I've got a subresource class which must be initialized with a parameter from the path and which also contains a reference to an EJB which must be injected.
Resource class:
@Path("widgets")
public class MasterResource{
@Inject
WidgetBean widgets;
@Context
ResourceContext rc;
@Path("{year}")
public WidgetArchives wArchives(@PathParam("year") String year){
return rc.initResource(new WidgetArchiveResource(year));
}
}
Subresource class
public class WidgetArchiveResource{
@Inject
WidgetBean widgets;
public WidgetArchiveResource(String year){
....code
}
@GET
public String doGet(){
....code using WidgetBean
}
}
When I invoke get with the year, I see the following error:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=WidgetBean,parent=WidgetArchiveResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,542790913)
I'm new to Java EE. What am I doing wrong?
The method rc.initResource makes sense only if you need to inject some dependencies into the resource (e.g. annotated by @Inject). This is a JAX-RS specific way to inject dependencies into a bean. It is deprecated in a full JavaEE environment where the preferred way to inject dependencies is via CDI. rc.initResource
does not inject all CDI beans (e.g. @EJB could work, but @Inject not).
Hence, in JavaEE, the preferred way to do what you want to achieve would be to inject WidgetArchiveResource
into parent MasterResource
. CDI beans must have constructor without arguments, but you may pass year using setter. If you put your master resouce in request scope, it will be recreated for every request, making it safe for concurrent requests:
@Path("widgets")
@RequestScoped
public class MasterResource{
@Inject
Instance<WidgetArchiveResource> waResources;
@Path("{year}")
public WidgetArchives wArchives(@PathParam("year") String year){
WidgetArchiveResource waResource = waResources.get();
waResource.setYear(year);
return waResource;
}
}
Also, you should either have beans.xml in your WEB-INF folder with bean-discovery-mode="all"
, or explicitly add dependent scope on your WidgetArchiveResource
to make it CDI eligible:
@Dependent
public class WidgetArchiveResource {
public WidgetArchiveResource() {} // optional no arg constructor
}