<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
  ~  Copyright (c) 2009, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
  ~
  ~  WSO2 Inc. licenses this file to you under the Apache License,
  ~  Version 2.0 (the "License"); you may not use this file except
  ~  in compliance with the License.
  ~  You may obtain a copy of the License at
  ~
  ~    http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~  Unless required by applicable law or agreed to in writing,
  ~  software distributed under the License is distributed on an
  ~  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  ~  KIND, either express or implied.  See the License for the
  ~  specific language governing permissions and limitations
  ~  under the License.
  -->

<!DOCTYPE html
     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>
    <title>
      WSO2 ESB - Deployment Guide
    </title>
    <link href="css/esb-docs.css" rel="stylesheet"/>
    <link href="styles/dist-docs.css" rel="stylesheet" type="text/css" media="all"/>
  </head>
  <body xml:lang="en">
      [ <a href="docs_index.html"> Documentation Index </a> ]
    <h1>
      WSO2 Enterprise Service Bus (ESB) Deployment Guide
    </h1>
    <p>
        Deploying the WSO2 ESB correctly on your infrastructure is a vital task for the success
        of the usage of the ESB. You should first analyze the requirement and then select the
        best matching deployment mode. There are different set of possible deployment modes with
        different configurations.
    </p>
    <h2>
      Available Deployment options
    </h2>
    <p>
      <a href="installation_guide.html">Standalone Deployment Guide</a> :
      Describes the default standalone installation and deployment of the ESB
    </p>
    <p>
      <a href="webapp_deployment_guide.html">Webapp Deployment Guide</a> :
      Contains the information on deploying the ESB on an Application Server, this particular guide
      explains the deployment of an existing Tomcat Servlet Container.
    </p>

    <h2>Clustered Deployment Guide</h2>
    <p>
        This document describes the steps you need to follow to setup a working WSO2 ESB cluster in your environment.
        <br/><br/>Clustering the ESB has two different aspects.
    </p>
      <ol>
          <li><a href="#confshare">Configuration sharing across the cluster nodes</a></li>
          <li><a href="#runtimeshare">Runtime state replication among the cluster nodes</a></li>
      </ol>

    <h3>
        <a name="confshare">Configuration sharing across the cluster nodes</a>
    </h3>

    <p>The configuration sharing is done using the WSO2 Governance Registry. All the ESB nodes in the
        cluster are pointed to one instance of WSO2 G-Reg and through this registry configuration is shared.
    </p>
    <p>
        WSO2 G-Reg consists of three registry spaces.
    </p>
  <ul>
      <li>Local Registry - Per running instance of every product</li>
      <li>Configuration Registry - Shared among all the instance of a cluster of one product</li>
      <li>Governance Registry - Centrally managed &amp; shared across multiple products and multiple
          instances of those</li>
  </ul>
      <p>So, when it comes to ESB clustering, we will be using local registry per each instance,
          mounting the configuration registry of each ESB instance to the same config registry and
          sharing the governance space among GReg and 2-ESB instances.
      </p>
      <p>First lets see how to set up ESB instances pointing to a single G-Reg. </p>
      <p>
          WSO2 ESB Cluster Deployment Diagram<br/>
          <img alt="ESB clustered with GReg" src="images/esb-4-cluster.png"/>
      </p>
      <p><strong>Setting UP WSO2 ESB cluster with GReg</strong></p>
      <ul>
          <li>Extract the WSO2 ESB 4.0.0 distribution and as the first step we need to configure the database configuration.</li>
          <li>Both GReg and ESB are shipped embedded H2 registry. However, for clustering purposes we will be using MySQL instead.</li>
          <li>In the following setup, we have GReg running on mysql database which means it's local/config/governance registries are store in a mysql database and it's user-manager tables are also inside the same database.</li>
          <li>In ESB instances,
            <ul>
                <li>Both master and slave ESBs are using unique local registries. </li>
                <li>Both configuration registries mounted to the same directory of GReg.</li>
                <li>Governance registry is mounted to the governance registry of GReg</li>
            </ul>
          </li>
          <li>All the ESB instances in the cluster are sharing a common database for user-manager. (if you are using an LDAP you do not have to use a database for user-manager.)</li>
      </ul>
      <p>
          (This documentation http://wso2.org/project/registry/3.5.0/docs/user_guide/registry_config.html contains database
          configurations with different databases and we recommend you to go through it if you are using a
          different database server other than mysql.)
     </p>

      <p><strong>ESB cluster database configuration</strong></p>

      <table border="1">
          <tr>
              <td>Instance Name</td>
              <td>Registry Space</td>
              <td>Instance Name <br/>Registry Space Mysql database name/mounted path (x.x.x.x)</td>
          </tr>
          <tr>
              <td>ESB Master (x.x.x.x)</td>
              <td>local</td>
              <td>amamaster</td>
          </tr>
           <tr>
              <td></td>
              <td>config</td>
              <td>amagregdb /_system/esbConfig</td>
          </tr>
           <tr>
              <td></td>
              <td>governance</td>
              <td>amagregdb /_system/governance</td>
          </tr>
           <tr>
              <td></td>
              <td>user-manager</td>
              <td>amausermgtdb</td>
          </tr>
           <tr>
              <td>ESB Slave1 (x.x.x.x)</td>
              <td>local</td>
              <td>amaslave1</td>
          </tr>

          <tr>
              <td></td>
              <td>config</td>
              <td>amagregdb /_system/esbConfig</td>
          </tr>
          <tr>
              <td></td>
              <td>governance</td>
              <td>amagregdb /_system/governance</td>
          </tr>
          <tr>
              <td></td>
              <td>user-manager</td>
              <td>amausermgtdb</td>
          </tr>
          <tr>
              <td>GREG (x.x.x.x)</td>
              <td>All</td>
              <td>amagregdb</td>
          </tr>
      </table>

      <p>In the above table there are 5 separate databases with following names </p>
      <ul>
          <li>amagregdb</li>
          <li>amausermgtdb</li>
          <li>amaslave1</li>
          <li>amamaster</li>
      </ul>

      <p>If you are having your database remotely, please
          <a href=" http://www.debianhelp.co.uk/remotemysql.htm">configure mysql instance to allow remote
          connections to accept.</a></p>

      <p><strong>Running Multiple instance of the WSO2 Carbon Servers in the same machine</strong></p>
      <p>If you are running multiple instance same or different WSO2 Product Instances, then you need to
          configure ports for each instance. You can configure $CARBON_HOME/repository/conf/carbon.xml by using portOffset
      </p>
      <pre xml:space="preserve">
          &lt;Offset&gt;0&lt;/Offset&gt;
      </pre>
      <p>Please provide + Offset value</p>
	  <p>E.g: If Offset=2 and HTTPS port=9443, will be set the effective HTTPS port to 9445</p>

	  
	  <h4> Settings for Governance Registry</h4>
      <p>
         If you see the table above you can see that we are using a single database
          for all the queries in GREG instance. So we need to change the configuration in registry.xml and user-mgt.xml.
      </p>
	  
      <p>Go to  GREG_HOME/repository/conf/registry.xml file remove the original dbConfig element and add the
          database configuration below. (IP addresses and database urls have to be changed acccording to your setup).</p>
      <pre xml:space="preserve">
   &lt;currentDBConfig&gt;wso2registry&lt;/currentDBConfig&gt;
   &lt;readOnly&gt;false&lt;/readOnly&gt;
   &lt;registryRoot&gt;/&lt;/registryRoot&gt;
   &lt;dbConfig name=&quot;wso2registry&quot;&gt;
     &lt;url&gt;jdbc:mysql://x.x.x.x:3306/amagregdb?autoReconnect=true&lt;/url&gt;
        &lt;userName&gt;root&lt;/userName&gt;
        &lt;password&gt;root123&lt;/password&gt;
        &lt;driverName&gt;com.mysql.jdbc.Driver&lt;/driverName&gt;
        &lt;maxActive&gt;50&lt;/maxActive&gt;
        &lt;maxWait&gt;60000&lt;/maxWait&gt;
        &lt;minIdle&gt;5&lt;/minIdle&gt;
    &lt;/dbConfig&gt;
  </pre>

      <p>
          Go to GREG_HOME/repository/conf/user-mgt.xml file and change the database configuration as below(IP addresses and urls have to be changed according to your setup).
      </p>
      <pre xml:space="preserve">
    &lt;Property name=&quot;url&quot;&gt;jdbc:mysql://x.x.x.x:3306/amagregdb?autoReconnect=true&lt;/Property&gt;
    &lt;Property name=&quot;userName&quot;&gt;root&lt;/Property&gt;
    &lt;Property name=&quot;password&quot;&gt;root123&lt;/Property&gt;
    &lt;Property name=&quot;driverName&quot;&gt;com.mysql.jdbc.Driver&lt;/Property&gt;
    &lt;Property name=&quot;maxActive&quot;&gt;50&lt;/Property&gt;
    &lt;Property name=&quot;maxWait&quot;&gt;60000&lt;/Property&gt;
    &lt;Property name=&quot;minIdle&quot;&gt;5&lt;/Property&gt;
       </pre>


      <p>Copy mysql jdbc driver library to GREG_HOME/repository/components/lib direcotry since by default we do not ship the mysql drivers in GREG.</p>
      <p>If we examine the above configuration we can see that we are pointing the same database (amagregdb)for registry and user store .</p>
		<p>Start the GREG instance with <strong>-Dsetup</strong>
	      (This will create tables for user manager database and registry database(pick the database configuration from currentDBConfig element in registry.xml
			since there might be number of database configurations in your registry.xml which we put
	       to perform mounting from other databases but only one database configuration is configured as currentDBConfig)).
      </p>
	  
      <p>After successfully starting GREG instance create following directory from GREG's management console. Go to 
	  management console-->Registry browser and create "esbConfig" collection under "system" path.	  
          Configurations will be  mounted by ESB instances running in the cluster to this directory.<strong>( /_system/esbConfig)</strong></p>
		  
		<h4> Settings for ESB Master Node</h4>
		
      <p>Here we are changing the default database configuration to point master node's local registry to <strong>amamaster</strong> and will be poinetd the user manager database
	  to <strong>amausermgtdb</strong> . Here ESB master node's configuration and Governance registriy's configuration also will be mounted from GREG database.</p>

      <p>Let's first add local registry configuration and user-manager configuration.</p>
      <p>Open the ESB_HOME/repository/conf/registry.xml file remove the original dbConfig element and add the database configuration below.
          (IP addresses and database urls have to be changed according to your setup).</p>

      <pre xml:space="preserve">
    &lt;currentDBConfig&gt;wso2registry&lt;/currentDBConfig&gt;
        &lt;readOnly&gt;false&lt;/readOnly&gt;
       &lt;registryRoot&gt;/&lt;/registryRoot&gt;
        &lt;dbConfig name=&quot;wso2registry&quot;&gt;
     &lt;url&gt;jdbc:mysql://x.x.x.x:3306/amamaster?autoReconnect=true&lt;/url&gt;
        &lt;userName&gt;root&lt;/userName&gt;
        &lt;password&gt;root123&lt;/password&gt;
        &lt;driverName&gt;com.mysql.jdbc.Driver&lt;/driverName&gt;
        &lt;maxActive&gt;50&lt;/maxActive&gt;
        &lt;maxWait&gt;60000&lt;/maxWait&gt;
        &lt;minIdle&gt;5&lt;/minIdle&gt;
    &lt;/dbConfig&gt;
      </pre>


      <p>Open the ESB_HOME/repository/conf/user-mgt.xml file and change the database configuration as below(IP addresses and urls have to be changed according to your setup).</p>
      <pre xml:space="preserve">
  &lt;Property name=&quot;url&quot;&gt;jdbc:mysql://x.x.x.x:3306/amausermgtdb?autoReconnect=true&lt;/Property&gt;
        &lt;Property name=&quot;userName&quot;&gt;root&lt;/Property&gt;
        &lt;Property name=&quot;password&quot;&gt;root123&lt;/Property&gt;
        &lt;Property name=&quot;driverName&quot;&gt;com.mysql.jdbc.Driver&lt;/Property&gt;
        &lt;Property name=&quot;maxActive&quot;&gt;50&lt;/Property&gt;
        &lt;Property name=&quot;maxWait&quot;&gt;60000&lt;/Property&gt;
     &lt;Property name=&quot;minIdle&quot;&gt;5&lt;/Property&gt;
      </pre>
      <p>Now let's configure the mounting configuration. For that we need to add more parameters to registry.xml file.</p>
      <p>Open the ESB_HOME/repository/conf/registry.xml file  and add the following mount database configuration below. (IP addresses and database urls have to be changed acccording to your setup).</p>
      <pre xml:space="preserve">
      &lt;dbConfig name=&quot;esbMountRegistry&quot;&gt;
         &lt;url&gt;jdbc:mysql://x.x.x.x:3306/amagregdb?autoReconnect=true&lt;/url&gt;
            &lt;userName&gt;root&lt;/userName&gt;
            &lt;password&gt;root123&lt;/password&gt;
            &lt;driverName&gt;com.mysql.jdbc.Driver&lt;/driverName&gt;
            &lt;maxActive&gt;50&lt;/maxActive&gt;
            &lt;maxWait&gt;60000&lt;/maxWait&gt;
            &lt;minIdle&gt;5&lt;/minIdle&gt;
        &lt;/dbConfig&gt;


        &lt;remoteInstance url=&quot;https://x.x.x.x:9443/registry&quot;&gt;
            &lt;id&gt;Mount1&lt;/id&gt;
            &lt;dbConfig&gt;esbMountRegistry&lt;/dbConfig&gt;
            &lt;readOnly&gt;false&lt;/readOnly&gt;
            &lt;registryRoot&gt;/&lt;/registryRoot&gt;
        &lt;/remoteInstance&gt;

        &lt;mount path=&quot;/_system/config&quot; overwrite=&quot;true&quot;&gt;
            &lt;instanceId&gt;Mount1&lt;/instanceId&gt;
            &lt;targetPath&gt;/_system/esbConfig&lt;/targetPath&gt;
        &lt;/mount&gt;

        &lt;mount path=&quot;/_system/governance&quot; overwrite=&quot;true&quot;&gt;
            &lt;instanceId&gt;Mount1&lt;/instanceId&gt;
            &lt;targetPath&gt;/_system/governance&lt;/targetPath&gt;
        &lt;/mount&gt;
      </pre>
      <p> Please change the "remoteInstance URL" according to the configuration of the GREG instance. Please note that "InstanceIds", "id" and "dbConfig" elements should be mapped properly if you are using different
	        names for them.</p>

      <p>Copy mysql jdbc driver library to ESB_HOME/repository/components/lib direcotry since by default we do not ship the mysql drivers in ESB.</p>
      
	  <h4> Settings for ESB Slave Node</h4>
		
	  <p>Here we are changing the default database configuration, to point slvae node's local registry to <strong>amaslave1</strong> and will be pointed the user manager
	  database to <strong>amausermgtdb </strong>. Here ESB slave node's configuration and Governance registriy's configuration also will be mounted from GREG database.</p>

      <p>Let's first add local registry configuration and user-manager configuration.</p>
      <p>Open the ESB_SLAVE_HOME/repository/conf/registry.xml file , remove the original dbConfig element and add the database configuration below. (IP addresses and database 
	  urls have to be changed acccording to your setup).</p>
      <pre xml:space="preserve">
      &lt;currentDBConfig&gt;wso2registry&lt;/currentDBConfig&gt;
            &lt;readOnly&gt;false&lt;/readOnly&gt;
           &lt;registryRoot&gt;/&lt;/registryRoot&gt;
            &lt;dbConfig name=&quot;wso2registry&quot;&gt;
         &lt;url&gt;jdbc:mysql://x.x.x.x:3306/amaslave1?autoReconnect=true&lt;/url&gt;
            &lt;userName&gt;root&lt;/userName&gt;
            &lt;password&gt;root123&lt;/password&gt;
            &lt;driverName&gt;com.mysql.jdbc.Driver&lt;/driverName&gt;
            &lt;maxActive&gt;50&lt;/maxActive&gt;
            &lt;maxWait&gt;60000&lt;/maxWait&gt;
            &lt;minIdle&gt;5&lt;/minIdle&gt;
        &lt;/dbConfig&gt;
      </pre>
      <p>Open the ESB_SLAVE_HOME/repository/conf/user-mgt.xml file and change the database configuration as below(IP addresses and urls have to be changed according to your setup).</p>
	   <p> <strong> Note :</strong> Here we are changing the mode to 'readOnly' in database configuration.</p>
      <pre xml:space="preserve">
  &lt;ReadOnly&gt;true&lt;/ReadOnly&gt;
        &lt;Property name=&quot;url&quot;&gt;jdbc:mysql://x.x.x.x:3306/amausermgtdb?autoReconnect=true&lt;/Property&gt;
        &lt;Property name=&quot;userName&quot;&gt;root&lt;/Property&gt;
        &lt;Property name=&quot;password&quot;&gt;root123&lt;/Property&gt;
        &lt;Property name=&quot;driverName&quot;&gt;com.mysql.jdbc.Driver&lt;/Property&gt;
        &lt;Property name=&quot;maxActive&quot;&gt;50&lt;/Property&gt;
        &lt;Property name=&quot;maxWait&quot;&gt;60000&lt;/Property&gt;
     &lt;Property name=&quot;minIdle&quot;&gt;5&lt;/Property&gt;
      </pre>

  <p>Now let's configure the mounting configuration. For that we need to add more parameters to registry.xml file.</p>
   <p>Open the ESB_SLAVE_HOME//repository/conf/registry.xml file  and add the following mount database configuration below. (IP addresses and database urls have to be changed acccording to your setup).</p>



      <pre xml:space="preserve">
  &lt;dbConfig name=&quot;esbMountRegistry&quot;&gt;
     &lt;url&gt;jdbc:mysql://x.x.x.x:3306/amagregdb?autoReconnect=true&lt;/url&gt;
        &lt;userName&gt;root&lt;/userName&gt;
        &lt;password&gt;root123&lt;/password&gt;
        &lt;driverName&gt;com.mysql.jdbc.Driver&lt;/driverName&gt;
        &lt;maxActive&gt;50&lt;/maxActive&gt;
        &lt;maxWait&gt;60000&lt;/maxWait&gt;
        &lt;minIdle&gt;5&lt;/minIdle&gt;
    &lt;/dbConfig&gt;


    &lt;remoteInstance url=&quot;https://x.x.x.x:9443/registry&quot;&gt;
        &lt;id&gt;Mount1&lt;/id&gt;
        &lt;dbConfig&gt;esbMountRegistry&lt;/dbConfig&gt;
        &lt;readOnly&gt;true&lt;/readOnly&gt;
        &lt;registryRoot&gt;/&lt;/registryRoot&gt;
    &lt;/remoteInstance&gt;

    &lt;mount path=&quot;/_system/config&quot; overwrite=&quot;true&quot;&gt;
        &lt;instanceId&gt;Mount1&lt;/instanceId&gt;
        &lt;targetPath&gt;/_system/esbConfig&lt;/targetPath&gt;
    &lt;/mount&gt;

    &lt;mount path=&quot;/_system/governance&quot; overwrite=&quot;true&quot;&gt;
      &lt;instanceId&gt;Mount1&lt;/instanceId&gt;
        &lt;targetPath&gt;/_system/governance&lt;/targetPath&gt;
    &lt;/mount&gt;
      </pre>



    <p>
          Please change the remoteInstance URL according to the configuration of the GREG running machine. Please note that "InstanceIds", "id" and "dbConfig" elements 
		  should be mapped properly if you are using different  names for them.
	</p>
	<p>
	<strong>	Note: </strong> If you compare the configuration with master node, we are only changing the configuration of local registry 
	and all the other configurations are same with the master node, but the registry access mode in mounting is readonly but the local registry 
	configuration should be read-write since it is specific for each node.
     </p>

    <p>Copy mysql jdbc driver library to ESB_SLAVE_HOME/repository/components/lib direcotry since by default we do not ship the mysql drivers in ESB.</p>
    <p>Before starting the slave ESB node you need to load registry database schema to <strong>amaslave1</strong> database.
	You can find the required SQL script at ESB_SLAVE_HOME/dbscripts directory.</p>

	<h4> Running the setup</h4>
	
    <p>After successful configurations, run the api-manager.sh or api-manager.bat of master node based on your platform with '-Dsetup' option for the first time start up
	to create the database tables, and after creating database tables, do not use '-Dsetup' option when run the server.</p>
    <pre xml:space="preserve">sh CARBON_HOME/bin/api-manager.sh -Dsetup</pre>
	
    <p>You don't need to specify the -Dsetup option for ESB slave node because we have created DB schema in the previous step.</p>
      <p><strong>  Note: </strong> -Dsetup doesn't work with ESB slave node because we share a same database for user manager and  -Dsetup option will try to
		create user manager tables at the startup if you use -Dsetup option.</p>

     <p>After setting up the ESB's pointing to a single Registry we have two options for sharing the configuration. </p>


      <ol>
          <li>Manual configuration sharing
              <p>In this mode ESB's can be configured to load the configuration from the Registry instead of the file system. The configuration loading happens only when the ESB starts up. So if a change is made to the master ESB node, other ESB's has to be restarted to get the new configuration.

                  Lot of users prefer this mode because it guarantees a consistent configuration at the start up and configuration is not changed while the ESB is running.
                  By default ESB loads the configuration from the File System. If the configuration has to be loaded from the Registry following configuration has to be uncommented and changed in the carbon.xml</p>
                  <pre xml:space="preserve">
&lt;MediationConfig&gt;
    &lt;LoadFromRegistry&gt;false&lt;/LoadFromRegistry&gt;
    &lt;SaveToFile&gt;false&lt;/SaveToFile&gt;
    &lt;Persistence&gt;enabled&lt;/Persistence&gt;
    &lt;RegistryPersistence&gt;enabled&lt;/RegistryPersistence&gt;
&lt;/MediationConfig&gt;
                  </pre>
              <p>LoadFromRegistry parameter has to be changed to true in the slave nodes.</p>

          </li>
          <li>Deployment Synchronizer
              <p>The next approach is to use the Deployment Synchronizer shipped with the ESB. With the deployment
                  synchronizer, configurations can be updated in the slave nodes at the runtime.</p>
              <ol>
                  <li>Configuration has to be changed in the master node.</li>
                  <li>The check in that configuration to the registry</li>
                  <li>Check out the configuration from the slave nodes</li>
              </ol>
          </li>
      </ol>


      <h3><a name="runtimeshare">Runtime State Replication</a></h3>
      <p>WSO2 ESB flows are stateless for the most part. But in very rare deployments users have requested to share some of the runtime information among the cluster nodes. For example Caching can be used with runtime state sharing. </p>

      <p>Runtime state replication is based on the Tribes group management system. It
      provides group membership handling and group communication for clustered Carbon Server
      instances. Although ESB ships with this built in Tribes based
      implementation, other clustering implementations based on different group
      management systems can be plugged in easily. The only thing you have to do is
      to implement a set of clustering interfaces provided by Carbon Server.</p>

      <p></p>

      <p>ESB clustering currently does not support distributed locking for session
      data replication. Therefore, we have to deploy primary backup clusters for
      stateful services. This restriction does not apply to
      stateless services and you can direct client requests to any node in the
      cluster for such services.</p>

      <p></p>

      <h3><a name="AppServerClusteringConfiguration">ESB State Replication
      Configuration</a></h3>

      <p>ESB clustering is configured using the axis2.xml file. So you have to
          enable clustering in the axis2.xml of each node.</p>
      <p>
          For more details about Carbon Server clustering, please see
          <a href="http://wso2.org/library/articles/wso2-carbon-cluster-configuration-language">
              WSO Carbon Clustering Configuration Language
          </a>.
      </p>
          <p>NWe can enable clustering by changing the configuration in the axis2.xml. By default, clustering is
              turned off to avoid additional overhead for individual deployments. Open
              the axis2.xml and set the value 'true' for the "enable" attribute
              of the "clustering" element as follows.</p>

          <pre>
              &lt;clustering class="org.apache.axis2.clustering.tribes.TribesClusteringAgent" enable="true"&gt;
          </pre>

          <p>You may also change clustering properties to suit your deployment as explianed
              in the above article. However, the default configuration is sufficient for
              the demonstration.</p>

      <h2>
          Other Resources
      </h2>
      <p/>
      <p>
          <a href="http://wso2.org/library/esb">The WSO2 Oxygen Tank
              Library</a> : The Library contains articles, tutorials,
          presentations, and other knowledge base items published on The Oxygen
          Tank on different styles of deployments.
      </p>
  </body>
</html>
