Guice Hello World

March 12, 2007

A new project called Guice (pronounced Juice, but starts with a G instead of J because it's Googlerrific) has been created. Guice aims to be a better Dependency Injection (DI) framework for Java. The de facto DI framework for Java is currently Spring. Spring provides a lot of things besides DI, but I think DI is it's main selling point. I often use Spring in projects only for it's DI. I use Stripes as my Web MVC framework and Hibernate as my ORM framework, so I don't need Spring's MVC layer or JDBC Template. I do use Spring's declarative transaction management and hibernate configuration features, but that's only because once you start using Spring for DI, it's easy to use those features as well, but they could be easily replaced.

The main disadvantage of Spring, in my opinion, is the amount of XML files that you have to create to configuration you application. The thing I dislike most about the XML configuration is that it is not type safe, and just like Bob Lee says:

I'm using a strongly typed language; why would I want to throw all of this perfectly good type information away? If I wanted that, I'd use Ruby.

I don't think he meant that statement as a knock against Ruby, he's just saying that if you are programming in Java, then you want to use type safety as much as possible. Annotations and Generics, features added to Java in Java 5, can allow you to do that, and Guice aims to provide dependency injection via Annotations rather than XML.

So I decided to take a look at Guice, and although the documentation is pretty good, it doesn't have a working "Hello World" type example to get you going, so I figured I would provide one here. I encourage you to play along at home.

First, download Guice, setup a new project in your favorite IDE, and add guice-1.0.jar to your classpath. What we're going to do is create a basic domain model object, Foo, and a DAO-like Manager for Foo, and then create a controller that depends on the FooManager, and has that dependency set using Guice. So here we go. Create the Foo class:

public class Foo {

    private Long id;
    private String name;

    //Generate and getters/setters in your IDE

}

Then create the interface for the FooManager:

public interface FooManager {

    public Foo get(Long id);
    public void save(Foo foo);

}    

Then create an implementation of the FooManager. In real life, you might implement this with an ORM framework like Hibernate, but this simple little thing serves the purpose for this example:

public class FooManagerImpl implements FooManager {

    private static Long fooSequence = 1l;
    private static final Map<Long, Foo> foos = new HashMap<Long, Foo>();

    public Foo get(Long id) {
        return foos.get(id);
    }

    public void save(Foo foo) {
        if(foo == null) return;
        if(foo.getId() == null) {
            foo.setId(fooSequence);
            fooSequence++;
        }
        foos.put(foo.getId(), foo);
    }
}

And for the last part of our app, we'll create a controller that calls our manager. This controller is sort of like what a controller in a web app might be like:

public class FooController {

    private FooManager fooManager;

    //----- Controller Actions -------------------------------------------------
    public Foo create(String name) {
        Foo foo = new Foo();
        foo.setName(name);
        fooManager.save(foo);
        return foo;
    }

    public Foo retrieve(Long id) {
        return fooManager.get(id);
    }

    //----- Getters/Setters ----------------------------------------------------
    public FooManager getFooManager() {
        return fooManager;
    }

    @Inject
    public void setFooManager(FooManager fooManager) {
        this.fooManager = fooManager;
    }

}

You can see that with the annotation Inject on the fooManager setter, we are asking Guice to inject a fooManager instance into our controller. Continuing with the web app like architecture of our app, we'll create a dispatcher. In a real app, this would be the FrontController responsible for directing the request to be handled by the appropriate controller action, but for our simple app, we'll just hard code 2 controller action methods to be called:

public class FooDispatcher {

    public static void main(String[] args) {

        FooController controller = new FooController();
        Injector injector = Guice.createInjector(new FooModule());
        injector.injectMembers(controller);

        //Our action is now injected with a FooManager, so let's use it
        Foo foo = controller.create("Bar");
        Foo bar = controller.retrieve(foo.getId());
        System.out.println("bar.name => "+bar.getName());

    }

}

As you can see here, we've now got some Guice specific code. First we create an injector using the FooModule. The FooModule is a class we create that serves as the configuration for Guice, we'll get to that in a minute. The creation of this injector is something that you would do once, probably upon application startup. Then, we ask the injector to inject our controller instance with its dependencies. The simple Inject annotation we added on the setFooManager method of our controller is all the info the injector needs to set up our controller. Next you see we call 2 action methods, one to create a new Foo instance, and then another to retrieve it.

So let's look at the FooModule, which is where we do our Guice configuration:

public class FooModule extends AbstractModule {

    protected void configure() {
        bind(FooManager.class)
            .to(FooManagerImpl.class)
            .in(Scopes.SINGLETON);
    }

}

What this says is that when something needs a FooManager injected into it, use a singleton instance of FooManagerImpl to fulfill that dependency. We can actually use annotations to further simplify this configuration. First, we add the ImplementedBy annotation to the FooManager interface:

@ImplementedBy(FooManagerImpl.class)
public interface FooManager {

    public Foo get(Long id);
    public void save(Foo foo);

}

This basically says to Guice that we want FooManagerImpl to be the default implementation class for FooManager. Also, we can specify that by default we want FooManagerImpl to be a singleton:

@Singleton
public class FooManagerImpl implements FooManager {

    private static Long fooSequence = 1l;
    private static final Map<Long, Foo> foos = new HashMap<Long, Foo>();

    public Foo get(Long id) {
        return foos.get(id);
    }

    public void save(Foo foo) {
        if(foo == null) return;
        if(foo.getId() == null) {
            foo.setId(fooSequence);
            fooSequence++;
        }
        foos.put(foo.getId(), foo);
    }
}

Now, we can modify our module to look like this:

public class FooModule extends AbstractModule {

    protected void configure() {
        bind(FooManager.class);
    }

}

An now when we re-run our FooDispatcher, every thing still works. In real life, there would be some core mechanism in the web app framework to handle creating the injector and injecting dependencies into the controller instances, and I'm sure it would be fairly trivial to implement that into Stripes.

Although some people don't think Guice is going to replace Spring, I think for projects where Spring is being used mostly for DI, we will see Guice or something like it start to replace Spring. I also predict that in response to this, Spring will be forced into incorporating an annotation-based configuration mechanism into its core codebase in order to remain popular in the oncoming wave of Annotation based "zero" configuration frameworks like Stripes, Struts 2 and Hibernate.

UPDATE: Monday, March 12, 5:18pm

Thanks to a tip from Bob, I've discovered that once you have every thing configured by annotations, as we do at the end of this example, you can completely remove the FooModule, which gives you the code like this in the dispatcher:

public class FooDispatcher {

    public static void main(String[] args) {

        FooController controller = new FooController();
        Injector injector = Guice.createInjector();
        injector.injectMembers(controller);

        //Our action is now injected with a FooManager, so let's use it
        Foo foo = controller.create("Bar");
        Foo bar = controller.retrieve(foo.getId());
        System.out.println("bar.name => "+bar.getName());

    }

}

The point is that for any class that you can configure with annotations, you don't need to explicitly define them in a module, or anywhere. So take an app with 50 different manager classes, all you would have to do is create a manager interface, annotate it as a singleton, and then create the default implementation. Compare that with a minimum of 50 bean entries in a Spring context configuration XML file, and you can see how Guice can really start to simplify your configuration.

Posted in Technology | Tags Spring, Hibernate, Stripes, Java, DependencyInjection, Guice

Comments

1.

Thankyou very much for this nice article.

# Posted By Shailendra Pandey on Tuesday, March 13 2007 at 2:38 AM

2.

Great article...Would like to use Guice with Wicket, see how it is to have a Wicket-Juice like Wicket-Spring

# Posted By Atul Singh on Tuesday, March 13 2007 at 6:08 AM

3.

Great. Now I can really test Guice.
A friend tell me that it is better than Spring (well, just read about the Annotation Vs. XML file, I think I quite agree).
www.miraclesofislam.com

# Posted By Eko SW on Thursday, March 15 2007 at 11:35 AM

4.

Nice one for getting people (like me) started with Guice. Thanks!

Rgds,
Peter

# Posted By PeeWee on Friday, March 16 2007 at 8:36 AM

5.

Any idea of how FooDispatcher look like if FooController uses constructor injection instead of setter injection?

# Posted By Wesslan on Friday, March 16 2007 at 10:06 AM

6.

"Any idea of how FooDispatcher look like if FooController uses constructor injection instead of setter injection?"

public class FooDispatcher {

public static void main(String[] args) {

Injector injector = Guice.createInjector(new FooModule());
injector.getInstance(FooController.class); // this line is for Constructor Injection

}
}

# Posted By FrancisM on Sunday, March 18 2007 at 9:38 AM

7.

Isn't the reason you can perform the code removal from FooModule due to the fact that you are using the default implementation specified in the @ImplementedBy annotation?

So to inject some arbitrary implementation (FooManagerImplTest) you would need to keep this example in its original form?

# Posted By Tony on Saturday, March 24 2007 at 4:05 PM

8.

@Tony

Yes

# Posted By Paul Barry on Sunday, March 25 2007 at 9:36 AM

9.

Thanks a lot for the nice example!
I have one question - how would you go about packaging all artifacts? Say, if I wanted to have separate interfaces, implementations and consumer (client) JARs - where would you put the Module in and what would be the (classpath) dependencies between the jars? Further, what would be the best practice for swapping implementations with minimal disruption on the client side, thus providing a true transparency of which implementation is currently used?

# Posted By Marina on Wednesday, March 28 2007 at 1:41 PM

10.

Thanks for the quick intro. As you say Guice is only meant to provide IoC. For those coming to it from a Spring background this means things such as HibernateDaoSupport and HibernateTemplate are lost, along with the correct session injection and transactional demaraction. What strategies are there for dealing with this? I have not found a larger working example of Guice with Hibernate.

# Posted By Martin on Wednesday, April 25 2007 at 5:06 PM

11.

@Martin

My project is using Guice with Hibernate and Webwork. We have very simple transaction needs. We declare an interceptor stack for requests that need transactions. In that stack, we have an interceptor that starts a txn, passes control, then does a commit or rollback as appropriate, protected by a finally block.

If you have more sophisticated txn needs,

For classes that need Hibernate sessions, we either inject the Session through guice or inject a Provider. You need a Provider if the object you're injecting into has a lifetime that exceeds the life of a Session.

For example, we have long-lived Hibernate Daos that need Sessions, and we inject Provider into the daos.

# Posted By JB on Wednesday, April 25 2007 at 8:23 PM

12.

@Maritn

To clarify my previous comments on Sessions, in order to inject a Session into a long-lived Dao, for example, you should set up a request-scoped binding from Session.class to your Provider. Then each time your Dao asks its Provider for a Session, you will get the Session that belongs to the current request.

This assumes a one-to-one relationship from Session to web request, which is what our app needs. If you have different needs, I imagine you could handle them with differnt scoping.

# Posted By JB on Wednesday, April 25 2007 at 8:36 PM

13.

This is a nice introduction to guice. I will have a look at it and see if its better than Spring as others claims.

# Posted By frank on Saturday, November 1 2008 at 9:47 AM

14.

Nice article,Thanks Paul...
I have one question, if FooManager interface is implemented by more than one class FooManagerImpl and fooImpl...then how will i map these 2 classes.

# Posted By Daniel on Thursday, August 27 2009 at 10:50 AM

Comments Disabled