I used to integrate Service and DAO beans in Jersey REST resources by annotating them with @Path following Java EE tutorial
In general, for JAX-RS to work with enterprise beans, you need to annotate the class of a bean with @Path to convert it to a root resource class. You can use the @Path annotation with stateless session beans and singleton POJO beans.
So my code used to be something like this:
@Path("/")
public class ServiceResource {
@Inject
private AccountService accountService;
@GET
@Path("/account/get")
public Account getAccount(@QueryParam("id") String id) {
return accountService.get(id);
}
}
@javax.inject.Singleton
@Path("")
public class AccountService {
public Account get(String id){...}
}
Now, I started integrating a Quartz Job into my application, and I wanted to find a way to inject my AccountService inside a job like this
public class AccountJob implements Job {
@Inject
private AccountService accountService;
@Override
public void execute(JobExecutionContext jec) throws JobExecutionException {
accountService.updateAllAccounts();
}
}
I found this answer that tells to use DeltaSpike to do the Job, so I added the following dependencies to my pom.xml, and without adding any more lines of code to any class the inejection of accountService to my Job works fine
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-scheduler-module-api</artifactId>
<version>1.7.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-scheduler-module-impl</artifactId>
<version>1.7.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.cdictrl</groupId>
<artifactId>deltaspike-cdictrl-api</artifactId>
<version>1.7.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.cdictrl</groupId>
<artifactId>deltaspike-cdictrl-weld</artifactId>
<version>1.7.2</version>
<scope>runtime</scope>
</dependency>
However, I realized that when I remove the @Path("") from AccountService, its instance is still injected fine inside ServiceResource, so my questions are the following:
- Why adding
DeltaSpikedependencies made it possible to inject my beans without using@Pathon them? - By searching more, I understood that
DeltaSpikeinternally usesWeldto do the injection, and since I am already usingGlassFish 4.0, I know thatWeldis already there, so why the injection is not working by default in myJobclass and inServiceResourceclass without adding@Pathon my beans? Actually why adding@Pathis even suggested in the Java tutorial? - Is there any bad side effects that I don't see in my code, because I think that I am mixing multiple DI methods here without really understanding how do they work?
Update: After more search, I realize that Jersey doesn't use Weld for dependency injection, instead it uses HK2, a different framework that also happens to be a part of GlassFish, when I try to inject AccountService without using @Path it shows the following exception
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=AccountService,parent=ServiceResource,qualifiers={}...
So this updates the questions to the following:
- How to make
HK2injections works? // Without using@Pathas mentioned in the Java EE Tutorial - If I managed to to do
DIwithHK2, will it be safe to useDeltaSpiketo doDIfor the Quartz Job? Is it okay to mix two CDI framewroks together to scan the classes and do the injection?
I put my my source code on pastebin; pom.xml is here and the Java is here