I'm using CDI in a Jersey app. On root resources, CDI injection works as expected, but whenever I return a sub-resource, the CDI injection sources are not available.
My root resource with sub-resource locator:
@Path("")
public class MyResource {
@Inject @Named("name") // works
private String name;
@Context
private ResourceContext context;
@Path("test2")
public Object test2() {
return MySubResource.class;
//return context.getResource(MySubResource.class); // this does not work either
}
}
The sub-resource:
public class MySubResource {
@Inject @Named("name") // error
private String name;
@GET
public Response test() {
return Response.ok("Name in sub resource: " + name).build();
}
}
Error:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=String,parent=MySubResource,qualifiers={@javax.inject.Named(value=name)},position=-1,optional=false,self=false,unqualified=null,1235803160)
I'm using org.glassfish.jersey.ext.cdi:jersey-cdi1x
and Weld dependencies, running on Undertow, with the Weld servlet listener added to the deployment.
Again, the same injection on the root resource does work. The @Named("name") String
is produced by an @ApplicationScoped
producer.
Is this not supposed to work? What am I missing?
Minimal example Maven project available here: https://gitlab.com/Victor8321/jersey-sub-resource-cdi
Note: An open issue for this exists, but not sure what the official stance on this is: https://java.net/jira/browse/JERSEY-3184
As pointed out in https://github.com/eclipse-ee4j/jersey/issues/3456, adding a dummy @Path("xyz")
to the sub-resource class is a "fix". However, that exposes your sub-resource under the dummy path.
Injecting an instance just through CDI works as well (@Inject Instance<MySubResource> ..
), but then Jersey-managed resources aren't available for injection, such as @Context HttpServletRequest
.
I've found 2 other approaches that fully work (both CDI injection and JAX-RS injection) and have no side effects (as with @Path
):
@Provider
.register()
the sub resource class in the ResourceConfig
(or Application
).Both approaches seem to work because they make Jersey - and in turn, CDI - aware of the class.
Note: I've updated my example project accordingly for future reference.