Search code examples
javadependency-injectionguice

Google Guice Inject Member not working


I'm creating a new project using GoogleGuice as DI.

So i create an interface of my DAO:

public interface UserDAO extends DAO<User> {

    // Some CRUD methods

}

and an implementation of that:

public class UserDAOImpl implements UserDAO {

     // CRUD Methods implementation

}

This is my ApplicationModule class:

public class ApplicationModule extends AbstractModule {

    @Override
    protected void configure() {

        // Tried swap the order without results
        bind(UserDAO.class).in(Singleton.class);
        bind(UserDAO.class).to(UserDAOImpl.class);

    }

}

On my UserService I try this:

@Inject
private UserDAO dao;

But my dao is allways null. And, when I call Guice.createInjector(new ApplicationModule()) on UserService constructor, I got the following stack trace:

Servlet.service() for servlet [Jersey REST Service] in context with path [/simple-rest-application] threw exception [A MultiException has 2 exceptions.  They are:
1. com.google.inject.CreationException: Unable to create injector, see the following errors:

1) No implementation for br.com.brunots.training.simple_rest_application.dao.UserDAO was bound.
  Did you mean?
    br.com.brunots.training.simple_rest_application.dao.UserDAO bound  at br.com.brunots.training.simple_rest_application.guice.ApplicationModule.configure(ApplicationModule.java:15)

  at br.com.brunots.training.simple_rest_application.guice.ApplicationModule.configure(ApplicationModule.java:14)

2) A binding to br.com.brunots.training.simple_rest_application.dao.UserDAO was already configured at br.com.brunots.training.simple_rest_application.guice.ApplicationModule.configure(ApplicationModule.java:15).
  at br.com.brunots.training.simple_rest_application.guice.ApplicationModule.configure(ApplicationModule.java:14)

2 errors
2. java.lang.IllegalStateException: Unable to perform operation: create on br.com.brunots.training.simple_rest_application.services.UserService
] with root cause
com.google.inject.CreationException: Unable to create injector, see the following errors:

1) No implementation for br.com.brunots.training.simple_rest_application.dao.UserDAO was bound.
  Did you mean?
    br.com.brunots.training.simple_rest_application.dao.UserDAO bound  at br.com.brunots.training.simple_rest_application.guice.ApplicationModule.configure(ApplicationModule.java:15)

  at br.com.brunots.training.simple_rest_application.guice.ApplicationModule.configure(ApplicationModule.java:14)

2) A binding to br.com.brunots.training.simple_rest_application.dao.UserDAO was already configured at br.com.brunots.training.simple_rest_application.guice.ApplicationModule.configure(ApplicationModule.java:15).
  at br.com.brunots.training.simple_rest_application.guice.ApplicationModule.configure(ApplicationModule.java:14)

2 errors

Someone knows what's happening? What I'm missing?


Solution

  • Basically your issue is that you're trying to bind an interface to a singleton without providing any implementation. Then in your "answer", you actually do something better: you provide an interface with an implementation, then you say that your implementation is a singleton. But then you fail to actually make the UserDAO an effective singleton because you create a new injector for each UserService.

    Try the following:

    ApplicationModule.java

    public class ApplicationModule extends AbstractModule {
      @Override protected void configure() {
        bind(UserDAO.class)       // Define UserDAO 
          .to(UserDAOImpl.class)  // as implemented by UserDAOImpl
          .in(Singleton.class);   // and make it a singleton.
      }
    }
    

    UserService.java

    public class UserService {
      private final UserDAO userDAO;
      @Inject UserService(UserDAO userDAO) { // Actually inject your UserDAO!!
        this.userDAO = userDAO;
      }
    }
    

    Main.java

    public class Main {
      public static void main(String[] args) {
        Injector injector = Guice.createInjector(new ApplicationModule());
        UserService userService = injector.getInstance(UserService.class);
      }
    }