Non-XA DataSources

Whilst the org.mortbay.jetty.plus.JotmService provides support for JTA and DataSources that can participate in distributed transactions, JettyPlus also supports non-XA DataSources. The org.mortbay.jetty.plus.AbstractDataSourceService provides the basis for pluggable DataSource and connection pooling implementations. A default implementation is provided that allows you to use any javax.sql.DataSource for non-pooled connections and that uses XAPool internally to provide the pool for pooled connections. By subclassing AbstractDataSourceService, you may add other types of connection pooling implementations to JettyPlus.

The general method of configuring the org.mortbay.jetty.plus.DefaultDataSourceService in your JettyPlus xml configuration file is as follows:


  <Call name="addService">
    <Arg>
      <New class="org.mortbay.jetty.plus.DefaultDataSourceService">
        <Set name="Name">DataSourceService</Set> <!-- name of the service -->

         <!-- repeat this section to add more DataSource definitions -->
         <Call name="addDataSource"> 
             <Arg>jdbc/xyz</Arg>  <!-- name for app to lookup relative to java:comp/env -->   
             <New class=......>   <!-- class for javax.sql.DataSource implementation -->
	     <!-- configure the particular DataSource implementation --> 
             </New>
         </Call> 
	 <!-- end of DataSource definition -->

          <!-- repeat this section to add more pooled datasources -->
         <Call name="addConnectionPoolDataSource">
             <Arg>jdbc/postgres</Arg><!-- name for app to lookup relative to java:comp/env -->
             <New class=......>      <!-- class for javax.sql.ConnectionPoolDataSource implementation -->
	     <!-- configure the particular javax.sql.ConnectionPoolDataSource implementation -->
             </New>
         </Call>
	 <!-- end of ConnectionPolDataSource definition -->

       </New>
     </Arg>
   </Call> 
   

As this mechanism is extremely flexible, let's now consider some of the different ways in which you can configure DataSource resources:

Configuration Scenarios

1 Using a vendor-supplied javax.sql.DataSource that does internal connection pooling, or pooling not required

The following example configures a Postgres DataSource that does its own connection pooling. You can configure any javax.sql.DataSource implementation.
         <Call name="addDataSource">
            <Arg>jdbc/mydatabase</Arg>
            <Arg>
             <New class="org.postgresql.jdbc3.Jdbc3PoolingDataSource">
                <Set name="DataSourceName">Database on localhost</Set>
                <Set name="ServerName">localhost</Set>
                <Set name="DatabaseName">database</Set>
                <Set name="PortNumber">5432</Set>
                <Set name="User">postgres</Set>
                <Set name="Password">password</Set>
                <Set name="MaxConnections">50</Set>
                <Set name="InitialConnections">5</Set>
             </New>
            </Arg>
           </Call>

2 No vendor-supplied DataSource available, pooling not required

If you only have a JDBC driver class, you can use the XAPool org.enhydra.jdbc.standard.StandardDataSource class to provide a non-pooling javax.sql.DataSource. Eg:
         <Call name="addDataSource">
             <Arg>jdbc/hsqldb</Arg>  
             <!-- Configure the DataSource impl                        -->
             <Arg>
               <New class="org.enhydra.jdbc.standard.StandardDataSource">
                 <Set name="DriverName">org.hsqldb.jdbcDriver</Set>
                 <Set name="Url">jdbc:hsqldb:extra/etc/tmtest</Set>
                 <Set name="User">sa</Set>
                 <Set name="Password"></Set>
                <!-- bug work around only for StandardDataSource:      -->
                 <Set name="Logger">
                   <New class="org.enhydra.jdbc.util.Logger">
                     <Arg>
                       <Call class="org.apache.commons.logging.LogFactory" name="getLog">
                         <Arg>org.enhydra.jdbc.xapool</Arg>
                       </Call>
                     </Arg>
                   </New>
                 </Set>                 
               </New>
             </Arg>
         </Call>

3 Using JettyPlus connection pooling where vendor supports JDBC2 javax.sql.ConnectionPoolDataSource

If your JDBC provider does not do connection pooling internally, you can use JettyPlus's default connection pooling implementation (or write your own replacement connection pool). If your JDBC vendor implements the JDBC2 specification, ie implements the javax.sql.ConnectionPoolDataSource interface, you can configure connection pooling by using the addConnectionPoolDataSource() method. The following example uses Postgres:
         <Call name="addConnectionPoolDataSource">
            <Arg>jdbc/mydatabase</Arg>
            <Arg>
             <New class="org.postgresql.jdbc3.Jdbc3ConnectionPool">
                <Set name="DataSourceName">Database on localhost</Set>
                <Set name="ServerName">localhost</Set>
                <Set name="DatabaseName">database</Set>
                <Set name="PortNumber">5432</Set>
                <Set name="User">postgres</Set>
                <Set name="Password">password</Set>
             </New>
            </Arg>
           <!-- configure the pool:                                  -->
           <Set name="user">postgress</Set>
           <Set name="password">password</Set>
           <Set name="minSize">1</Set>
           <Set name="maxSize">5</Set>
        </Call>

4 Using JettyPlus connection pooling without JDBC2 support

If your JDBC provider does not support the JDBC2 specification, you can use the org.enhydra.jdbc.standard.StandardConnectionPoolDataSource class to create a DataSource that pools connections:
         <Call name="addConnectionPoolDataSource">
           <Arg>jdbc/myPooledDataSource</Arg>
           <Arg>                               
             <New class="org.enhydra.jdbc.standard.StandardConnectionPoolDataSource">
                 <Set name="DriverName">org.hsqldb.jdbcDriver</Set>
                 <Set name="Url">jdbc:hsqldb:extra/etc/tmtest</Set>
                 <Set name="User">sa</Set>
                 <Set name="Password"></Set>
                 <!-- workaround for XAPool bug:                      -->
                 <Set name="Logger">
                   <New class="org.enhydra.jdbc.util.Logger">
                     <Arg>
                       <Call class="org.apache.commons.logging.LogFactory" name="getLog">
                         <Arg>org.enhydra.jdbc.xapool</Arg>
                       </Call>
                     </Arg>
                   </New>
                 </Set>                              
             </New>
           </Arg>
           <!-- configure the pool:                                  -->
           <Set name="user">sa</Set>   
           <Set name="password"></Set>
           <Set name="minSize">1</Set>
           <Set name="maxSize">5</Set> 
         </Call>        

Plugging in an alternate DataSourceService

If you would like to use a different connection pooling mechanism other than the default supplied with the JettyPlus distribution, you can code your own DataSourceService.

You will need to subclass the org.mortbay.jetty.plus.AbstractDataSourceService and provide an implementation for the following method:

        public DataSource createPooledDataSource (String jndiName, javax.sql.ConnectionPoolDataSource cpds) 
	throws Exception;

Notice that the method returns a javax.sql.DataSource object. This is the object will be bound into JNDI for application code to lookup in java:comp/env, and must work with your pooling mechanism. The abstract base class ensures that the DataSource impl returned by this method will be available for linking to webapplication's <resource-ref> and <resource-env-ref> elements.

Of course, you are also free to add and expose other methods in order to configure your pooling mechanism.

You must then make your class available on to the JettyPlus classpath. Perhaps the easiest way to do this is to create a jar of your implemenation class, and place it in $JETTY_HOME/extra/lib. Put any auxiliary jars into $JETTY_HOME/extra/ext.

Now all you have to do is call your service implementation in your JettyPlus xml configuration file, and you're all done!