1
votes

I have one Maven module where I define some utils shared across several other Maven modules. In this module I want to create some singleton:

package org.me.util;

public interface Baz {
    String myMethod(String s);
}

@Singleton
public class Foo implements Baz {
private Bar bar;

    @Inject
    Foo(Bar bar) {
        this.bar = bar;
    }

    @Override
    public String myMethod(String s) {
        return s;
    }

}

Then I bind my interface with:

public class MyModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(Baz.class).to(Foo.class);
    }

}

Suppose I want to use this singleton from another Maven module (say, a web service), how do I achieve this? The only way I found was to create a class in my util Maven module like:

package org.me.util;
public class Main {

    private static Injector injector = Guice.createInjector(new MyModule());;

    public static Injector getInjector() {
        return injector;
    }

Alternatively I could create the injector in a static main method as seen in the Guice tutorials, and save an instance somewhere.

Then from my web service do something like:

Baz baz = Main.getInjector().getInstance(Baz.class);    

But this does not seem very elegant because I have to pass my injector around (in this case by providing it with a static getter).

Is there any other way? Thanks.

1
Ideally you'd also inject whatever is in the other module. Can you @Inject Baz baz and then get an instance of whatever needs Baz from the injector? - condit
I am not sure I follow you. I am doing my first steps with Guice and DI. But isn't it bad practice to inject fields like @Inject Baz baz? Anyway I don't understand how am I supposed to get an instance of my singleton without using the injector. - dmz73
Right - you could also inject into the constructor of your other class. All I'm saying is that you should @Inject your singleton where you need it, if possible. Guice can only help you if it's creating the objects. - condit

1 Answers

1
votes

The more elegant way to pass the Baz object it's to inject it.

For example,

 public class BusinessService {
     private final Baz baz;
     @Inject
     public BusinessService(Baz baz) { this.baz = baz; }
 }

And again if you want to use the BusinessService in a WS.

 public class WebService {
     private final BusinessService businessService;
     @Inject
     public WebService(BusinessService businessService) { this.businessService = businessService; }
 }

By doing this, all the dependency are clearly exposed in the API signatures.


The remaining problem is that you have to create the Injector in the entry point of an application.

In a standalone application, the injector is usually created in the main method.

public static void main(String[] args) {
     Injector injector = Guice.createInjector(new UtilModule(), new BusinessModule());
     BusinessService businessService = injector.getInstance(BusinessService.class);
     ...

}

In a web application, the injector might be created in different way. It depends of the framework.

Servlets:

Dropwizard:

playframework

...