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
DeltaSpike
dependencies made it possible to inject my beans without using@Path
on them? - By searching more, I understood that
DeltaSpike
internally usesWeld
to do the injection, and since I am already usingGlassFish 4.0
, I know thatWeld
is already there, so why the injection is not working by default in myJob
class and inServiceResource
class without adding@Path
on my beans? Actually why adding@Path
is 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
HK2
injections works? // Without using@Path
as mentioned in the Java EE Tutorial - If I managed to to do
DI
withHK2
, will it be safe to useDeltaSpike
to doDI
for 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