<?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">
<chapter id="resource-injection">
  <title>TorqueBox Resource Injection</title>

  <section id="what-is-resource-injection">
    <title>What is Resource Injection?</title>

    <para><emphasis>Resource injection</emphasis> is the term given a software
    architectural strategy that moves the responsibility of finding and
    connecting components to a container, allowing components to remain simple
    and testable. Components declare what they need, and when instantiated by
    the container, the container also satisfies those needs.</para>

    <formalpara>
      <title>What's a resource?</title>

      <para>A resource may be most any component within your application,
      ranging from instances of Java classes, to messaging
      destinations.</para>
    </formalpara>
  </section>

  <section id="basics-of-resource-injection">
    <title>Basics of Resource Injection</title>

    <para>TorqueBox supports injection within the context of jobs, services,
    messaging-handlers, Stomplets and web applications. The two key components
    of using the injection capabilities are:</para>

    <para><itemizedlist>
        <listitem>
          <para>Include <classname>TorqueBox::Injectors</classname> in a
          source file that needs to perform injection. If injection occurs in
          a super-class, the super class must include
          <classname>TorqueBox::Injectors</classname>. If injection also
          occurs in a sub-class, the sub-class must also include
          <classname>TorqueBox::Injectors</classname>. By including this
          module, you indicate to the injection analyzer that a given source
          file should be considered. Inclusion of it does not inherit.</para>
        </listitem>

        <listitem>
          <para>To look up a value from the injection registry, use the
          <methodname>fetch(...)</methodname> method (or a variant) with a
          literal value. Variable interpolation is not supported within the
          argument list of <methodname>fetch(...)</methodname>. For
          convenience, the result of the <methodname>fetch(...)</methodname>
          call may be assigned to an instance value, but this is not
          required.</para>
        </listitem>
      </itemizedlist></para>

    <para>TorqueBox supports injection for source files in the following
    locations (relative to the root directory of your application):
    <itemizedlist>
        <listitem>
          <para>your app's root directory</para>
        </listitem>

        <listitem>
          <para><filename>/app</filename></para>
        </listitem>

        <listitem>
          <para><filename>/lib</filename></para>
        </listitem>

        <listitem>
          <para><filename>/helpers</filename></para>
        </listitem>

        <listitem>
          <para><filename>/models</filename> (for Padrino apps)</para>
        </listitem>
      </itemizedlist></para>

    <para>For instance:</para>

    <para><informalexample>
        <programlisting>class MyService 

  include TorqueBox::Injectors

  def initialize()
    @queue = fetch( '/queues/new-accounts' )
  end

  def that_thing()
    fetch( com.foo.ThatThing )
  end

end</programlisting>
      </informalexample></para>
  </section>

  <section id="injectable-resources">
    <title>Injectable Resources</title>

    <para>A variety of resources may easily be injected with the
    <methodname>fetch(...)</methodname> method.</para>

    <formalpara>
      <title>CDI Resources</title>

      <para>The Java Context and Depedency Injection (CDI) spec defines a
      method for managing relationships between components. CDI-enabled
      components may be injected by providing a fully-qualified Java class
      name to the <methodname>fetch(...)</methodname> method. Typically CDI
      components should be packaged in a JAR archive, and placed in your
      application's <filename>lib/</filename> or
      <filename>vendor/jars/</filename> directory.</para>
    </formalpara>

    <para>TorqueBox uses the JBoss Weld implementation of CDI. Please see the
    <ulink url="http://seamframework.org/Weld">Weld website</ulink> for more
    information.</para>

    <para><informalexample>
        <programlisting>class MyService

  include TorqueBox::Injectors

  def initialize()
    @java_service = fetch( com.mycorp.MyJavaService )
  end

end</programlisting>
      </informalexample></para>

    <para>JRuby explicitly supports the simple syntax for common US-centric
    package names starting with <literal>com</literal>,
    <literal>org</literal>, <literal>net</literal>, <literal>java</literal>,
    and javax, amongst others. For other top-level packages based on country
    codes, such as <literal>pl</literal>, <literal>de</literal>, or
    <literal>za</literal>, to perform injection you should reference your
    class through the <classname>Java</classname> ruby package.</para>

    <para><informalexample>
        <para><programlisting>fetch( Java::pl.softwaremine.PolishingService )</programlisting></para>
      </informalexample></para>

    <formalpara id="injectable-destinations">
      <title>Messaging Destinations</title>

      <para>Message destinations, such as queues and topics, may be injected
      into your components. If the argument to
      <methodname>fetch(...)</methodname> includes the string fragment
      <literal>"/queue"</literal> or <literal>"/topic"</literal>, TorqueBox
      will look up the relevant
      <classname>TorqueBox::Messaging::Queue</classname> or
      <classname>TorqueBox::Messaging::Topic</classname>.</para>
    </formalpara>

    <para>Using injection is the preferred method for obtaining a reference to
    a destination, to ensure that your job, service or web application relying
    upon the destination does not begin operation until the destination has
    been completely provisioned.</para>

    <para><informalexample>
        <programlisting>class MyController &lt; ApplicationController

  include TorqueBox::Injectors

  def create
    notify_topic = fetch( '/topics/new-accounts' )
  end

end</programlisting>
      </informalexample></para>

    <formalpara>
      <title>Naming &amp; Directory Entries</title>

      <para>Arbitrary items within the application's naming environment may be
      injected if the argument to <methodname>fetch(...)</methodname> begins
      with <literal>"java:comp/env"</literal>.</para>
    </formalpara>

    <para><informalexample>
        <programlisting>class MyController &lt; ApplicationController

  include TorqueBox::Injectors

  def create
    jndi_item = fetch( 'java:comp/env/that_thing' )
  end

end</programlisting>
      </informalexample></para>

    <formalpara>
      <title>JBoss MSC Services</title>

      <para>JBoss Modular Service Container is the container that drives the
      entire TorqueBox AS. Many components are accessible as MSC Services.
      These may be injected by passing the ServiceName as a string to
      <methodname>fetch(...)</methodname>.</para>
    </formalpara>

    <para><informalexample>
        <programlisting>class MyController &lt; ApplicationController

  include TorqueBox::Injectors

  def create
    the_actual_webserver = fetch( 'jboss.web' )
  end

end</programlisting>
      </informalexample></para>

    <formalpara>
      <title>Services</title>

      <para>TorqueBox Services may be injected into your components if the
      argument to <methodname>fetch(...)</methodname> begins with
      <literal>"service:"</literal> followed by the key used to configure the
      service in <filename>torquebox.yml</filename>.</para>
    </formalpara>

    <para><informalexample>
        <programlisting>class MyController &lt; ApplicationController

  include TorqueBox::Injectors

  def stop
    # Service defined with a unique name in torquebox.yml
    the_torque_service = fetch( 'service:my_torque_service' )
    # Service defined with service class in torquebox.yml
    another_service = fetch( 'service:AnotherSerice' )
  end

end</programlisting>
      </informalexample></para>
  </section>

  <section id="variants-of-inject">
    <title>Variants of <methodname>fetch(...)</methodname></title>

    <para>While the <methodname>fetch(...)</methodname> method is overloaded
    to detect the correct type of resource, there are occasions where it may
    guess incorrectly. To overcome this, variant are provided that explicitly
    direct the injection analyzer to look for a specific type of resource. For
    string-based injections, the previously mentioned matching rules do not
    apply to the injection method variants.</para>

    <formalpara>
      <title><methodname>fetch_cdi(...)</methodname></title>

      <para>Injects CDI resources by literal class name.</para>
    </formalpara>

    <formalpara>
      <title><methodname>fetch_queue(...)</methodname></title>

      <para>Injects a messaging queue by literal name.</para>
    </formalpara>

    <formalpara>
      <title><methodname>fetch_topic(...)</methodname></title>

      <para>Injects a messaging topic by literal name.</para>
    </formalpara>

    <formalpara>
      <title><methodname>fetch_naming(...)</methodname></title>

      <para>Injects JNDI resources by literal name.</para>
    </formalpara>

    <formalpara>
      <title><methodname>fetch_msc(...)</methodname></title>

      <para>Injects MSC services by literal name.</para>
    </formalpara>

    <formalpara>
      <title><methodname>fetch_service(...)</methodname></title>

      <para>Injects a TorqueBox application service component</para>
    </formalpara>
  </section>

  <section id="injection-internals-and-testing">
    <title>Internals and Testing</title>

    <para>At runtime, each <classname>fetch(...)</classname> method looks up
    the injected resource through the
    <classname>TorqueBox::Registry</classname> singleton. In test
    environments, you may desire to populate this registry, using the
    <methodname>merge!(...)</methodname> method, which accepts a key/value
    <classname>Hash</classname>.</para>

    <para>The key for each entry should match either the string argument used
    with <methodname>fetch(...)</methodname>, or the Ruby version of the Java
    class name, if performing CDI injection. The value should be an
    appropriate object.</para>

    <para>For instance, the Java class of <classname>java.util.Set</classname>
    should be converted into a string of
    <literal>"Java::JavaUtil::Set"</literal> when used as an injection look-up
    key.</para>
  </section>

  <section id="disabling-the-scanner">
    <title>Disabling the Injection Scanner</title>

    <para>If you're not making use of injection, you can disable the injection
    scanner on a per-application basis. Simply add:</para>

    <para><informalexample>
        <programlisting>injection:
  enabled: false
    </programlisting>
      </informalexample></para>

    <para>to your -knob.yml or torquebox.yml file, and injection scanning will
    be disabled for your application.</para>
  </section>
</chapter>
