Skip to content
This repository has been archived by the owner on Feb 9, 2019. It is now read-only.

JedisPool is null when trying to inject in another class than the controllers #157

Open
johdah opened this issue Jul 9, 2015 · 6 comments

Comments

@johdah
Copy link

johdah commented Jul 9, 2015

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;
    }
}
@ronaldwidha
Copy link

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

@johdah
Copy link
Author

johdah commented Jul 16, 2015

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?

@ronaldwidha
Copy link

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

ronaldwidha added a commit to ronaldwidha/play-plugins that referenced this issue Jul 17, 2015
For Play 2.4.2, the current readme causes an exception to be thrown upon setting up @Inject on JedisPool. The correct dependency is play-plugin-redis 2.4.1 see playframework#156 and playframework#157
@mmadian
Copy link

mmadian commented Aug 19, 2015

i tried the solution but still gives me null.

@ronaldwidha
Copy link

@mmadian why dont you share some code

@johdah
Copy link
Author

johdah commented Aug 20, 2015

@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);

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants