Search code examples
javadependency-injectionjax-rscdipayara

Is bean-discovery-mode="all" required to @Inject a bean into a Jersey @Path JAX-RS resource?


I am using Payara 4.1.1.161. I have a Jersey @Path JAX-RS resource and all I want to do is @Inject a bean into it using CDI. I've tried lots of different combinations to get this to work, but so far the only way I've gotten it to work successfully is to set bean-discovery-mode="all" in beans.xml.

I know that "annotated" is the preferred mode with no beans.xml even more prefered. But every time I've tried to use "annotated" I've either had a failure calling the JAX-RS resource which look like this:

MultiException stack 1 of 1
org.glassfish.hk2.api.UnsatisfiedDependencyException: 
There was no object available for injection at
SystemInjecteeImpl(requiredType=InjectMe, parent=InjectResource,
qualifiers={}, position=-1, optional=false, self=false,
unqualified=null, 1000687916))

Or I've had a failure deploying the application which looks like this:

Exception during lifecycle processing
java.lang.Exception: java.lang.IllegalStateException:
ContainerBase.addChild: start: org.apache.catalina.LifecycleException:
org.apache.catalina.LifecycleException:
org.jboss.weld.exceptions.DeploymentException: WELD-001408: 
Unsatisfied dependencies for type InjectMe with qualifiers @Default
at injection point [BackedAnnotatedField] 
@Inject private org.thoth.jaspic.web.InjectResource.me

Here is my application setup.

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="all">
</beans>

JAX-RS Application

@javax.ws.rs.ApplicationPath("webresources")
public class ApplicationResourceConfig  extends org.glassfish.jersey.server.ResourceConfig {
    public ApplicationResourceConfig() {
        register(RolesAllowedDynamicFeature.class);
        registerClasses(
            org.thoth.jaspic.web.InjectResource.class
        );
     }
 }

JAX-RS Resource

@Path("inject")
public class InjectResource {
    @Inject
    private InjectMe me;

    @GET
    @Produces(MediaType.TEXT_HTML)
    public String getText(@Context SecurityContext context) {
        Principal p = context.getUserPrincipal();
        String retval = "<h3>inject</h3>";
        retval += String.format("<p>me=[%s]</p>", me);
        return retval;
    }
}

Simple bean I want to inject

public class InjectMe implements Serializable {

    private static final long serialVersionUID = 158775545474L;

    private String foo;

    public String getFoo() {
        return foo;
    }

    public void setFoo(String foo) {
        this.foo = foo;
    }
 }

Again, if I have my application as shown with the configuration above and with bean-discovery-mode="all" everything seems to be OK and the application deploys without error and when calling the JAX-RS service the bean gets injected without error. But when I switch to bean-discovery-mode="annotated" OR if I have no beans.xml file at all then things go horribly wrong.

So can you @Inject a bean into a Jersy @Path JAX-RS resource running Payara 4.1.1.161 with either no beans.xml or with bean-discovery-mode="annotated"?


Solution

  • Your JAX-RS resource class needs to have a bean defining annotation to enable injection of the CDI bean. Just add @ApplicationScoped or @RequestScoped to your JAX-RS resource and bean injection should then work without bean discovery mode of all.

    BTW I'm assuming the InjectMe bean also has a scope annotation of some form as it's not shown in the code above.

    For example;

    @Path("inject")
    @ApplicationScoped
    public class InjectResource {