<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="Kernel.Container-Integration">
  <title>Container Integration</title>

  <para>Thanks to the extensibility of the kernel, it is now possible to
  interact with other containers. Indeed, you can inject components of an
  external container into a component of eXo kernel and you can also inject
  components of eXo kernel into a component of an external container.</para>

  <para>To allow eXo kernel to interact with a given container, you will need
  to deploy the artifact of the extension corresponding to this particular
  container and its related dependencies. At startup, eXo kernel will detect
  automatically the new interceptor thanks to SPI, and will add it to the head
  of the interceptor chain.</para>

  <para>When you will try to access to a component thanks to its type or key,
  the interceptor will first try to get it from the eXo kernel, if it can be
  found, it will return it, otherwise it will try to get it from the
  container. If you try to access to a list of components thanks to their
  type, it will first get the components from eXo kernel than add those found
  in the container.</para>

  <para>As we don't want to create and initialize a container for each
  ExoContainer to limit the impact of such process, you will need to configure
  explicitly a specific component in the configuration of all the
  ExoContainers for which you would like to enable the interceptor. By default
  the interceptor will be disabled, so no interaction between eXo kernel and
  the container will be possible and no container will be created and
  initialized. This component is specific to each extension, it is also used
  to provide anything that the interceptor could need to be enabled. We rely
  on this component to indicate which components of the container should be
  shared with eXo kernel, knowing that the shared components can be either
  injected into components of eXo kernel or components of eXo kernel could be
  injected into those shared components.</para>

  <note>
    <para>The extensions only register the components at startup, all the
    dynamic registrations using the methods
    <emphasis>registerComponentImplementation</emphasis> and
    <emphasis>registerComponentInstance</emphasis> will be ignored by the
    extensions such that the components dynamically registered after the
    startup won't be injected in the components of the container and no
    component of the container will be injected into those components.</para>
  </note>

  <para>All the components of eXo kernel that are shared with the container
  are the components defined before the starup of the ExoContainer and that
  are configured in the configuration of this particular ExoContainer. In
  other words the components of the parent ExoContainer won't be
  shared.</para>

  <para>The next sub sections will describe the different integrations that
  are already available.</para>

  <section id="Kernel.Container-Integration.Guice">
    <title>Google Guice</title>

    <para>In case of Google Guice 3, the artifacts to deploy are
    <emphasis>exo.kernel.container.ext.provider.impl.guice.v3</emphasis> and
    its dependencies. This artifact defines the interceptor called
    <emphasis>org.exoplatform.container.guice.GuiceContainer</emphasis>. To
    enable the <emphasis>GuiceContainer</emphasis>, you will need to configure
    explicitly in the configuration of the <emphasis>ExoContainer</emphasis>
    for which you want to enable the <emphasis>GuiceContainer</emphasis>, a
    component of type
    <emphasis>org.exoplatform.container.guice.ModuleProvider</emphasis>. This
    component is needed to enable the <emphasis>GuiceContainer</emphasis> but
    also to provide the Google Guice Module in which you define all the
    components that you would like to share with eXo Kernel. You will need to
    implement explicitly this interface and configure it.</para>

    <para>Here is an example of a configuration of such component, please note
    that you need to use
    <emphasis>org.exoplatform.container.guice.ModuleProvider</emphasis>
    explicitly as key in the component definition otherwise the
    <emphasis>GuiceContainer</emphasis> won't be enabled.</para>

    <programlisting language="xml">   &lt;component&gt;
      &lt;key&gt;org.exoplatform.container.guice.ModuleProvider&lt;/key&gt;
      &lt;type&gt;org.exoplatform.container.guice.TestGuiceContainer$MyModuleProvider&lt;/type&gt;
   &lt;/component&gt;</programlisting>

    <para>Here is an example of a <emphasis>ModuleProvider</emphasis></para>

    <programlisting language="java">   public static class MyModuleProvider implements ModuleProvider
   {
      public Module getModule()
      {
         return new AbstractModule()
         {
            @Override
            protected void configure()
            {
               bind(B.class);
               bind(C.class);
               bind(F.class);
               bind(G.class);
            }
         };
      }
   }</programlisting>

    <para>When you define a component in the configuration of the
    corresponding ExoContainer, this component is also defined in Google Guice
    allowing it to inject it in its components if needed. When the key used in
    the component definition is a class or an interface that is not an
    annotation, it will use this class/interface to bind the component. In
    case the key is a string, it will use the component implementation class
    and all its super classes and interfaces to bind the component and will
    annotate it with Named and the value of the key. If the key is an
    annotation, it will use the component implementation class and all its
    super classes and interfaces to bind the component and will annotate it
    with this annotation.</para>
  </section>

  <section id="Kernel.Container-Integration.Spring">
    <title>Spring</title>

    <para>In case of Spring 3, the artifacts to deploy are
    <emphasis>exo.kernel.container.ext.provider.impl.spring.v3</emphasis> and
    its dependencies. This artifact defines the interceptor called
    <emphasis>org.exoplatform.container.spring.SpringContainer</emphasis>. To
    enable the <emphasis>SpringContainer</emphasis>, you will need to
    configure explicitly in the configuration of the
    <emphasis>ExoContainer</emphasis> for which you want to enable the
    <emphasis>SpringContainer</emphasis>, a component of type
    <emphasis>org.exoplatform.container.spring.ApplicationContextProvider</emphasis>.
    This component is needed to enable the
    <emphasis>SpringContainer</emphasis> but also to create and provide the
    <emphasis>ApplicationContext</emphasis> in which you define all the
    components that you would like to share with eXo Kernel.</para>

    <para>We propose out of the box two implementations of the
    <emphasis>ApplicationContextProvider</emphasis> which are
    <emphasis>org.exoplatform.container.spring.FileSystemXmlApplicationContextProvider</emphasis>
    and
    <emphasis>org.exoplatform.container.spring.AnnotationConfigApplicationContextProvider</emphasis>.
    When you configure one of them don't forget to use
    <emphasis>org.exoplatform.container.spring.ApplicationContextProvider</emphasis>
    as key in the component definition otherwise the
    <emphasis>SpringContainer</emphasis> won't be enabled.</para>

    <itemizedlist>
      <listitem>
        <para>The <emphasis>FileSystemXmlApplicationContextProvider</emphasis>
        creates and initializes a
        <emphasis>FileSystemXmlApplicationContext</emphasis> thanks to a set
        of path to XML configuration files. The paths that you can use are
        resolved thanks to the <emphasis>ConfigurationManager</emphasis> which
        means that we can use prefixes like <emphasis>jar:</emphasis>,
        <emphasis>classpath:</emphasis>, <emphasis>file:</emphasis> and so on.
        The XML configuration files can be defined thanks to the values-param
        called <emphasis>config.paths</emphasis>.</para>

        <para>See below a configuration example:</para>

        <programlisting language="xml">   &lt;component&gt;
      &lt;key&gt;org.exoplatform.container.spring.ApplicationContextProvider&lt;/key&gt;
      &lt;type&gt;org.exoplatform.container.spring.FileSystemXmlApplicationContextProvider&lt;/type&gt;
      &lt;init-params&gt;
         &lt;values-param&gt;
            &lt;name&gt;config.paths&lt;/name&gt;
            &lt;description&gt;Path of the configuration files&lt;/description&gt;
            &lt;value&gt;classpath:/org/exoplatform/container/spring/beans-config2.xml&lt;/value&gt;
         &lt;/values-param&gt;
      &lt;/init-params&gt;
   &lt;/component&gt;</programlisting>

        <para>See below an example of XML configuration file:</para>

        <programlisting language="xml">&lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd"&gt;

   &lt;context:annotation-config /&gt;

   &lt;bean id="h" class="org.exoplatform.container.spring.TestSpringContainer$H"&gt;
   &lt;/bean&gt;

&lt;/beans&gt;</programlisting>
      </listitem>

      <listitem>
        <para>The
        <emphasis>AnnotationConfigApplicationContextProvider</emphasis>
        creates and initializes an
        <emphasis>AnnotationConfigApplicationContext</emphasis> thanks to a
        set of FQN of configuration classes. The FQN of configuration classes
        can be defined thanks to the values-param <emphasis>called
        config.classes</emphasis>.</para>

        <para>See below a configuration example:</para>

        <programlisting language="xml">   &lt;component&gt;
      &lt;key&gt;org.exoplatform.container.spring.ApplicationContextProvider&lt;/key&gt;
      &lt;type&gt;org.exoplatform.container.spring.AnnotationConfigApplicationContextProvider&lt;/type&gt;
      &lt;init-params&gt;
         &lt;values-param&gt;
            &lt;name&gt;config.classes&lt;/name&gt;
            &lt;description&gt;FQN of the configuration classes&lt;/description&gt;
            &lt;value&gt;org.exoplatform.container.spring.TestSpringContainer$Config2&lt;/value&gt;
         &lt;/values-param&gt;
      &lt;/init-params&gt;
   &lt;/component&gt;</programlisting>

        <para>See below an example of configuration class:</para>

        <programlisting language="java">   @Configuration
   public static class Config2
   {
      @Bean
      public H h()
      {
         return new H();
      }
   }</programlisting>
      </listitem>
    </itemizedlist>

    <para>When you define a component in the configuration of the
    corresponding ExoContainer, this component is also defined in Spring
    allowing it to inject it in its components if needed. When the key used in
    the component definition is a class or an interface, it will register the
    bean with the FQN of this class/interface as bean name. In case the key is
    a string, it will register the bean with the value of the key as bean
    name. In case the key is a class or an interface that is not an
    annotation, the corresponding bean will be defined as the primary autowire
    candidate otherwise we will only register the related qualifier which is
    Named and its value in case the key is a string or directly the key if the
    key is an annotaion.</para>

    <para>When you try to access to a component instance or a component
    adapter thanks to a key, it will first check if there is an existing bean
    whose name is the FQN of the class in case the key is a class or whose
    name is value of the key if the key is a String. If no bean can be found,
    it will then get the bean that matches with the bind type and the key if
    the key is an annotation class or the key is a string. In case the key is
    an annotation class, it will get the first bean that has been bound with
    this annotation. In case the key is a string, it will get the first bean
    that has been bound with Named and the value of the key.</para>

    <para>When you try to access to a component instance or a component
    adapter thanks to a type, it will first check if there is an existing bean
    whose name is the FQN of the type. If no bean can be found, it will then
    get the first bean that matches with the type.</para>
  </section>

  <section id="Kernel.Container-Integration.Weld">
    <title>Weld</title>

    <para>In case of Weld 1 or 2, the artifacts to deploy are
    <emphasis>exo.kernel.container.ext.provider.impl.weld.v</emphasis>1 or
    <emphasis>exo.kernel.container.ext.provider.impl.weld.v2</emphasis> and
    its dependencies. This artifact defines the interceptor called
    <emphasis>org.exoplatform.container.weld.WeldContainer</emphasis>. To
    enable the <emphasis>WeldContainer</emphasis>, you will need to configure
    explicitly in the configuration of the <emphasis>ExoContainer</emphasis>
    for which you want to enable the <emphasis>WeldContainer</emphasis>, a
    component of type
    <emphasis>org.exoplatform.container.weld.WeldContainerHelper</emphasis>.</para>

    <para>This component is needed to enable the
    <emphasis>WeldContainer</emphasis> but also to provide the Weld extensions
    that you would like to register and the method
    <emphasis>isIncluded(Class&lt;?&gt; clazz)</emphasis> which will be used
    to identify all the classes of the components that should be managed by
    Weld otherwise by default Weld will manage everything the classes of the
    components managed by eXo kernel included.</para>

    <para>All the components of Weld will be included automatically to the
    scope of Weld so we won't rely on the
    <emphasis>WeldContainerHelper</emphasis> to know if they need to be
    included to the scope of Weld or not.</para>

    <para>We propose out of the box one implementation of the
    <emphasis>WeldContainerHelper</emphasis> which is
    <emphasis>org.exoplatform.container.weld.BasicWeldContainerHelper</emphasis>.
    When you configure it don't forget to use
    <emphasis>org.exoplatform.container.weld.WeldContainerHelper</emphasis> as
    key in the component definition otherwise the
    <emphasis>WeldContainer</emphasis> won't be enabled.</para>

    <para>The <emphasis>BasicWeldContainerHelper</emphasis> is really a basic
    implementation as it doesn't provide any Weld extensions such that if you
    don't want to rely on the SPI approach proposed out of the box by Weld to
    register your extensions, you will need to propose your own implementation
    of the <emphasis>WeldContainerHelper</emphasis>.</para>

    <para>The <emphasis>BasicWeldContainerHelper</emphasis> allows to define
    the scope of Weld thanks to two values-param which are
    <emphasis>include</emphasis> and <emphasis>exclude</emphasis>. They both
    expect as values, as set of class name prefixes The first one can be used
    to define a set of name prefixes of the classes to include and the second
    one can be used to define a set of name prefixes of the classes to
    exclude.</para>

    <note>
      <para>It is not allowed to not set any values for both parameters. In
      case you set only values for the exclude parameters, the
      <emphasis>BasicWeldContainerHelper</emphasis> will include all the
      classes that don't match with those values.</para>
    </note>

    <para>See below a configuration example:</para>

    <programlisting language="xml">   &lt;component&gt;
      &lt;key&gt;org.exoplatform.container.weld.WeldContainerHelper&lt;/key&gt;
      &lt;type&gt;org.exoplatform.container.weld.BasicWeldContainerHelper&lt;/type&gt;
      &lt;init-params&gt;
         &lt;values-param&gt;
            &lt;name&gt;include&lt;/name&gt;
            &lt;value&gt;org.exoplatform.container.weld.TestWeldContainer$&lt;/value&gt;
         &lt;/values-param&gt;
         &lt;values-param&gt;
            &lt;name&gt;exclude&lt;/name&gt;
            &lt;value&gt;org.exoplatform.container.weld.TestWeldContainer$A&lt;/value&gt;
            &lt;value&gt;org.exoplatform.container.weld.TestWeldContainer$B&lt;/value&gt;
            &lt;value&gt;org.exoplatform.container.weld.TestWeldContainer$C&lt;/value&gt;
            &lt;value&gt;org.exoplatform.container.weld.TestWeldContainer$D&lt;/value&gt;
            &lt;value&gt;org.exoplatform.container.weld.TestWeldContainer$E&lt;/value&gt;
            &lt;value&gt;org.exoplatform.container.weld.TestWeldContainer$F&lt;/value&gt;
            &lt;value&gt;org.exoplatform.container.weld.TestWeldContainer$G&lt;/value&gt;
            &lt;value&gt;org.exoplatform.container.weld.TestWeldContainer$Marker&lt;/value&gt;
         &lt;/values-param&gt;
      &lt;/init-params&gt;
   &lt;/component&gt;</programlisting>

    <para>In this example we include all the inner classes of
    org.exoplatform.container.weld.TestWeldContainer but we exclude the inner
    classes A, B, C, D, E, F, G and Marker.</para>

    <para>When you define a component in the configuration of the
    corresponding ExoContainer, this component is also defined in Weld
    allowing it to inject it in its components if needed. In case the key is a
    class or an interface that is not an annotation, the corresponding bean
    will be qualified using the annotations <emphasis>Default</emphasis> and
    <emphasis>Any</emphasis> otherwise it will be qualified with Named and its
    value in case the key is a string or directly the key if the key is an
    annotaion.</para>

    <para>If the key is a class or an interface that is not an annotation, the
    bean will be bound to the key and the component implementation class
    otherwise the bean will be bound to the component implementation class and
    all its super classes and interfaces.</para>

    <para>When you try to access to a component instance or a component
    adapter thanks to a key, if it finds several candidates, it will return
    the first one except if the key is a class or an interface that is not an
    annotation, in that case it will return the first one annotated with
    <emphasis>Default</emphasis>.</para>

    <para>When you try to access to a component instance or a component
    adapter thanks to a type, if it finds several candidates, it will return
    the first one annotated with <emphasis>Default</emphasis>.</para>
  </section>
</section>
