Thursday, August 13, 2009

How to convert a web application using a datasource defined in Tomcat's context.xml into a web application running on Jboss and using an internal one

Example is for an Oracle Datasource and a MyApp web application, but is identical for other vendor types/web applications.

Initial situation on Tomcat 6

  • JDBC driver in $TOMCAT/lib

  • context.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <Context path="/MyApp">
    <Loader delegate="true"/>

    <!-- Name must match resource-ref in web.xml and bean with id="datasource" in applicationContext.xml!
    <Resource name="jdbc/MyDs"
    auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
    url="jdbc:oracle:thin:@192.168.0.107:1521:XE" username="vatengine" password="vatengine"
    removeAbandoned="true" maxActive="-1" maxIdle="-1" maxWait="-1"/>
    </Context>


  • web.xml:

    ...
    <resource-ref>
    <description>MyDs Oracle Datasource</description>
    <res-ref-name>jdbc/MyDs</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    </resource-ref>
    ...


  • Spring's applicationContext.xml:

    ...
    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/MyDs"/>
    </bean>
    ...



Final situation on Jboss 5

  • add JDBC driver to $JBOSS/server/type_of_server/lib, in our case $JBOSS/server/default/lib


  • MyDs-ds.xml: this file defines the Jboss datasource and has to be added to $JBOSS/server/type_of_server/deploy, in our case $JBOSS/server/default/deploy

    <?xml version="1.0" encoding="UTF-8"?>
    <datasources>
    <local-tx-datasource>
    <jndi-name>jdbc/MyDs</jndi-name>
    <connection-url>jdbc:oracle:thin:@192.168.0.107:1521:XE</connection-url>
    <driver-class>oracle.jdbc.OracleDriver</driver-class>
    <user-name>vatengine</user-name>
    <password>vatengine</password>
    <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
    </local-tx-datasource>
    </datasources>


  • web.xml and applicationContext.xml stay identical


  • context.xml: the datasource declaration can be removed, since we will be creating one in Jboss (but it seems leaving it doesn't do harm)

    <?xml version="1.0" encoding="UTF-8"?>
    <Context path="/MyApp">
    <Loader delegate="true"/>
    </Context>


  • jboss.web.xml: this file has to be added to the web application's WEB-INF directory contains glue logic between web.xml and Jboss resource declarations

    <?xml version="1.0" encoding="UTF-8"?>
    <jboss-web>
    <resource-ref>
    <res-ref-name>jdbc/MyDs</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <jndi-name>java:jdbc/MyDs</jndi-name>
    </resource-ref>
    </jboss-web>


Tuesday, August 11, 2009

Converting an application using an internal datasource to one using a JNDI datasource

Elaboration for Tomcat 6 and Oracle 10; other application or db servers are similar.

1. Copy the jdbc driver jar (ojdbc14.jar) to $TOMCAT_HOME/lib

2. To the application's context.xml, add the following lines:

<Resource name="jdbc/XXX"
auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
url="url" username="usr" password="pass"
removeAbandoned="true" maxActive="-1" maxIdle="-1" maxWait="-1"/>

where XXX is the name the datasource will take in the JNDI tree, and url, username and password keep the real values used before.
The other parameters may be finetuned at will. removeAbandoned="true" makes sure that that abandoned dB connections are removed and recycled.

3. To the application's web.xml, add the following:

<resource-ref>
<description>Oracle Datasource</description>
<res-ref-name>jdbc/XXX</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

where XXX matches the JNDI name chosen before.

4. Within the application, use the datasource's JNDI name when referring to it: java:comp/env/jdbc/XXX
for instance, in Spring's applicationContext.xml, one can add:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/XXX"/>
</bean>

and inject this bean in other beans that need a datasource.

5. Since the Oracle driver will already be loaded by Tomcat's classloader at the startup of the application, it isn't needed to deploy it with the application, it's only needed to compile. Hence, in Eclipse, in the project's properties->Java EE Module Dependencies, unmark the dependency on the oracle driver (ojdbc14.jar), or remove it from the dist target within a custom Ant script.

Source: http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html