<?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.DI">
  <title>Dependency Injection (JSR 330)</title>

  <para>It is now possible to use the Inject annotation in order to inject the
  dependencies of a given component as described in the JSR 330.</para>

  <para>You can inject values thanks to a constructor:</para>

  <programlisting language="java">@Inject
public JSR330_C(Provider&lt;P&gt; p, @Named("n2") N n, @N1 N n2)
{
   this.p = p;
   this.n = n;
   this.n2 = n2;
}</programlisting>

  <para>In the example above the kernel will inject thanks to the constructor
  an object of type N named <emphasis>n2</emphasis>, another object of type N
  annotated with the qualifier <emphasis>N1</emphasis> and will inject the
  provider allowing to lazily access to an object of type P.</para>

  <note>
    <para>The kernel will take the first constructor with the Inject
    annotation that it can find so you must not have more than one constructor
    with the Inject annotation otherwise you won't be able to predict which
    constructor will be used by the kernel.</para>
  </note>

  <para>You can inject values to fields:</para>

  <programlisting language="java">@Inject
@Named("n2")
private N n;

@Inject
@N1
private N n2;

@Inject
private Provider&lt;P&gt; p;

</programlisting>

  <para>In the example above the kernel will inject an object of type N named
  <emphasis>n2</emphasis>, another object of type N annotated with the
  qualifier <emphasis>N1</emphasis> and will inject the provider allowing to
  lazily access to an object of type P.</para>

  <para>You can inject values thanks to methods usually setters but you can
  also make the kernel call methods for initialization purpose</para>

  <programlisting language="java">@Inject
void setN(@Named("n2") N n)
{
   this.n = n;
}

@Inject
void setN2(@N1 N n2)
{
   this.n2 = n2;
}

@Inject
public void init()
{
...
}</programlisting>

  <para>In the example above the kernel will inject an object of type N named
  <emphasis>n2</emphasis> thanks to the method setN, another object of type N
  annotated with the qualifier <emphasis>N1</emphasis> thanks to the method
  setN2 and finally will call the init method.</para>

  <note>
    <para>You have no way to ensure that a given method will be called before
    another, so in case you need to implement an init method that needs to be
    called only when all the dependencies are injected, you should inject your
    dependencies using constructors or fields. Because constructors are
    injected first, followed by fields, and then methods.</para>
  </note>

  <section id="Kernel.DI.SNL">
    <title>Specificities and Limitations</title>

    <para>The implementation can inject dependencies using private,
    package-private, protected and public constructors, methods and fileds.
    Injection on final and/or static fields is not supported. Injection on
    static methods is not supported. Only one constructor can be annotated
    with the Inject annotation.</para>

    <para>As the old way to create a component only creates only singletons
    and according to the specification only components explicitly annotated
    with the Singleton annotation must be considered as singleton, the kernel
    will decide which mode to use thanks to the constructors. Indeed if you
    have no constructor annotated with the Inject annotation and you don't
    have only one constructor that is public with no argument, the kernel will
    consider that the component expects the old behavior as it won't be
    considered as JSR 330 compliant. This also helps to limit the overhead of
    data injection, it will only be done on compliant components only.</para>

    <note>
      <para>Once the component is considered as JSR 330 compliant, the kernel
      will try to inject the dependencies and will check if the annotation
      Singleton has explicitly been added at class declaration level. By
      default it will be considered as a Dependent such that a new instance
      will be created at each call. So be very careful of that.</para>
    </note>

    <para>You can only use one qualifier and the only attribute supported for
    a qualifier is the value of the annotation <emphasis>Named</emphasis>. You
    can bind only one class to a given qualifier so make sure that the type is
    compatible with the object that must be injected by the kernel otherwise
    you will get <emphasis>ClassCastException</emphasis>.These limitations are
    for the sake of simplicity.</para>

    <para>The names are unique within the context of a given container so to
    prevent any naming collision don't hesitate to add a prefix to your
    names.</para>
  </section>

  <section id="Kernel.DI.Configuration">
    <title>Configuration</title>

    <para>When you use the annotation Named, the kernel will get the value of
    the annotation and will try to get the component that has been registered
    using this value as key. So thanks to the configuration example below it
    will be possible to use <emphasis>@Named("spare")</emphasis> in order to
    inject a component of type <emphasis>SpareTire</emphasis>.</para>

    <programlisting language="xml">&lt;component&gt;
   &lt;key&gt;spare&lt;/key&gt;
   &lt;type&gt;org.atinject.tck.auto.accessories.SpareTire&lt;/type&gt;
&lt;/component&gt;</programlisting>

    <para>In case you want to use your own qualifier, you will be able to bind
    your object class to this particular qualifier by simply using the FQN of
    your qualifier as key like in the next example:</para>

    <programlisting language="xml">&lt;component&gt;
   &lt;key&gt;org.atinject.tck.auto.Drivers&lt;/key&gt;
   &lt;type&gt;org.atinject.tck.auto.DriversSeat&lt;/type&gt;
&lt;/component&gt;</programlisting>

    <para>In the example above
    <emphasis>org.atinject.tck.auto.Drivers</emphasis> is the FQN of the
    qualifier and <emphasis>org.atinject.tck.auto.DriversSeat</emphasis> is
    the FQN of the class to which we want to bind the qualifier. Thanks to
    that if the kernel detects the annotation <emphasis>@Drivers</emphasis> it
    will inject a component of type <emphasis>DriversSeat</emphasis>.</para>
  </section>

  <section id="Kernel.DI.Scope">
    <title>Scope Management</title>

    <para>A part of the JSR 346 also know as CDI 1.1 (Contexts and Dependency
    Injection for JavaTM EE), has been implemented in order to be able to set
    a scope to a component. For now, the implementation is limited as It is
    only possible to set a scope at class and/or interface definition level
    since the producers are not supported and it is not possible to set a
    scope at field declaration level either.</para>

    <para>The pseudo-scope <emphasis>Singleton</emphasis> and the normal scope
    <emphasis>ApplicationScoped</emphasis> are both considered as singletons
    such that they are managed the exact same way by the kernel. The only
    difference is the fact that the scope
    <emphasis>ApplicationScoped</emphasis> can be inherited and the scope
    <emphasis>Singleton</emphasis> cannot be inherited by definition.</para>

    <para>How the kernel gets the scope?</para>

    <itemizedlist>
      <listitem>
        <para>If the component is not considered as JSR 330 compliant (there
        isn't any compliant constructor and the Inject annotation is never
        used), the scope will be <emphasis>Singleton</emphasis> for backward
        compatibility reason.</para>
      </listitem>

      <listitem>
        <para>If the component is considered as JSR 330 compliant and the
        context manager has not been defined</para>

        <itemizedlist>
          <listitem>
            <para>A scope has been set explicitly to <emphasis>Singleton,
            ApplicationScoped or Dependent</emphasis>, in that case it will
            use the provided scope.</para>
          </listitem>

          <listitem>
            <para>No scope has been set explicitly, in that case it will get
            the default scope from the stereotypes, by default it will use the
            scope <emphasis>Dependent</emphasis>.</para>
          </listitem>

          <listitem>
            <para>A scope has been set explicitly to something other than
            <emphasis>Singleton, ApplicationScoped or Dependent</emphasis>, in
            that case it will get the default scope from the stereotypes, by
            default it will use the scope
            <emphasis>Dependent</emphasis>.</para>
          </listitem>
        </itemizedlist>
      </listitem>

      <listitem>
        <para>If the component is considered as JSR 330 compliant and the
        context manager has been defined</para>

        <itemizedlist>
          <listitem>
            <para>A scope has been set explicitly to <emphasis>Singleton,
            ApplicationScoped, Dependent</emphasis> or a scope known by the
            context manager, in that case it will use the provided
            scope.</para>
          </listitem>

          <listitem>
            <para>No scope has been set explicitly, in that case it will get
            the default scope from the stereotypes, by default it will use the
            scope <emphasis>Dependent</emphasis>.</para>
          </listitem>

          <listitem>
            <para>A scope has been set explicitly to something other than
            <emphasis>Singleton, ApplicationScoped, Dependent</emphasis> or a
            scope known by the context manager, in that case it will get the
            default scope from the stereotypes, by default it will use the
            scope <emphasis>Dependent</emphasis>.</para>
          </listitem>
        </itemizedlist>
      </listitem>
    </itemizedlist>

    <note>
      <para>In the package
      <emphasis>org.exoplatform.container.context.stereotype</emphasis>, you
      can find a set of stereotypes that you can use to set a default scope.
      You have one stereotype per supported scope. For example if you want to
      set the scope <emphasis>Singleton</emphasis> by default, you can add the
      annotation <emphasis>@SingletonByDefault</emphasis> at the class
      definition level of your component.</para>
    </note>

    <para>If you intend to use a passivating scope, you will have to make sure
    that the component with this scope is Serializable otherwise the container
    will prevent the instantiation of your component.</para>

    <para>Any time the kernel will need to create an instance of a component
    that has a normal scope (except the
    <emphasis>ApplicationScoped</emphasis>), it will create automatically a
    proxy of your component implementation class as defined in the
    specification. So if you intend to use a normal scope, you will need to
    deploy the latest version of javassist otherwise you will get a
    <emphasis>ClassNotFoundException</emphasis>. Moreover, you need to make
    sure that the code that accesses to a component that has a normal scope,
    only accesses to methods of this component and never directly to fields
    otherwise you will get unexpected issues. The best wait to prevent issues
    is to make private all the fields of a component with a normal
    scope.</para>

    <para>Out of the box, eXo kernel can manage the scopes
    <emphasis>Singleton</emphasis>, <emphasis>ApplicationScoped</emphasis> and
    <emphasis>Dependent</emphasis>, even if the context manager has not been
    defined. If you define the context manager, you will be able to define and
    use the scopes <emphasis>SessionScoped</emphasis> and
    <emphasis>RequestScoped</emphasis>.</para>

    <para>The next code snippet shows how the context manager can be
    configured to allow you to use the scopes
    <emphasis>SessionScoped</emphasis> and
    <emphasis>RequestScoped</emphasis>:</para>

    <programlisting language="xml">&lt;component&gt;
 &lt;key&gt;org.exoplatform.container.context.ContextManager&lt;/key&gt;
 &lt;type&gt;org.exoplatform.container.context.ContextManagerImpl&lt;/type&gt;
 &lt;component-plugins&gt;
  &lt;component-plugin&gt;
   &lt;name&gt;main-scopes&lt;/name&gt;
   &lt;set-method&gt;addContexts&lt;/set-method&gt;
   &lt;type&gt;org.exoplatform.container.context.ContextPlugin&lt;/type&gt;
   &lt;init-params&gt;
    &lt;object-param&gt;
     &lt;name&gt;request-scope&lt;/name&gt;
     &lt;object type="org.exoplatform.container.context.RequestContext"/&gt;
    &lt;/object-param&gt;
    &lt;object-param&gt;
     &lt;name&gt;session-scope&lt;/name&gt;
     &lt;object type="org.exoplatform.container.context.SessionContext"/&gt;
    &lt;/object-param&gt;
   &lt;/init-params&gt;
  &lt;/component-plugin&gt;
 &lt;/component-plugins&gt;
&lt;/component&gt;</programlisting>

    <warning>
      <title>Warning</title>

      <para>For technical reasons, the context manager must be configured at
      <emphasis>RootContainer</emphasis> (for portal mode) or
      <emphasis>StandaloneContainer</emphasis> (for standalone mode) level,
      otherwise if you configure it at <emphasis>PortalContainer</emphasis>
      level it won't work properly.</para>
    </warning>

    <para>You can find a simple example that shows you how to use the
    different supported scopes in eXo JCR in the project
    <emphasis>applications/exo.jcr.applications.examples</emphasis> available
    in the source code of eXo JCR. Read the file
    <emphasis>readme.txt</emphasis> for more details.</para>

    <para>How to define your own scope?</para>

    <orderedlist>
      <listitem>
        <para>You will need to implement the interface
        <emphasis>org.exoplatform.container.context.AdvancedContext</emphasis>.
        Most of the time, you will simply need to extend the abstract classes
        <emphasis>UnSharedContext</emphasis> in case of an unshared context or
        <emphasis>SharedContext</emphasis> in case of a shared context.</para>
      </listitem>

      <listitem>
        <para>You will need to define the lifecycle of your scope by calling
        the methods register/unregister to create/destroy a context. You will
        have also to activate/deactivate the context using the corresponding
        methods.</para>
      </listitem>

      <listitem>
        <para>You will need to configure your scope thanks to a
        <emphasis>org.exoplatform.container.context.ContextPlugin</emphasis>.</para>
      </listitem>
    </orderedlist>
  </section>
</section>
