<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
      "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">

<chapter id="guice">
   <title>Guice integration</title>

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

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

   <para>In this example we will define a Guice module, binding a simple Singleton class to one of its
      instances. We will then do a contextual lookup for the Singleton instance in the SingletonHolder class.
   </para>

   <programlisting>
      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());
   </programlisting>

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

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

   <programlisting>
      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"));
         }
      });
   </programlisting>

   <programlisting>
     AbstractBeanMetaData injectorBean = 
        new AbstractBeanMetaData(
            "injector", GuiceInjectorFactory.class.getName());
     AbstractConstructorMetaData constructor = new AbstractConstructorMetaData();
     constructor.setFactoryClass(GuiceInjectorFactory.class.getName());
     constructor.setFactoryMethod("createInjector");
     List&lt;ParameterMetaData> parameters = new ArrayList&lt;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();
   </programlisting>

   <programlisting>
      &lt;bean name="injector" class="org.jboss.guice.plugins.GuiceInjectorFactory">
         &lt;constructor 
                factoryClass="org.jboss.guice.plugins.GuiceInjectorFactory" 
                factoryMethod="createInjector">
            &lt;parameter>jboss.kernel:service=Kernel&lt;/parameter>
            &lt;parameter>
               &lt;array>
                  &lt;bean name="BindAll" 
                        class="org.jboss.guice.plugins.AllGuiceObject">
                     &lt;constructor 
                            factoryClass="org.jboss.guice.plugins.AllGuiceObject" 
                            factoryMethod="getInstance"/>
                  &lt;/bean>
               &lt;/array>
            &lt;/parameter>
         &lt;/constructor>
      &lt;/bean>
   </programlisting>

   <para>Here we saw three ways of using 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 the Guice Injector via a -beans.xml. Or you can provide a ControllerContextBindFilter
      instance to the binding methods to filter the beans you want to bind. See the API docs for more details.
   </para>

</chapter>
