views:

85

answers:

3

Hi,

I'm creating a library that will be included as a jar, so it won't contain a main method. I'm wondering what is the best practice for bootstrapping Guice in this case. I have one top level singleton.

public class TestManager
{
    private TestManager()
    {
    }

    public static TestManager getInstance()
    {
        // construct and return singleton
    }

    public void createSomeObjects()
    {
    }

}

Where should I bootstrap Guice? I was thinking that in the constructor that I could call Guice.createInjector(new Module()); but it wouldn't inject any of the objects created in createSomeObjects().

Is there a common way to do this when you don't have a main method()?

Cheers.

+7  A: 

Much like logging configurations, if this is a true library then your options are pretty much this:

  • Tell the library user that they are responsible for bootstrapping Guice themselves.
  • Provide a library initialization method that takes care of bootstrapping Guice if they want to use your library

Trying to make the library super-smart to do self-configuration often ends up with somewhat inflexible, hard to test class hierarchies.

Ophidian
Giving your clients a Guice module might work nicely.
Jesse Wilson
+1 for super-smart self-configuration. Just think of how bad it went with Apache Commons Logging.
Thorbjørn Ravn Andersen
A: 

This is not what you should do, but what you could do:

Let key classes in your library extend or otherwise reference a class that initializes everything in a static block. This is a very dirty hack, but if you make sure your api can't be accessed without the classloader loading your initializer class you should be on the safe side.

You could make it a bit cleaner if you used AspectJ and injected a private Member of the initializer type into all classes in your library (without touching the java code), but it would still be a hack.

seanizer
A: 

If you're just using Guice in the scope of your library and not for the whole application then you could use a static block in the TestManager class.

This strategy assumes that the application is going to call TestManager.getInstance() at some point and that it is the only entry point into your API.

@Singleton
class TestManager {

  private static final TestManager INSTANCE;

  static {
    INSTANCE = Guice.createInjector(new Module()).getInstance(TestManager.class);
  }

  private TestManager() {
  }

  public static TestManager getInstance() {
      return INSTANCE;
  }

  @Inject
  public void createSomeObjects(YourDependencies ...) {
     // Do something with dependencies
  }
}
hallidave