为什么 CDI(使用 JAX RS)不能在 Open Liberty Server 中运行,但在 Payara Server 上运行良好?
Why is CDI (with JAXRS) not working in Open Libety Server but works fine on Payara Server?
我一直在尝试从 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()
return 在 Test.java post 构造函数中为 null。 为什么这种行为在 Open Liberty 而不是在 Payara 中? 此外,如果我不在 TestResources.java 文本方法中调用 test.getName()
而只是 return 一个随机字符串,我没有收到任何错误。 这引出了一个问题,@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 节配置,
Both the client and the server runtime configurations are available for injection via @Context. These configurations are available for injection in providers (client or server) and resource classes (server only).
该规范不要求 CDI bean 支持特定的 JAX-RS @Context
注释,仅支持资源和提供程序。
似乎 Payara 超出了规范,并支持 CDI bean 上的 @Context
注释。
我一直在尝试从 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()
return 在 Test.java post 构造函数中为 null。 为什么这种行为在 Open Liberty 而不是在 Payara 中? 此外,如果我不在 TestResources.java 文本方法中调用 test.getName()
而只是 return 一个随机字符串,我没有收到任何错误。 这引出了一个问题,@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 节配置,
Both the client and the server runtime configurations are available for injection via @Context. These configurations are available for injection in providers (client or server) and resource classes (server only).
该规范不要求 CDI bean 支持特定的 JAX-RS @Context
注释,仅支持资源和提供程序。
似乎 Payara 超出了规范,并支持 CDI bean 上的 @Context
注释。