Chapter 15. Guice integration

Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 5 and above, brought to you by Google.

We've written a piece of integration code that bridges the two IoC frameworks together. You can inject Guice defined beans into Microcontainer and/or the other way around. See examples for more details.

In this example we will define Guice module, binding simple Singleton class to one of it's instances. We will then do a contextual lookup for the Singleton instance in SingletonHolder class.

      AbstractBeanMetaData guicePlugin = new AbstractBeanMetaData("GuicePlugin", GuiceKernelRegistryEntryPlugin.class.getName());
      AbstractConstructorMetaData constructor = new AbstractConstructorMetaData();
      AbstractArrayMetaData arrayMetaData = new AbstractArrayMetaData();
      final Singleton singleton = new Singleton();
      Module module = new AbstractModule()
      {
         protected void configure()
         {
            bind(Singleton.class).toInstance(singleton);
         }
      };
      arrayMetaData.add(new AbstractValueMetaData(module));
      constructor.setParameters(Collections.singletonList((ParameterMetaData)new AbstractParameterMetaData(arrayMetaData)));
      guicePlugin.setConstructor(constructor);

      public class SingletonHolder
      {
         private Singleton singleton;

         @Constructor
         public SingletonHolder(@Inject Singleton singleton)
         {
            this.singleton = singleton;
         }

         public Singleton getSingleton()
         {
            return singleton;
         }
      }

      ControllerContext holderContext = controller.getInstalledContext("holder");
      assertNotNull(holderContext);
      SingletonHolder holder = (SingletonHolder)holderContext.getTarget();
      assertNotNull(holder);
      assertEquals(singleton, holder.getSingleton());
   

The detail that is hidden is in GuiceKernelRegistryEntryPlugin, which acts as a intermediate between Microcontainer's registry and Guice Injector. But all you need to do is register GuiceKernelRegistryEntryPlugin as a POJO into Microcontainer, providing Guice Modules with its constructor.

We can also go the other way around. Injecting named beans into Guice Injector. There are a couple of ways to achieve that. Lets look at them.

         Injector injector = Guice.createInjector(new AbstractModule()
         {
            protected void configure()
            {
               bind(Controller.class).toInstance(controller);
               bind(Singleton.class).toProvider(GuiceIntegration.fromMicrocontainer(Singleton.class, "singleton"));
               bind(Prototype.class).toProvider(GuiceIntegration.fromMicrocontainer(Prototype.class, "prototype"));
            }
         });
   
         AbstractBeanMetaData injectorBean = new AbstractBeanMetaData("injector", GuiceInjectorFactory.class.getName());
         AbstractConstructorMetaData constructor = new AbstractConstructorMetaData();
         constructor.setFactoryClass(GuiceInjectorFactory.class.getName());
         constructor.setFactoryMethod("createInjector");
         List<ParameterMetaData> parameters = new ArrayList<ParameterMetaData>();
         parameters.add(new AbstractParameterMetaData(new AbstractDependencyValueMetaData(KernelConstants.KERNEL_NAME)));
         AbstractArrayMetaData array = new AbstractArrayMetaData();
         array.add(new AbstractValueMetaData(GuiceObject.ALL));
         parameters.add(new AbstractParameterMetaData(array));
         constructor.setParameters(parameters);
         injectorBean.setConstructor(constructor);
         controller.install(injectorBean);

         ControllerContext injectorContext = controller.getInstalledContext("injector");
         assertNotNull(injectorContext);
         Injector injector = (Injector)injectorContext.getTarget();
   
      <bean name="injector" class="org.jboss.guice.plugins.GuiceInjectorFactory">
         <constructor factoryClass="org.jboss.guice.plugins.GuiceInjectorFactory" factoryMethod="createInjector">
            <parameter>jboss.kernel:service=Kernel</parameter>
            <parameter>
               <array>
                  <bean name="BindAll" class="org.jboss.guice.plugins.AllGuiceObject">
                     <constructor factoryClass="org.jboss.guice.plugins.AllGuiceObject" factoryMethod="getInstance"/>
                  </bean>
               </array>
            </parameter>
         </constructor>
      </bean>
   

Here we see three way of usgin Microcontainer beans to do wiring in Guice. The first and second examples are purely programmatic and you need to provide a Controller instance. The third one is how you would bind all existing installed beans into Guice Injector via -beans.xml. Or you can provide a ControllerContextBindFilter instance to the binding methods to filter those beans you want to bind. See API docs for more details.