我一直在尝试从Payara服务器切换到Open Liberty,但是我遇到了一个问题:我的代码在Payara上运行良好,但在Open Liberty上运行不好。这是说明问题的最简单的代码测试:
ApiEntryPoint.java
@ApplicationPath("/v1")
public class ApiEntryPoint extends Application {
@Override
public Map<String, Object> getProperties() {
Map<String, Object> props = new HashMap<String, Object>();
props.put("name", "This is my name");
return props;
}
}
Test.java
@ApplicationScoped
public class Test {
@Context
private Configuration configuration;
private String name;
@PostConstruct
private void init() {
name = (String) configuration.getProperties().get("name");
}
public String getName() {
return name;
}
}
TestResources.java
@Path("/test")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@RequestScoped
public class TestResources {
@Inject
private Test test;
@GET
public String test(@Context HttpHeaders headers, @PathParam("id") int id) {
return test.getName();
}
}
您可能会猜到,此代码在Payara服务器上有效,当我尝试在Open Liberty服务器上运行它时,出现以下错误:
[err] org.jboss.weld.exceptions.WeldException: WELD-000049: Unable to invoke private void com.domain.test.Test.init() on com.domain.test.Test@74caba3d
[err] at org.jboss.weld.injection.producer.DefaultLifecycleCallbackInvoker.invokeMethods(DefaultLifecycleCallbackInvoker.java:85)
[err] at [internal classes]
[err] at com.domain.test.Test$Proxy$_$$_WeldClientProxy.getName(Unknown Source)
[err] at com.domain.test.TestResources.test(TestResources.java:25)
[err] at com.domain.test.TestResources$Proxy$_$$_WeldClientProxy.test(Unknown Source)
[err] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[err] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[err] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[err] at java.lang.reflect.Method.invoke(Method.java:498)
[err] at com.ibm.ws.jaxrs20.server.LibertyJaxRsServerFactoryBean.performInvocation(LibertyJaxRsServerFactoryBean.java:656)
[err] at [internal classes]
[err] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[err] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[err] at java.lang.Thread.run(Thread.java:748)
[err] Caused by: java.lang.reflect.InvocationTargetException
[err] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[err] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[err] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[err] at java.lang.reflect.Method.invoke(Method.java:498)
[err] at org.jboss.weld.injection.producer.DefaultLifecycleCallbackInvoker.invokeMethods(DefaultLifecycleCallbackInvoker.java:83)
[err] ... 64 more
[err] Caused by: java.lang.NullPointerException
[err] at com.domain.test.Test.init(Test.java:18)
[err] ... 69 more
最后一个异常告诉我configuration.getProperties()
在Test.java的post构造函数中返回null。 为什么在Open Liberty中表现不这样,而在Payara中却没有?另外,如果我没有在TestResources.java文本方法中调用test.getName()
并仅返回一个随机字符串,则不会出现任何错误。 这引起了@PostConstructor方法何时被调用的问题?我认为在Bean完全初始化时它会被调用,并且应该在TestResources.java中执行测试方法之前发生。我在这里缺少什么吗?
请注意,我在maven中使用的唯一依赖项是具有提供范围的完整jakartaee-8。
server.xml
<server description="new server">
<featureManager>
<feature>jakartaee-8.0</feature>
<feature>localConnector-1.0</feature>
</featureManager>
<keyStore password="mypassword"/>
<basicRegistry id="basic" realm="BasicRealm">
<user name="username" password="mypassword"/>
</basicRegistry>
<httpEndpoint httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>
<applicationManager autoExpand="true"/>
<ssl id="defaultSSLConfig" trustDefaultCerts="true"/>
<applicationMonitor updateTrigger="mbean"/>
<webApplication id="test" location="test-0.0.1-SNAPSHOT.war" name="test"/>
</server>
根据我的最初回答,我认为这是OpenLiberty的错误,但是根据JAX-RS 2.1规范的10.2.8节,
客户端和服务器运行时配置均可通过@Context注入。这些配置可用于注入提供程序(客户机或服务器)和资源类(仅服务器)。
该规范没有要求CDI bean支持特定的JAX-RS @Context
批注,仅支持资源和提供程序。
[Payara似乎超出了规范,并支持CDI bean上的@Context
注释。