<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
  <!ENTITY % images_ent SYSTEM "images.ent"> 
  %images_ent;
] >
<book lang="en">
  <bookinfo>
    <title>TorqueBox Getting Started Guide</title>

    <releaseinfo>${project.version}</releaseinfo>

    <authorgroup>
      <corpauthor>The TorqueBox Project</corpauthor>
    </authorgroup>
  </bookinfo>

  <toc></toc>

  <chapter id="first-steps">
    <title>First Steps</title>

    <para>
      Choose the section below to follow based on your development
      environment - Windows users should follow <xref
      linkend="first-steps-windows"/>, RVM users should follow <xref
      linkend="first-steps-rvm"/>, and regular Mac or Linux users
      should follow <xref linkend="first-steps-mac-linux"/>.
    </para>

    <section id="first-steps-mac-linux">
      <title>First Steps on Mac / Linux</title>

      <para>
        If you use Ruby Version Manager (RVM), be sure to follow the
        <xref linkend="first-steps-rvm"/> instructions and not the
        generic Mac / Linux instructions.
       </para>

       <section>
        <title>Your First Rails Application</title>

        <para>
          Ensure you have Java 6 or above installed then download and
          extract the TorqueBox binary distribution and set a few
          environment variables.

           <screen><prompt>$</prompt> <command>wget http://torquebox.org/release/org/torquebox/torquebox-dist/${project.version}/torquebox-dist-${project.version}-bin.zip</command>
...
2012-09-13 09:35:56 (1.61 MB/s) - `torquebox-dist-${project.version}-bin.zip' saved [152039457/152039457]

<prompt>$</prompt> <command>unzip torquebox-dist-${project.version}-bin.zip -d ~ </command>
...
  inflating: torquebox-${project.version}/Rakefile
<prompt>$</prompt> <command>export TORQUEBOX_HOME=~/torquebox-${project.version}</command>
<prompt>$</prompt> <command>export JBOSS_HOME=$TORQUEBOX_HOME/jboss</command>
<prompt>$</prompt> <command>export JRUBY_HOME=$TORQUEBOX_HOME/jruby</command>
<prompt>$</prompt> <command>export PATH=$JRUBY_HOME/bin:$PATH</command></screen>

          You'll likely want to place the exports somewhere that gets
          loaded automatically - <filename>~/.bashrc</filename>,
          <filename>~/.bash_profile</filename>, or wherever your
          operating system suggests placing user-specific environment
          variables.
        </para>

        <para>
          Install Rails and create a new Rails example application.

          <screen><prompt>$</prompt> <command>mkdir -p ~/torquebox_examples/rails_example</command>
<prompt>$</prompt> <command>cd ~/torquebox_examples/rails_example</command>
<prompt>$</prompt> <command>gem install rails</command>
...
Successfully installed rails-3.2.11
27 gems installed
<prompt>$</prompt> <command>rails new .</command>
...
Using rails (3.2.11) 
Installing sass (3.2.5) 
Installing sass-rails (3.2.6) 
Installing therubyrhino_jar (1.7.4) 
Installing therubyrhino (2.0.2) 
Installing uglifier (1.3.0) 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.</screen>
          <note>
            <title>Bundler and jruby-openssl</title>
            <para>
              Some versions of JRuby, Bundler, and jruby-openssl don't
              play well together so if you get an error when Rails
              tries to run <command>bundle install</command> regarding
              jruby-openssl, edit the <filename>Gemfile</filename> to
              change the source line from https to http and manually
              run <command>bundle install</command> afterwards.
            </para>
          </note>
        </para>

        <para>
          Add a simple scaffolded resource, deploy it to TorqueBox,
          and run TorqueBox.

          <screen><prompt>$</prompt> <command>rails g scaffold post title body:text</command>
...
      create      app/assets/stylesheets/posts.css.scss
      invoke  scss
      create      app/assets/stylesheets/scaffolds.css.scss
<prompt>$</prompt> <command>rake db:migrate</command>
==  CreatePosts: migrating ====================================================
-- create_table(:posts)
   -> 0.0060s
   -> 0 rows
==  CreatePosts: migrated (0.0080s) ===========================================

<prompt>$</prompt> <command>torquebox deploy</command>
Deployed: rails_example-knob.yml
    into: /Users/someone/torquebox-${project.version}/jboss/standalone/deployments
<prompt>$</prompt> <command>torquebox run </command>
...
15:59:28,053 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "rails_example-knob.yml"</screen>
        </para>

        <para>
          Open <ulink url="http://localhost:8080"/> in your browser
          and you'll be greeted with the Rails "Welcome aboard"
          page. Navigate to <ulink
          url="http://localhost:8080/posts/"/> to see your scaffolded
          resource.
        </para>

        <para>
          Now edit
          <filename>~/torquebox_examples/rails_example/app/views/posts/index.html.erb</filename>
          then refresh the posts page in your browser and see your
          changes. Changes to your Rails application show up
          immediately in the browser, as expected. When you're done,
          press CTRL+C in the terminal to stop TorqueBox before
          continuing with the next steps.
        </para>
      </section>

      <section>
        <title>Subsequent Applications</title>

        <para>
          Deploying multiple applications to TorqueBox is
          straightforward, but let's walk through the required steps.
          We'll create a Rack application to go with our Rails example
          application created earlier. If TorqueBox is still running
          stop it with CTRL+C in its terminal window before following
          the steps below.

      <screen><prompt>$</prompt> <command>mkdir -p ~/torquebox_examples/rack_example</command>
<prompt>$</prompt> <command>cd ~/torquebox_examples/rack_example</command>
<prompt>$</prompt> <command>gem install rack</command>
Fetching: rack-1.5.0.gem (100%)
Successfully installed rack-1.5.0
1 gem installed
</screen>

          Now create a <filename>config.ru</filename> for our example
          rack application.
          <example>
            <title><filename>~/torquebox_examples/rack_example/config.ru</filename></title>
            <programlisting>app = lambda { |env|
  [200, { 'Content-Type' => 'text/html' }, "Hello from Rack\n" ]
}
run app</programlisting>
          </example>

          Deploy the Rack application at a context-path of "/rack"
          since we already have the Rails application deployed at the
          root context.

        <screen><prompt>$</prompt> <command>torquebox deploy --context-path=/rack</command>
Deployed: rack_example-knob.yml
    into: /Users/someone/torquebox-${project.version}/jboss/standalone/deployments</screen>
        </para>

        <para>
          Now you should be able to run TorqueBox and see both
          applications deployed.

        <screen><prompt>$</prompt> <command>torquebox run</command>
...
19:25:38,049 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS018559: Deployed "rails_example-knob.yml"
19:25:38,050 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS018559: Deployed "rack_example-knob.yml"</screen>

          Visit <ulink url="http://localhost:8080"/> and <ulink
          url="http://localhost:8080/rack/"/> to see that both your
          Rails and Rack applications are deployed and working.
        </para>

        <para>
          Congratulations! You now know all the basics to proceed with
          the rest of this getting started guide when using a Mac or
          Linux.
        </para>

        <para>Continue to <xref linkend="adding-torquebox-features"/>.</para>
      </section>
     </section>

    <section id="first-steps-windows">
      <title>First Steps on Windows</title>

      <section>
        <title>Your First Rails Application</title>

        <para>
          Ensure you have Java 6 or above installed then download
          TorqueBox using your web browser from <ulink
          url="http://torquebox.org/release/org/torquebox/torquebox-dist/${project.version}/torquebox-dist-${project.version}-bin.zip"/>. Right-click
          the downloaded zip in Windows Explorer and select Extract
          All. When prompted for a folder to extract the files to,
          choose your user's home directory (ie
          <filename>C:\Users\someone\</filename>).
        </para>

        <para>
          After TorqueBox is extracted, we need to set a few
          environment variables. Find the Advanced System Settings
          dialog (in Windows 7 this is Control Panel -> System and
          Security -> System -> Advanced System Settings) and click
          the Environment Variables button. We want to add three new
          user environment variables. Add
          <varname>TORQUEBOX_HOME</varname> with a value of
          <filename>%HOME%\torquebox-${project.version}</filename>. Add
          <varname>JBOSS_HOME</varname> with a value of
          <filename>%HOME%\torquebox-${project.version}\jboss</filename>. Add
          <varname>JRUBY_HOME</varname> with a value of
          <filename>%HOME%\torquebox-${project.version}\jruby</filename>. Also modify the
          <varname>Path</varname> environment variable by prepending
          <filename>%JRUBY_HOME%\bin;</filename> to the front of the
          current value. Click the OK button to save and close the
          Environment Variables dialog.
        </para>

        <para>
          Now let's open up a Command Prompt to install Rails and
          create a new Rails example application. You can open a
          Command Prompt by clicking the Windows button in the bottom
          left and typing <filename>cmd</filename> in the search box.

          <screen><prompt>&gt;</prompt> <command>mkdir %HOME%\torquebox_examples\rails_example</command>
<prompt>&gt;</prompt> <command>cd %HOME%\torquebox_examples\rails_example</command>
<prompt>&gt;</prompt> <command>gem install rails</command>
...
Successfully installed rails-3.2.11
27 gems installed
<prompt>&gt;</prompt> <command>rails new .</command>
...
Using rails (3.2.11) 
Installing sass (3.2.5) 
Installing sass-rails (3.2.6) 
Installing therubyrhino_jar (1.7.4) 
Installing therubyrhino (2.0.2) 
Installing uglifier (1.3.0) 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.</screen>
          <note>
            <title>Bundler and jruby-openssl</title>
            <para>
              Some versions of JRuby, Bundler, and jruby-openssl don't
              play well together so if you get an error when Rails
              tries to run <command>bundle install</command> regarding
              jruby-openssl, edit the <filename>Gemfile</filename> to
              change the source line from https to http and manually
              run <command>bundle install</command> afterwards.
            </para>
          </note>
        </para>

        <para>
          Add a simple scaffolded resource, deploy it to TorqueBox,
          and run TorqueBox.

          <screen><prompt>&gt;</prompt> <command>rails g scaffold post title body:text</command>
...
      create      app/assets/stylesheets/posts.css.scss
      invoke  scss
      create      app/assets/stylesheets/scaffolds.css.scss
<prompt>&gt;</prompt> <command>rake db:migrate</command>
==  CreatePosts: migrating ====================================================
-- create_table(:posts)
   -> 0.0060s
   -> 0 rows
==  CreatePosts: migrated (0.0080s) ===========================================

<prompt>&gt;</prompt> <command>torquebox deploy</command>
Deployed: rails_example-knob.yml
    into: C:\Users\someone\torquebox-${project.version}\jboss\standalone\deployments
<prompt>&gt;</prompt> <command>echo Y | jruby -S torquebox run </command>
...
15:59:28,053 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "rails_example-knob.yml"</screen>

          <tip>
            <title>Why <command>echo Y</command> and <command>jruby -S</command>?</title>
            <para>
              When stopping TorqueBox via CTRL+C, the Windows Command
              Prompt will ask you if you want to "Terminate batch job
              (Y/N)?". Piping <command>echo Y</command> into the
              command just prevents you from having to answer this
              prompt.

              We prefix the command with <command>jruby -S</command>
              because if we just used <command>echo Y | torquebox
              run</command> there's currently a bug where TorqueBox
              would get stuck in an infinite restart loop upon
              stopping.
            </para>
          </tip>
        </para>

        <para>
          Open <ulink url="http://localhost:8080"/> in your browser
          and you'll be greeted with the Rails "Welcome aboard"
          page. Navigate to <ulink
          url="http://localhost:8080/posts/"/> to see your scaffolded
          resource.
        </para>

        <para>
          Now edit
          <filename>%HOME%\torquebox_examples\rails_example\app\views\posts\index.html.erb</filename>
          then refresh the posts page in your browser and see your
          changes. Changes to your Rails application show up
          immediately in the browser, as expected. When you're done,
          press CTRL+C in the terminal to stop TorqueBox before
          continuing with the next steps.
        </para>
      </section>

      <section>
        <title>Subsequent Applications</title>

        <para>
          Deploying multiple applications to TorqueBox is
          straightforward, but let's walk through the required steps.
          We'll create a Rack application to go with our Rails example
          application created earlier. If TorqueBox is still running
          stop it with CTRL+C in its terminal window before following
          the steps below.

      <screen><prompt>&gt;</prompt> <command>mkdir %HOME%\torquebox_examples\rack_example</command>
<prompt>&gt;</prompt> <command>cd %HOME%\torquebox_examples\rack_example</command>
<prompt>&gt;</prompt> <command>gem install rack</command>
Fetching: rack-1.5.0.gem (100%)
Successfully installed rack-1.5.0
1 gem installed
</screen>

          Now create a <filename>config.ru</filename> for our example
          rack application.
          <example>
            <title><filename>%HOME%\torquebox_examples\rack_example\config.ru</filename></title>
            <programlisting>app = lambda { |env|
  [200, { 'Content-Type' => 'text/html' }, "Hello from Rack\n" ]
}
run app</programlisting>
          </example>

          Deploy the Rack application at a context-path of "/rack"
          since we already have the Rails application deployed at the
          root context.

        <screen><prompt>&gt;</prompt> <command>torquebox deploy --context-path=/rack</command>
Deployed: rack_example-knob.yml
    into: C:\Users\someone\torquebox-${project.version}\jboss\standalone\deployments</screen>
        </para>

        <para>
          Now you should be able to run TorqueBox and see both
          applications deployed.

        <screen><prompt>&gt;</prompt> <command>echo Y | jruby -S torquebox run</command>
...
19:25:38,049 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS018559: Deployed "rails_example-knob.yml"
19:25:38,050 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS018559: Deployed "rack_example-knob.yml"</screen>

          Visit <ulink url="http://localhost:8080"/> and <ulink
          url="http://localhost:8080/rack/"/> to see that both your
          Rails and Rack applications are deployed and working.
        </para>

        <para>
          Congratulations! You now know all the basics to proceed with
          the rest of this getting started guide when using
          Windows. The filesystem paths and command prompts shown in
          future chapters won't be Windows-specific, so be sure to
          translate any paths to the appropriate format before
          executing the example commands.
        </para>

        <para>Continue to <xref linkend="adding-torquebox-features"/>.</para>

      </section>

    </section>

    <section id="first-steps-rvm">
      <title>First Steps with RVM</title>

      <section>
        <title>Your First Rails Application</title>

        <para>
          Ensure you have a recent JRuby installed then install the
          <varname>torquebox-server</varname> gem into the global
          gemset.

        <screen><prompt>$</prompt> <command>rvm install jruby-${version.jruby}</command>
<prompt>$</prompt> <command>rvm use jruby-${version.jruby}@global</command>
<prompt>$</prompt> <command>gem install torquebox-server</command></screen>
        </para>

        <para>
          Create a directory and project-specific gemset for our
          example application.

        <screen><prompt>$</prompt> <command>mkdir -p ~/torquebox_examples/rails_example</command>
<prompt>$</prompt> <command>cd ~/torquebox_examples/rails_example</command>
<prompt>$</prompt> <command>rvm --rvmrc --create jruby-${version.jruby}@tb_rails_example</command></screen>
        </para>

        <para>
          Change to the Rails example directory, trust the generated
          .rvmrc file when prompted, and install Rails.

        <screen><prompt>$</prompt> <command>cd ~/torquebox_examples/rails_example</command>
====================================================================================
= NOTICE                                                                           =
====================================================================================
= RVM has encountered a new or modified .rvmrc file in the current directory       =
= This is a shell script and therefore may contain any shell commands.             =
=                                                                                  =
= Examine the contents of this file carefully to be sure the contents are          =
= safe before trusting it! ( Choose v[iew] below to view the contents )            =
====================================================================================
Do you wish to trust this .rvmrc file? (/Users/someone/torquebox_examples/rails_example/.rvmrc)
y[es], n[o], v[iew], c[ancel]> y
<prompt>$</prompt> <command>rvm gemset list</command>

gemsets for jruby-${version.jruby} (found in /Users/someone/.rvm/gems/jruby-${version.jruby})
   global
=> tb_rails_example

<prompt>$</prompt> <command>gem install rails</command>
...
Successfully installed rails-3.2.11
27 gems installed</screen>
        </para>

        <para>
          Create a new Rails application, add a simple scaffolded
          resource, deploy it to TorqueBox, and run TorqueBox.

        <screen><prompt>$</prompt> <command>rails new .</command>
...
Using rails (3.2.11) 
Installing sass (3.2.5) 
Installing sass-rails (3.2.6) 
Installing therubyrhino_jar (1.7.4) 
Installing therubyrhino (2.0.2) 
Installing uglifier (1.3.0) 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
<prompt>$</prompt> <command>rails g scaffold post title body:text</command>
...
      create      app/assets/stylesheets/posts.css.scss
      invoke  scss
      create      app/assets/stylesheets/scaffolds.css.scss
<prompt>$</prompt> <command>rake db:migrate</command>
==  CreatePosts: migrating ====================================================
-- create_table(:posts)
   -> 0.0060s
   -> 0 rows
==  CreatePosts: migrated (0.0080s) ===========================================

<prompt>$</prompt> <command>torquebox deploy</command>
Deployed: rails_example-knob.yml
    into: /Users/someone/.rvm/gems/jruby-${version.jruby}@global/gems/torquebox-server-${project.version}-java/jboss/standalone/deployments
<prompt>$</prompt> <command>torquebox run </command>
...
15:59:28,053 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "rails_example-knob.yml"</screen>
        </para>

        <para>
          Open <ulink url="http://localhost:8080"/> in your browser
          and you'll be greeted with the Rails "Welcome aboard"
          page. Navigate to <ulink
          url="http://localhost:8080/posts/"/> to see your scaffolded
          resource.
        </para>

        <para>
          Now edit
          <filename>~/torquebox_examples/rails_example/app/views/posts/index.html.erb</filename>
          then refresh the posts page in your browser and see your
          changes. Changes to your Rails application show up
          immediately in the browser, as expected. When you're done,
          press CTRL+C in the terminal to stop TorqueBox before
          continuing with the next steps.
        </para>

        <para>
          When you want to take advantage of TorqueBox-specific
          features, like we'll do in subsequent chapters, you'll need
          the <varname>torquebox</varname> gem in your application's
          Gemfile. However, since we're using
          <varname>torquebox-server</varname> under RVM to install
          TorqueBox, you'll want to ensure this gem is in the Gemfile
          for every application as well. If it's not you'll receive
          errors trying to use the <command>torquebox</command>
          because bundler will be unable to find the
          <varname>torquebox-server</varname> gem.

          <example>
            <title><filename>~/torquebox_examples/rails_example/Gemfile</filename></title>
            <programlisting>source 'https://rubygems.org'

gem 'rails', '3.2.11'

gem 'activerecord-jdbcsqlite3-adapter'
gem 'jruby-openssl'
gem 'json'

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'therubyrhino'
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

gem 'torquebox', '~> ${project.version}'
gem 'torquebox-server', '~> ${project.version}'</programlisting>
          </example>
        </para>

      </section>

      <section>
        <title>Subsequent Applications</title>

        <para>
          Deploying multiple applications to TorqueBox when using RVM
          and project-specific gemsets requires a small amount of
          extra work. To walk through the required steps, let's create
          a second Rack application to go with our Rails example
          application created earlier. If TorqueBox is still running
          stop it with CTRL+C in its terminal window before following
          the steps below.

      <screen><prompt>$</prompt> <command>mkdir -p ~/torquebox_examples/rack_example</command>
<prompt>$</prompt> <command>cd ~/torquebox_examples/rack_example</command>
<prompt>$</prompt> <command>rvm --rvmrc --create jruby-${version.jruby}@tb_rack_example</command>
<prompt>$</prompt> <command>cd ~/torquebox_examples/rack_example</command>
====================================================================================
= NOTICE                                                                           =
====================================================================================
= RVM has encountered a new or modified .rvmrc file in the current directory       =
= This is a shell script and therefore may contain any shell commands.             =
=                                                                                  =
= Examine the contents of this file carefully to be sure the contents are          =
= safe before trusting it! ( Choose v[iew] below to view the contents )            =
====================================================================================
Do you wish to trust this .rvmrc file? (/Users/someone/torquebox_examples/rack_example/.rvmrc)
y[es], n[o], v[iew], c[ancel]> y
<prompt>$</prompt> <command>rvm gemset list</command>

gemsets for jruby-${version.jruby} (found in /Users/someone/.rvm/gems/jruby-${version.jruby})
   global
=> tb_rack_example
   tb_rails_example

<prompt>$</prompt> <command>gem install rack</command>
Fetching: rack-1.5.0.gem (100%)
Successfully installed rack-1.5.0
1 gem installed
</screen>

          Now create a <filename>config.ru</filename> for our example
          rack application.
          <example>
            <title><filename>~/torquebox_examples/rack_example/config.ru</filename></title>
            <programlisting>app = lambda { |env|
  [200, { 'Content-Type' => 'text/html' }, "Hello from Rack\n" ]
}
run app</programlisting>
          </example>

          Deploy the Rack application at a context-path of "/rack"
          since we already have the Rails application deployed at the
          root context.

        <screen><prompt>$</prompt> <command>torquebox deploy --context-path=/rack</command>
Deployed: rack_example-knob.yml
    into: /Users/someone/.rvm/gems/jruby-${version.jruby}@global/gems/torquebox-server-${project.version}-java/jboss/standalone/deployments</screen>
        </para>

        <para>
          Now that two applications are deployed to TorqueBox, each
          with separate RVM gemsets, we hit an issue that trips up
          most users of RVM and TorqueBox. TorqueBox runs as a single
          process but RVM is really designed to have a separate
          process per project for gemsets to work out of the box. We
          can work around this by emulating the environment variables
          RVM sets when reading our <filename>.rvmrc</filename> in a
          <filename>torquebox.rb</filename> file for each application.

          <example>
            <title><filename>~/torquebox_examples/rack_example/torquebox.rb</filename></title>
            <programlisting>TorqueBox.configure do
  environment do
    GEM_HOME "#{ENV['rvm_path']}/gems/jruby-${version.jruby}@tb_rack_example"
    GEM_PATH "#{ENV['rvm_path']}/gems/jruby-${version.jruby}@tb_rack_example:#{ENV['rvm_path']}/gems/jruby-${version.jruby}@global"
  end
end</programlisting>
          </example>

          <example>
            <title><filename>~/torquebox_examples/rails_example/config/torquebox.rb</filename></title>
            <programlisting>TorqueBox.configure do
  environment do
    GEM_HOME "#{ENV['rvm_path']}/gems/jruby-${version.jruby}@tb_rails_example"
    GEM_PATH "#{ENV['rvm_path']}/gems/jruby-${version.jruby}@tb_rails_example:#{ENV['rvm_path']}/gems/jruby-${version.jruby}@global"
  end
end</programlisting>
          </example>

          Now you should be able to run TorqueBox and see both
          applications deployed.

        <screen><prompt>$</prompt> <command>torquebox run</command>
...
19:25:38,049 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS018559: Deployed "rails_example-knob.yml"
19:25:38,050 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS018559: Deployed "rack_example-knob.yml"</screen>

          Visit <ulink url="http://localhost:8080"/> and <ulink
          url="http://localhost:8080/rack/"/> to see that both your
          Rails and Rack applications are deployed and working.
        </para>

        <para>
          Congratulations! You now know all the basics to proceed with
          the rest of this getting started guide when using RVM. The
          most important thing to remember is to add the
          <filename>torquebox.rb</filename> that sets the
          <varname>GEM_HOME</varname> and <varname>GEM_PATH</varname>
          environment variables for each application that uses a
          project-specific gemset.
        </para>

        <para>Continue to <xref linkend="adding-torquebox-features"/>.</para>
      </section>
    </section>

   </chapter>

  <chapter id="adding-torquebox-features">
    <title>Adding TorqueBox Features</title>

    <para>
      This chapter builds upon the simple Rails application we created
      in <xref linkend="first-steps"/> by modifying it to take
      advantage of TorqueBox features.
    </para>

    <section id="features-rails-template">
      <title>TorqueBox Rails Template</title>

      <para>
        TorqueBox ships with a Rails template that we can use to
        automatically add <filename>torquebox</filename> to the
        Gemfile, convert the session store to the optional TorqueBox
        clustered session storage, setup all ActiveRecord objects to
        have <classname>TorqueBox::Backgroundable</classname> methods
        available, and add some TorqueBox-specific Rake tasks.

        <screen><prompt>$</prompt> <command>cd ~/torquebox_examples/rails_example</command>
<prompt>$</prompt> <command>torquebox rails</command>
       apply  .../torquebox-${project.version}/share/rails/template.rb
     gemfile    torquebox (${project.version})
      remove    config/initializers/session_store.rb
 initializer    session_store.rb
 initializer    active_record_backgroundable.rb
    rakefile    torquebox.rake</screen>
      </para>
    </section>

    <section id="features-backgroundable">
      <title>Running Tasks in the Background</title>

      <para>
        To illustrate how TorqueBox makes it effortless to run
        long-running tasks in the background, let's first add a
        long-running task to our <classname>Post</classname>
        model. After each <classname>Post</classname> is created, lets
        publish a message to our favorite social network linking to
        that post. For simplicitly we'll just log a message and sleep
        for a few seconds to simulate the publish.

        <example>
          <title><filename>~/torquebox_examples/rails_example/app/models/post.rb</filename></title>
          <programlisting><![CDATA[class Post < ActiveRecord::Base
  attr_accessible :body, :title

  after_create :publish_to_social_network

  def publish_to_social_network
    puts "Publishing '#{title}' to our favorite social network"
    sleep(5)
    puts "Post published"
  end
end]]></programlisting>
        </example>

        Start TorqueBox if it isn't already running via
        <command>torquebox run</command> (Windows users remember to
        use <command>echo Y | jruby -S torquebox run</command>),
        navigate to <ulink url="http://localhost:8080/posts/"/>,
        create a new post, and observe the output from the TorqueBox
        console.

        <screen>09:11:19,746 INFO  [stdout] (http-localhost/127.0.0.1:8080-1) Publishing 'Chunky Bacon Fever' to our favorite social network
09:11:24,747 INFO  [stdout] (http-localhost/127.0.0.1:8080-1) Post published</screen>

        As you can see, it took 5 seconds to publish the post and
        during that five seconds the browser was waiting on a response
        from the server. There's no reason the browser needs to wait
        until the post is published, so let's see how easy it is to
        convert the publish_to_social_network method to run in the
        background.

        <example>
          <title><filename>~/torquebox_examples/rails_example/app/models/post.rb</filename></title>
          <programlisting><![CDATA[class Post < ActiveRecord::Base
  attr_accessible :body, :title

  after_create :publish_to_social_network
  always_background :publish_to_social_network

  def publish_to_social_network
    puts "Publishing '#{title}' to our favorite social network"
    sleep(5)
    puts "Post published"
  end
end]]></programlisting>
        </example>

        Create a new post and you'll see that the browser returns
        immediately and in the TorqueBox console the messaging runtime
        will spin up (since
        <classname>TorqueBox::Backgroundable</classname> uses
        messaging and the first message we send starts the messaging
        runtime pool) and publish the post to our favorite social
        network in the background.
      </para>
    </section>

    <section id="features-scheduled-jobs">
      <title>Scheduled Jobs</title>

      <para>
        TorqueBox also has built-in support for scheduled jobs (like
        Cron or Windows Scheduler) but in a cross-platform way. To see
        how scheduled jobs work, let's create a job that logs the
        number of posts in our database every 10 seconds. To do this
        create a <classname>PostCounter</classname> class in the
        <filename>app/jobs</filename> directory created for us by the
        TorqueBox Rails template earlier.

        <example>
          <title><filename>~/torquebox_examples/rails_example/app/jobs/post_counter.rb</filename></title>
          <programlisting><![CDATA[class PostCounter

  def run
    puts "#{Post.count} posts in the database"
  end

end]]></programlisting>
        </example>

        We also have to tell TorqueBox about this new job and when to
        run it. To do that, edit the
        <filename>config/torquebox.yml</filename> created for us by
        the TorqueBox Rails template to have the contents below.

        <example>
          <title><filename>~/torquebox_examples/rails_example/config/torquebox.yml</filename></title>
          <programlisting>---
# This is the TorqueBox configuration file. Refer to the TorqueBox
# documentation at http://torquebox.org/documentation/current/ 
# for all configuration options.
web:
  context: "/"
jobs:
  post_counter:
    job: PostCounter
    cron: "*/10 * * * * ?"</programlisting>
        </example>

        Since we had to make a change to
        <filename>config/torquebox.yml</filename>, we need to restart
        TorqueBox for the job to start running. After restarting
        TorqueBox you should see output like below every 10 seconds.

        <screen>09:45:30,029 INFO  [stdout] (JobScheduler$rails_example-knob.yml_Worker-2) 2 posts in the database</screen>
      </para>
    </section>

    <section id="features-services">
      <title>Long-Running Services</title>

      <para>
        TorqueBox supports the notion of long-running services that
        get started when the application is deployed and stopped when
        the application is undeployed. This could be useful to connect
        a client to a streaming API service (like that provided by
        some social networks), monitor a resource for changes and take
        some action, or many other things. As an example, we'll create
        a service that pretends to connect to a social network and
        submit post ideas to a queue for later processing.

        <example>
          <title><filename>~/torquebox_examples/rails_example/app/services/post_idea_grabber.rb</filename></title>
          <programlisting><![CDATA[class PostIdeaGrabber

  def initialize(options)
    @queue = TorqueBox::Messaging::Queue.new(options['queue_name'])
  end

  def start
    puts "******** Starting PostIdeaGrabber ********"
    Thread.new do
      until @done
        @queue.publish("Random idea #{rand(100)}")
        sleep 2
      end
    end
  end

  def stop
    @done = true
  end
end]]></programlisting>
        </example>

        Just like with our scheduled job, we need to tell TorqueBox
        about this new service and the message queue it uses.

        <example>
          <title><filename>~/torquebox_examples/rails_example/config/torquebox.yml</filename></title>
          <programlisting>---
# This is the TorqueBox configuration file. Refer to the TorqueBox
# documentation at http://torquebox.org/documentation/current/ 
# for all configuration options.
web:
  context: "/"
jobs:
  post_counter:
    job: PostCounter
    cron: "*/10 * * * * ?"
services:
  post_idea_grabber:
    service: PostIdeaGrabber
    config:
      queue_name: "/queue/post_ideas"
queues:
  /queue/post_ideas:
    durable: false</programlisting>
        </example>

        Restart TorqueBox and you should see the service starting in
        the logs.

        <screen>10:43:56,316 INFO  [org.torquebox.core.runtime] (MSC service thread 1-7) Created ruby runtime (ruby_version: RUBY1_8, compile_mode: JIT, app: rails_example, context: services) in 17.73s
10:43:56,325 INFO  [stdout] (MSC service thread 1-5) ******** Starting PostIdeaGrabber ********</screen>
      </para>
    </section>

    <section id="features-processors">
      <title>Message Processors</title>

      <para>
        We have a long-running service placing messages on a queue but
        now we need something to consume those messages and do
        something with them. TorqueBox has a feature designed
        specifically for this purpose - message processors. We'll
        create a message processor to randomly choose some of the
        ideas and create new posts from them.

        <example>
          <title><filename>~/torquebox_examples/rails_example/app/processors/post_idea_processor.rb</filename></title>
          <programlisting><![CDATA[class PostIdeaProcessor < TorqueBox::Messaging::MessageProcessor

  def on_message(message)
    if (rand(10) > 8)
      puts "Creating new post from idea #{message}"
      Post.create(:title => message, :body => "Random post created from an idea")
    end
  end

end]]></programlisting>
        </example>

        As usual we need to edit
        <filename>config/torquebox.yml</filename> so TorqueBox knows
        how to wire up this new message processor.

        <example>
          <title><filename>~/torquebox_examples/rails_example/config/torquebox.yml</filename></title>
          <programlisting>---
# This is the TorqueBox configuration file. Refer to the TorqueBox
# documentation at http://torquebox.org/documentation/current/ 
# for all configuration options.
web:
  context: "/"
jobs:
  post_counter:
    job: PostCounter
    cron: "*/10 * * * * ?"
services:
  post_idea_grabber:
    service: PostIdeaGrabber
    config:
      queue_name: "/queue/post_ideas"
queues:
  /queue/post_ideas:
    durable: false
messaging:
  /queue/post_ideas: PostIdeaProcessor</programlisting>
        </example>

        Restart TorqueBox and you should see new posts being created
        from the random ideas.

        <screen>11:10:31,891 INFO  [stdout] (Thread-2 (HornetQ-client-global-threads-9512807)) Creating new post from idea Random idea 66</screen>
      </para>

      <para>
        Congratulations! You now have an application that uses many of
        the features of TorqueBox. For detailed documentation on
        TorqueBox, look for the User Manual in the same location you
        found this Getting Started Guide.
      </para>
    </section>
  </chapter>

  <chapter id="poorsmatic">
    <title>Poorsmatic</title>

    <para>
      This chapter shows you how to build a simple web application based
      on <ulink url="http://sinatrarb.com">Sinatra</ulink>. Although the
      application itself is very small, it uses most of the features of TorqueBox.
    </para>

    <para>
      We will create an application called Poorsmatic, a "poor man's
      <ulink url="http://getprismatic.com/">Prismatic</ulink>". This
      is a truly awful content discovery service that searches twitter
      using given terms, then extracts URLs from matching tweets and
      counts the occurrence of the search terms in the content from
      each URL.
    </para>

    <para>
      If you don't get it - don't worry - everything will be clear later.
    </para>

    <section id="poorsmatic-source">
      <title>Get the source</title>

      <para>
        The source for our example application is available in the
        <filename>examples/poorsmatic/</filename> directory of the
        TorqueBox source zip. To get started you need to download and
        unzip the source zip file.

        <screen><prompt>$</prompt> <command>wget http://torquebox.org/release/org/torquebox/torquebox-dist/${project.version}/torquebox-dist-${project.version}-src.zip
unzip torquebox-dist-${project.version}-src.zip</command></screen>
      </para>

      <note>
        <title>File location</title>
        <para>
          Unless stated otherwise, every file path used in this guide
          will be relative to the
          <filename>examples/poorsmatic/</filename> directory located
          under the unzipped directory.
        </para>
      </note>
    </section>

    <section id="poorsmatic-overview">
      <title>Poorsmatic application overview</title>

      <para>
        <mediaobject>
          <imageobject>
            <imagedata align="center" fileref="images/poorsmatic-overview.png" format="PNG" />
          </imageobject>
        </mediaobject>
      </para>

      <para>
        Our main data source for the application are tweets from the
        Twitter stream.  We'll use a TorqueBox service
        (<varname>TwitterService</varname>) to do that. The service itself
        will be notified about which keywords we're interested via the
        <varname>terms</varname> topic. Received tweets will be scanned for
        URLs and those URLs will be put on to <varname>urls</varname>
        queue for processing. The <varname>URLScraper</varname> will be
        responsible for visiting each URL from the <varname>urls</varname>
        queue and counting the matching search terms found in the
        <varname>&lt;body/&gt;</varname> tag on the page. The resulting
        URLs and counts will be stored in the database. The final
        piece is a web interface for viewing the URLs and editing the
        search terms.
      </para>

      <section>
        <title>Web</title>

        <para>
          We will use the Sinatra web framework for this
          application. It is a very simple framework for writing web
          applications quickly, and provides all the web features we
          need for this application.
        </para>

        <para>
          If you're new to Sinatra, see the <ulink
          url="http://www.sinatrarb.com/">project homepage</ulink> for
          lots of good examples and documentation.
        </para>
      </section>

      <section>
        <title>Configuration</title>

        <section>
          <title>ORM</title>

          <para>
            The object-relational mapper we've chosen is <ulink
            url="http://datamapper.org/">DataMapper</ulink>.  To see
            the DataMapper configuration details, look in
            <filename>torquebox_init.rb</filename>.  Our models are
            defined in the <filename>models/</filename> directory.
          </para>

          <para>
            In this quick overview of the app we will not go into the
            full details of the models - feel free to peruse that code
            at your leisure.
          </para>
        </section>
      </section>
    </section>

    <section id="poorsmatic-launch">
      <title>Launch the application</title>

      <para>
        It's time to launch the application for the first time. First, we need to
        start TorqueBox by executing <command>torquebox run</command>. The output
        should be similar to:

        <screen><prompt>$</prompt><command>torquebox run</command>
...
14:34:42,734 INFO  [org.torquebox.jobs.as] Initializing TorqueBox Jobs Subsystem
14:34:42,735 INFO  [org.torquebox.services.as] Initializing TorqueBox Services Subsystem
14:34:42,738 INFO  [org.torquebox.core.as] Initializing TorqueBox Core Subsystem
14:34:42,740 INFO  [org.torquebox.security.as] Initializing TorqueBox Auth Subsystem
14:34:42,740 INFO  [org.torquebox.web.as] Initializing TorqueBox Web Subsystem
14:34:42,733 INFO  [org.torquebox.cdi.as] Initializing TorqueBox CDI Subsystem
14:34:42,792 INFO  [org.torquebox.stomp.as] Initializing TorqueBox STOMP Subsystem
14:34:42,791 INFO  [org.projectodd.polyglot.stomp.as] Initializing Polyglot STOMP Subsystem
14:34:42,807 INFO  [org.projectodd.polyglot.hasingleton.as] Initializing HA-Singleton Subsystem
14:34:42,808 INFO  [org.projectodd.polyglot.cache.as] Initializing Polyglot Cache Subsystem
14:34:42,854 INFO  [org.torquebox.core.as] Welcome to TorqueBox AS - http://torquebox.org/
14:34:42,855 INFO  [org.torquebox.core.as]   version........... ${project.version}
14:34:42,856 INFO  [org.torquebox.core.as]   build............. 74
14:34:42,857 INFO  [org.torquebox.core.as]   revision.......... 530d7d30a5ba5ca953eba21b2aa6df1bf4022649
...
14:35:02,072 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management
14:35:02,073 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
14:35:02,073 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015874: JBoss AS 7.1.x.incremental.129 "Arges" started in 21875ms - Started 281 of 400 services (118 services are passive or on-demand)</screen>

        Now we're ready to deploy the application. To do so go to the <filename>examples/poorsmatic/</filename> directory
        and execute <command>torquebox deploy</command>:

        <screen><prompt>$</prompt><command>torquebox deploy</command>
Deployed: poorsmatic-knob.yml
    into: /Users/someone/torquebox-${project.version}/jboss/standalone/deployments</screen>

        You can now reach your application at <ulink url="http://localhost:8080/poorsmatic/"/>. If you see
        "Hello from Poorsmatic!", it means that everything worked perfectly!
      </para>

      <para>
        Congratulations! You now have a running web application. In
        the next few steps we will discuss the TorqueBox features we
        used to build it.
      </para>
    </section>

    <section id="poorsmatic-basic">
      <title>Basic TorqueBox features</title>

      <para>
        In this section we'll discuss the basic TorqueBox features which made it possible to build this
        application.
      </para>

      <section>
        <title>Deployment descriptor</title>

        <para>
          The deployment descriptor is a file that contains TorqueBox
          specific configuration for an application, and is read by
          TorqueBox at deploy time. The descriptor can use a pure Ruby
          DSL or a YAML format.  In our case, we'll use the Ruby DSL
          syntax. Please refer to the TorqueBox manual to learn more
          about deployment descriptors.
        </para>

        <para>
          TorqueBox does a pretty good job at guessing what type of
          application you are trying to deploy. If it's a Rack based
          application, it will be registered by default at the root
          context (/). We can change this (and many other things) by
          using a deployment descriptor.

          <example>
            <title><filename>torquebox.rb</filename></title>
            <programlisting><![CDATA[TorqueBox.configure do
  web do
    ...
    context "/poorsmatic"
    ...
  end
end]]></programlisting>
          </example> 

          As you can see, we chose the <varname>/poorsmatic</varname>
          context which makes the application available at the <ulink
          url="http://localhost:8080/poorsmatic/">/poorsmatic</ulink>
          context.
        </para>

        <para>
          This simple setting lets you deploy many applications to one
          TorqueBox server, each with a unique context path.
        </para>

      </section>

      <section>
        <title>Service</title>

        <para>
          In our application we filter the Twitter stream with a set
          of keywords.  The best way in TorqueBox to run something
          that needs a constant connection is to implement it as a
          TorqueBox service. Below you can find a simple skeleton service.

          <example>
            <title>TorqueBox service skeleton</title>
            <programlisting><![CDATA[class AService
  def initialize(credentials = {})
  end

  def start
  end

  def stop
  end
end]]></programlisting>
          </example>

          The code is fairly self-explanatory. The only thing you need
          to keep in mind is that the <varname>start</varname> method is
          executed when you deploy the service. Similarly the
          <varname>stop</varname> method is executed when you undeploy the
          service. It's as simple as that.
        </para>

        <para>
          In our application we'll use the <ulink url="https://github.com/tobias/twitter4j4r">twitter4j4r</ulink>
          Twitter client (please don't ask about the name). 

          <example>
            <title><filename>twitter_service.rb</filename></title>
            <programlisting><![CDATA[require 'twitter4j4r'

class TwitterService
  ...
  def initialize(credentials = {})

    @terms = []

    @client = Twitter4j4r::Client.new(
        :consumer_key     => credentials['consumer_key'],
        :consumer_secret  => credentials['consumer_secret'],
        :access_token     => credentials['access_token'],
        :access_secret    => credentials['access_secret']
    )

    @client.on_exception do |exception|
      puts "An error occured while reading the stream: #{exception.message}"
    end
  end

  def start
    @client.track(*@terms) do |status, client|
    end
  end

  def stop
    @client.stop
  end
end]]></programlisting>
          </example>

          Now we need to inform TorqueBox that we want to deploy a
          service implemented by <varname>TwitterService</varname> class. We
          do so in our deployment descriptor
          (<filename>torquebox.rb</filename>).  You might also ask how
          we inject the credentials required to connect to Twitter?
          Yes, you're right, the deployment descriptor.

          <example>
            <title><filename>torquebox.rb</filename></title>
            <programlisting><![CDATA[TorqueBox.configure do
  ...
  service TwitterService do
    name 'twitter-service'
    config do
      consumer_key 'Consumer key'
      consumer_secret 'Consumer secret'
      access_token 'Access token'
      access_secret 'Access token secret'
    end
  end
end]]></programlisting>
          </example>

          Before you deploy the application make sure you use the correct credentials. You can
          generate them on the <ulink url="https://dev.twitter.com/apps">Twitter apps</ulink>
          page. Just create a new application and you're ready to rock.
        </para>

        <para>
          You may wonder how we update the keyword list we want to watch on Twitter?
          We'll use the messaging features of TorqueBox.
        </para>

      </section>

      <section>
        <title>Messaging</title>

        <para>
          Messaging allows us to create loosely coupled applications. Using queues and topics
          as well as message producers and consumers is very easy, so let's start right away!
          If you're new to the messaging terms, don't fear - just take a look at the messaging
          section of the TorqueBox manual.
        </para>

        <section>
          <title>Queue and topic deployment</title>

          <para>
            We need to create a queue and a topic. We'll use the topic to send/receive keywords
            we want to watch on Twitter and we'll use the queue to send URLs from tweets
            containing one or more specified keywords. Creating them is very simple, we just need
            to add the queue and topic directives to the deployment descriptor.

            <example>
              <title><filename>torquebox.rb</filename></title>
              <programlisting><![CDATA[TorqueBox.configure do
  ...
  queue '/queues/urls'
  topic '/topics/terms'
end]]></programlisting>
            </example>

            That's everything required to deploy a queue and a topic with your application.
            Both will be started when the application is deployed, and stopped when it is
            undeployed. Handy feature, isn't it?
          </para>

        </section>

        <section>
          <title>Message consumers</title>

          <para>
            It's pretty easy to consume a message from a queue or topic. You use message
            processors.

            <example>
              <title><filename>term_consumer.rb</filename></title>
              <programlisting><![CDATA[class TermConsumer < TorqueBox::Messaging::MessageProcessor
  ...
  def on_message(message)
    # do stuff here
  end
end]]></programlisting>
            </example>

            A new message processor instance will be created for each
            message that arrives to the queue.  The message itself
            will be passed to the <varname>on_message</varname> method.
            You can do whatever you want with it afterwards. In our
            case we want to update the keywords in the twitter
            service. The easiest way to do that is to get access
            to the service and execute an update method on it. Let's
            do it!

            <example>
              <title><filename>term_consumer.rb</filename></title>
              <programlisting><![CDATA[class TermConsumer < TorqueBox::Messaging::MessageProcessor
  include TorqueBox::Injectors

  def initialize
    @twitter_service = fetch('service:twitter-service')
  end

  def on_message(terms)
    @twitter_service.update(terms)
  end
end]]></programlisting>
            </example>

            Each time a <varname>TermConsumer</varname> message processor
            instance is created, TorqueBox will inject
            the <varname>TwitterService</varname> service into the
            processor. Then terms will be passed to the
            <varname>on_message</varname> method and the <varname>update</varname>
            method will be executed on the service itself. The only
            thing left now is to show the <varname>update</varname>
            method in the <varname>TwitterService</varname> class.

            <example>
              <title><filename>twitter_service.rb</filename></title>
              <programlisting><![CDATA[class TwitterService
  def initialize(credentials = {})
    @terms = []
    ...
  end

  def update(terms)
    @terms = terms

    stop
    start
  end
  ...
end]]></programlisting>
            </example>

            Execution of this method will update the terms list. Additionally the Twitter client
            will be restarted to watch for the new keywords.
          </para>

          <para>
            The last task left with setting up this processor is to
            wire the message consumer to the queue or topic.  We use
            the deployment descriptor. Here's how:

            <example>
              <title><filename>torquebox.rb</filename></title>
              <programlisting><![CDATA[TorqueBox.configure do
  ...
  queue '/queues/urls' do
    processor UrlScrapper do
      concurrency 4
    end
  end

  topic '/topics/terms' do
    processor TermConsumer
  end
  ...
end]]></programlisting>
            </example>

            You may ask yourself what the <varname>concurrency</varname> parameter means. This tells
            TorqueBox how many message processors of the selected type should be connected
            to the selected queue. This is very handy if you expect to have messages arriving
            faster than you can process them.
          </para>

          <para>
            You can find another message processor that is used to
            retrieve and parse web pages in
            <filename>url_scrapper.rb</filename>. Since
            <varname>URLScrapper</varname> doesn't do anything fancy other
            than counting the words in <varname>&lt;body&gt;</varname> and
            saving the result to the database, we won't go into its details.
          </para>
        </section>

        <section>
          <title>Producing messages</title>

          <para>
            You know now how to receive messages from topics (or queues), but the remaining question is
            how to put new messages on to the queue? We'll look at that next.
          </para>

          <para>
            In addition to retrieving tweets for particular keywords,
            the <varname>TwitterService</varname> also extracts URLs from
            the received tweets. These URLs are then placed on to a
            queue for later processing.
          </para>

          <para>
            We will use the <ulink
            url="https://rubygems.org/gems/twitter-text">twitter-text</ulink>
            gem to retrieve the URLs.

            <example>
              <title><filename>twitter_service.rb</filename></title>
              <programlisting><![CDATA[require 'twitter-text'

class TwitterService
  include TorqueBox::Injectors
  ...
  def start
    @client.track(*@terms) do |status, client|
      urls = extract_urls(status.text)

      unless urls.empty?
        queue = fetch('/queues/urls')

        urls.each do |url|
          queue.publish(url)
        end
      end
    end
  end
  ...
end]]></programlisting>
            </example>

            For each received tweet we try to find any URLs in it.
            If we find at least one, we send this URL as a string to the queue. To do this
            we first inject the queue and then execute the <varname>publish</varname> method
            on it. Easy.

          </para>
        </section>

      </section>

    </section>
    <section>
      <title>Wrapping up</title>

      <para>
        Congratulations! You now know a little about a few of the
        features of TorqueBox. There are still many to explore.  To
        learn more about them, take a look at the TorqueBox manual.
      </para>

      <para>
        The Poorsmatic application was just a simple example. Feel
        free to go through the source code to in detail how it was
        done.
      </para>
    </section>

  </chapter>

</book>
