• Home
  • RSS Feed
  • Log in

Google Guice and Multibinding
Posted by Mischa Dasberg around lunchtime: December 21st, 2009

Last week I started migrating an application that used Spring for DI to Google Guice when I stumbled on multibinding.

Since Google Guice 2.0 we can use Multibinding which allows us to bind multiple objects to a collection.
But the one thing I missed in the current release is the ability to bind objects with a specific annotation. So I thought, why not build it myself :)


So lets use the Multibinder example written in the Javadoc of Multibinder.

public class SnacksModule extends AbstractModule {
    protected void configure() {
     Multibinder<ISnack> multibinder = Multibinder.newSetBinder(binder(), ISnack.class);
      multibinder.addBinding().toInstance(new Twix());
      multibinder.addBinding().toProvider(SnickersProvider.class);
      multibinder.addBinding().to(Skittles.class);
    }
  }

With this binding, a Set<ISnack> can now be injected:

  class SnackMachine {
    @Inject
    public SnackMachine(Set<ISnack> snacks) { ... }
  }

This is nice if you have a couple of Snacks, but if you have many and you want your
module clean and simple, you probably want something like this

 multibind(ISnack.class).toAnnotatedClasses(Snack.class);

Where a Snack looks like this:

 
@Snack
public class Snickers implements ISnack { ... }
 

To make this possible, I created the following Module:

public abstract class AbstractMultibindModule extends AbstractModule {
 
    public  AdvancedMultibinder multibind(Class clazz) {
        return new AdvancedMultibinder(clazz);
    }
 
    public class AdvancedMultibinder {
        private Multibinder multibinder;
        private Class clazz;
 
        private AdvancedMultibinder(Class clazz) {
            this.clazz = clazz;
            multibinder = Multibinder.newSetBinder(binder(), clazz);
        }
 
        public Multibinder toAnnotatedClasses(Class bindingAnnotation) {
            return toAnnotatedClasses(bindingAnnotation, clazz.getPackage().getName());
        }
 
        public Multibinder toAnnotatedClasses(Class bindingAnnotation, String basePackageName) {
            for (Class clazz : AnnotationUtil.getAnnotatedClasses(bindingAnnotation, basePackageName)) {
                multibinder.addBinding().to(clazz);
            }
            return multibinder;
        }
 
        public LinkedBindingBuilder addBinding() {
            return multibinder.addBinding();
        }
    }
}

As you can see the multibind method returns an AdvancedMultibinder. We cannot extend Multibinder because it has a private Constructor, so instead I use the multibinder internally and call methods on it to add bindings.

The AdvancedMultibinder has a method toAnnotatedClasses, which takes the annotation class as a parameter and adds a binding for each annotated class.

Now we can do the following.

 
     AdvancedMultibinder multibinder = multibind(ISnack.class);
     multibinder.toAnnotatedClasses(Snack.class);
 
     // Add a non annotated class to the bind.
     multibinder.addBinding().to(Skittles.class);
 
     bind(Machine.class).to(SnackMachine.class);

I have attached the example project here so you can look into the code yourself.

  • Share/Bookmark

Filed under Java | 7 Comments »



7 Responses to “Google Guice and Multibinding”



    Jesse Wilson Says:
    Posted at: December 21, 2009 at 6:31 pm

    Neato!



    niels Says:
    Posted at: December 24, 2009 at 10:19 am

    >> @Snack
    >> public class Snickers implements ISnack

    I don’t know anything about Guice, but it seems rather redundant. Isn’t it possible to specify something similar to:
    AdvancedMultibinder multibinder = multibind(ISnack.class);
    multibinder.toImplementingClasses(ISnack.class);

    or even:
    AdvancedMultibinder multibinder = multibind(ISnack.class);
    multibinder.bindAllImplementingClasses();

    Niels



    Sakuraba Says:
    Posted at: December 24, 2009 at 10:29 am

    I wish those were available in GIN. Could definetly use those!



    iwein Says:
    Posted at: December 26, 2009 at 9:25 am

    That’s pretty nice. I have to agree with niels though, the parametrization of the collection doesn’t stack up against the redundancy of implementing the interface and annotate. But that’s easily fixed I think.



    Mischa Dasberg Says:
    Posted at: December 26, 2009 at 1:16 pm

    @niels and Iwein,

    As you can see in the example I bind all Snacks with the Snack annotation. (maybe I should have called the annotation DefaultSnack)

    multibinder.toAnnotatedClasses(Snack.class);
    // Add a non annotated class to the bind.
    multibinder.addBinding().to(Skittles.class);

    And I add Skittles to my personal snackmachine which doesn’t have the annotation.
    The downside of the toImplementingClasses would be that I can’t exclude any implementing class.



    Erik Jan Says:
    Posted at: January 13, 2010 at 9:33 am

    Great blog, I’ve one question why would you want to migrate from spring to guice?



    Mischa Dasberg Says:
    Posted at: January 13, 2010 at 3:00 pm

    @Erik, why not? Both Spring and Guice work great, but Guice makes your code cleaner and the setup is easier and more readable.



Leave a Reply

Click here to cancel reply.

Deployment automation for Java application running on Websphere, WebLogic and JBoss

Archives

  • March 2010
  • February 2010
  • January 2010
  • December 2009
  • November 2009
  • October 2009
  • September 2009
  • August 2009
  • July 2009
  • June 2009
  • May 2009
  • April 2009

Xebia Sites

  • Xebia Corporate
  • Xebia France
  • Xebia India

Categories

  • Java (282)
  • Agile (109)
  • General (50)
  • Testing (42)
  • Performance (42)
  • Hibernate (36)
  • Scrum (33)
  • Podcast (31)
  • Architecture (31)
  • Spring (28)
  • SOA (24)
  • Maven (22)
  • Project Management (22)
  • Middleware (23)
    • Deployment (14)
  • Flex (17)
  • JPA (17)
  • Eclipse (15)
  • Xebia Labs (15)
  • Quality Assurance (14)

Tag Cloud

    Scrum Ajax JavaOne Agile Performance Closures Testing Functional Programming Grails qcon Xebia Groovy SOA Maven product owner fitnesse esb Lean Java Introduction to Agile Agile Awareness Workshop Poppendieck Spring IntelliJ XML Scala Hibernate Seam Semantic Web Architecture