I want to use a DAO in my RESTful service developed with Jersey, so the DAO implementation should be injected via the constructor of the service:
@Path("eventscheduler)
public class EventSchedulerService {
private IEventSchedulerDao dao;
public EventSchedulerService(IEventSchedulerDao dao) { this.dao = dao; }
}
However, I know Jersey expects a default constructor to setup everything correctly. I have been trying to figure out how to do this for a while but surprisingly this seems to be an uncommon case, I wonder how people inject DAOs into their services, or deal with injection in general at all.
How can I do this?
If you're using Jersey 2, it uses HK2 as it's DI framework. All resource classes go through the DI lifecycle when they are constructed. And constructor injection is not a problem.
The most basic way (with Jersey) to make an arbitrary object injectable, is to bind in an AbstractBinder
public class Binder extends AbstractBinder {
@Override
protected void configure() {
bind(EventSchedudlerDaoImpl.class).to(EventSchedulerDao.class);
}
}
Then register the binder with Jersey
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(new Binder());
}
}
Then you just need to declare the injection point by adding @Inject
on top of the constructor.
@Inject
public EventSchedulerService(EventSchedulerDao dao) {
this.dao = dao;
}
As far as the binder implementation, the binding syntax basically reads as
bind( Implementation ).to( Contract ).in( Scope );
The bind
method can take an instance or it can take a class. When you provide an instance, the Scope is automatically Singleton.
The to
method specifies the advertised contract, which is the type that can be declared at the injection point. In this case, only the interface EventSchedulerDao
can be used for the injection point. If you don't have an interface you can just do
bindAsContract(EventSchedulerDao.class)
assuming EventSchedulerDao
is the implementation class.
The scopes available are PerLookup
, RequestScoped
and Singleton
. If not specified, the default scope will be PerLookup
, meaning a new instance of the service will be created for each injection point. You should already know what Singleton
means. RequestScoped
means that a new instance will be created for each request, which may not be the same as PerLookup
, as the service may be injected at multiple points through out the request lifeclyle.
See Also:
- Dependency injection with Jersey 2.0
- Custom Injection and Lifecycle Management
- hk2 tagged questions. Alot of them are Jersey related.
You must annotate the class constructor (or the property itself) with javax.inject.Inject
.
import javax.inject.Inject;
class EventSchedulerResource {
private final IEventSchedulerDao dao;
@Inject
public EventSchedulerResource(IEventSchedulerDao dao) {
this.dao = dao;
}
// ...
}
If the IEventScheduler
is an interface you must create a configuration class class that extends org.glassfish.jersey.server.ResourceConfig
and register the binding of interface to a concrete implementation with bind(EventSchedulerDaoImpl.class).to(IEventScheduler.class)
(See here: https://jersey.java.net/documentation/latest/ioc.html chapter 23.1)