At the moment I'm using a static singleton to obtain the singleton service that Guice 3.0 builds for me through DI - I believe this a terrible hack and not at all the intended way to use Guice for DI, and complicates unit testing.

public class ServiceProvider {
    private static ServiceProvider instance = new ServiceProvider();    
    private MyService myService;

    public ServiceProvider() {      
        Injector myInjector = Guice.createInjector(new MyModule());
        myService = noobmeterInjector.getInstance(MyService.class);
    }

    public static MyService getMyService() {
        return instance.myService;
    }
}

However, I'm not quite sure how to fix that, as I need that service in at least four different spots:

  • Stripes ActionBeans - I think the Stripes Guice plugin would help me there, and I did connect it but ended up with multiple parallel MyServices
  • ServletContextListener - I think possibly the Guice Servlet module can help somehow, although I'm struggling with the documentation as it mostly discusses replacing web.xml with Guice configuration (not my priority at this point) and injecting HttpServletRequests into Guice-constructed objects (again not what I want to do)
  • Quartz Jobs - here I found something relevant, but not sure if it won't end up still creating a "parallel" MyService to the other ones
  • Batch processes run from command line - this is the easy part

The MyService service is intended to be a singleton (other services it owns open DB/MQ connections, etc., so creating multiple of these would be bad).

Is there some simple way how to do this in Guice that I'm missing?

1

There are 1 answers

5
moofins On

So there's a few issues with your code snippet.

  • You should no longer be implementing singletons as static variables; let Guice do the lifecycle management for you.
  • In this example, ServiceProvider is basically a Service Locator implementation, which is unnecessary since you're using Guice.
  • It's good practice to keep the Injector creation as "high" up as possible. The main method where your server starts would be a good place.

I've added some code to demonstrate.

public class Server {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new MyModule());
        // Your code here.
    }
}

public class MyModule extends AbstractModule {
    protected void configure() {
         // Assuming MyService implements Service
         bind(Service.class).to(MyService.class).in(Singleton.class);
    }
}