JedisPool is null when trying to inject in another class than the controllers
I am able to inject the JedisPool in my controllers but not in models, daos or other classes. An example is in my UserDAO. Isn't this supported or why does the exact same code work in the Application controller?
...
import javax.inject.Inject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class UserDAO extends AbstractDAO<User, User_> {
@Inject JedisPool jedisPool;
public UserDAO() {
super(User.class, User_.class);
}
/**
* @return an instance of {@link UserDAO}.
*/
public static UserDAO newInstance() {
return new UserDAO();
}
...
// -- Redis
/**
* Get the last time the user accessed the service.
*
* @param user the {@link models.User}
* @return the last time as a {@link org.joda.time.DateTime}
*/
public DateTime getLastAccess(User user) {
if(jedisPool == null) {
Logger.error("Redis is not available");
return null;
}
Jedis j = jedisPool.getResource();
DateTime dateTime = null;
try {
String dtString = j.hget("userLastAccess", user.id.toString());
dateTime = new DateTime(Long.valueOf(dtString));
} catch(NumberFormatException ex) {
dateTime = null;
} finally {
jedisPool.returnResource(j);
}
return dateTime;
}
}
In order for @Inject to work elsewhere, that class need to also participate in the dependency injection tree. Play2 uses Guice internally so this is what you need to do:
In application.conf:
play.modules.enabled += "modules.yourModule"
create a new class your module:
package modules;
import com.google.inject.AbstractModule;
public class yourModule extends AbstractModule {
@Override
protected void configure() {
//add configuration logic here
bind(yourDaoInterface.class).to(yourDaoImplementationClass.class);
}
}
This way when your Dao class is instantiated by Guice, it'll look through all annotations and inject the Dao's dependencies as needed.
If you need to learn more about Dependency Injection in general or Guice in particular, watch Bob Lee's video on Guice
So I need to create an interface for every DAO class I have and then create a DAOModule where I add a bind for every DAO class?
Yes. The module is application-wide as far as I know, where all your binding lives. Not just for the DAOs but any other class where you want to use Guice @inject
i tried the solution but still gives me null.
@mmadian why dont you share some code
@mmadian The problem is likely that you don't inject the class because then it doesn't matter if you have an @Inject. Here is my working code:
UserDAO:
public class UserDAO extends AbstractDAO<User, User_> {
JedisPool jedisPool;
@Inject
public UserDAO(final JPAApi jpaApi, JedisPool jedisPool) {
super(jpaApi, User.class, User_.class);
this.jedisPool = jedisPool;
}
/**
* Get the last time the user accessed the service.
*
* @param user the {@link models.User}
* @return the last time as a {@link org.joda.time.DateTime}
*/
public DateTime getLastAccess(User user) {
if(jedisPool == null) {
Logger.error("UserDAO - getLastAccess - Redis is not available");
return null;
}
Jedis j = jedisPool.getResource();
DateTime dateTime = null;
try {
String dtString = j.hget("userLastAccess", user.id.toString());
dateTime = new DateTime(Long.valueOf(dtString));
} catch(NumberFormatException ex) {
dateTime = null;
} finally {
jedisPool.returnResource(j);
}
return dateTime;
}
}
And then you load UserDAO like this:
UserDAO userDAO = play.Play.application().injector().instanceOf(UserDAO.class);