Search code examples
jakarta-eejax-rscdiopen-libertyjava-ee-8

Why is CDI (with JAXRS) not working in Open Libety Server but works fine on Payara Server?


I have been trying to switch from Payara server to Open Liberty, however I am faced with a problem: my code works well on Payara but does not work well on Open Liberty. Here is the simplest code test to illustrate the problem:

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();
    }
}

As you may guess, this code works on Payara server and when I try to run it on Open Liberty server, I get the following error:

[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

The last exception tells me the that configuration.getProperties() returns null in Test.java post constructor. Why is this behaving as such in Open Liberty and not in Payara? Also if I don't call test.getName() in TestResources.java text method and just return a random string, I am not getting any error. This begs the question when is @PostConstructor method called? I thought it gets called when the bean is fully initialized and this should happen before the test method executes in TestResources.java. Is there something that I am missing here?

Note that the only dependency I am using in maven is the full jakartaee-8 with a scope of provided.

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>

Solution

  • On my initial answer I assumed it was OpenLiberty's fault, but according to the JAX-RS 2.1 spec, section 10.2.8 Configuration,

    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).

    The spec doesn't mandate CDI beans to support specific JAX-RS @Context annotations, only resources and providers.

    It seems that Payara goes beyond the spec, and supports the @Context annotation on CDI beans.