【发布时间】:2020-08-02 22:29:48
【问题描述】:
我一直在尝试从 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 后构造函数中返回 null。 为什么在 Open Liberty 中而不是在 Payara 中出现这种行为?另外,如果我不在 TestResources.java 文本方法中调用 test.getName() 并且只返回一个随机字符串,我不会收到任何错误. 这引出了什么时候调用@PostConstructor 方法的问题? 我认为它会在bean 完全初始化时被调用,这应该发生在TestResources.java 中的测试方法执行之前。我在这里有什么遗漏吗?
请注意,我在 maven 中使用的唯一依赖项是完整的 jakartaee-8,其范围为提供。
服务器.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>
【问题讨论】:
-
Test.java:18、
configuration.getProperties()或configuration本身中的 究竟 是什么?您是说这是第一个,但是您是否在调试中仔细检查过?我问的原因是我觉得很奇怪 JAX-RS“资源”(Configuration)可用于在纯 CDI bean(即没有@Path注释的 bean)中注入。不过我没有在 JAX-RS 中使用过这个功能,所以我可能错了。 -
@NikosParaskevopoulos 是的,它是
configuration.getProperties(),我已经仔细检查了这一点。按照@areus 的回答,如果我用Application替换Configuration,configuration.getProperties()不会返回null,而是返回一个空地图。相信我,我对此感到很困惑。我不确定 JAX-RS 资源是否意味着注入纯 CDI bean。假设它不能注入到纯 CDI bean 中,那么为什么这与 Payara 服务器一起工作? -
嗯,我发现这两个系统的行为很奇怪:OpenLiberty 让我想知道为什么它会注入
Configuration却将其留空(或者,无论如何,不一致)? Payara 可能正在以自己的方式(诚然方便,但不可移植)解释规范的灰色区域(将 JAX-RS 工件注入“just CDI”bean)。我的意见:当您对规格有疑问时,您会经常遇到这种差异;如果官方规范中没有明确说明,使用它可能会导致可移植性问题,即使在同一服务器的版本之间也是如此!祝你好运! -
是的,你是对的!在@areus 更新之后,我已经阅读了规范并决定按照规范格式化我的代码。这是一个很好的教训,谢谢你们!
标签: jakarta-ee jax-rs cdi open-liberty java-ee-8