Search code examples
springtomcat6jndi

JNDI Resource Definition in Apache Tomcat 6


I'm more than inexperienced with Apache Tomcat, so forgive me if it's a trivial question I'm asking.

My task is to change a rather big program so that it uses the connection from Tomcat instead of its own bean, so that you don't have to rebuild the code when the database changes.

This is the original bean definition (slightly changed - passwords and such...):

<bean id="ProjectDS" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" scope="singleton">
        <property name="url"
                  value="jdbc:as400://127.0.0.1/TEST2;prompt=false;naming=sql;errors=full;date format=usa;date separator=/;time format=hms;time separator=:;transaction isolation=read committed;"/>
        <property name="driverClassName" value="com.ibm.as400.access.AS400JDBCDriver"/>
        <property name="username" value="asdf"/>
        <property name="password" value="asdf"/>
        <property name="initialSize" value="${ProjectDS.initialSize}"/>
        <property name="maxActive" value="${ProjectDS.maxActive}"/>
        <property name="maxIdle" value="${ProjectDS.maxIdle}"/>
        <property name="minIdle" value="${ProjectDS.minIdle}"/>
        <property name="testOnBorrow" value="${ProjectDS.testOnBorrow}"/>
        <property name="removeAbandoned" value="${ProjectDS.removeAbandoned}"/>
        <property name="removeAbandonedTimeout" value="${ProjectDS.removeAbandonedTimeout}"/>
        <property name="logAbandoned" value="${ProjectDS.logAbandoned}"/>
    </bean>

After reading several tutorials about Tomcat configuration, I did the following:

The new bean:

<bean id="ProjectDS" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName">
            <value>ProjectDS</value>
        </property>
        <property name="resourceRef" value="true"></property>
    </bean>

server.xml :

<Resource name="ProjectDS" global="ProjectDS" auth="Container"
            type="org.apache.commons.dbcp.BasicDataSource"
            driverClassName="com.ibm.as400.access.AS400JDBCDriver"
            url="jdbc:as400://127.0.0.1/TEST2"
            username="asdf"
            password="asdf" /> 

context.xml:

<WatchedResource>WEB-INF/web.xml</WatchedResource>
    <ResourceLink global="ProjectDS" name="ProjectDS" type="org.apache.commons.dbcp.BasicDataSource"/>

What I get is:

Exception processing Global JNDI Resources javax.naming.NamingException: Cannot create resource instance

I read somewhere that I shouldn't put the above into the server.xml but into the web.xml, but I don't know where exactly. Could that be the problem?


Solution

  • First, rollback your context.xml and server.xml in your tomcat and/or. Here is a working configuration:

    Create a file in src/main/webapp/META-INF named context.xml which contains:

    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
    <Resource name="ProjectDS" auth="Container"
                type="javax.sql.DataSource"
                driverClassName="com.ibm.as400.access.AS400JDBCDriver"
                url="jdbc:as400://127.0.0.1/TEST2"
                username="asdf"
                password="asdf" /> 
    </Context>
    

    Then, edit your bean in this way:

    <bean id="ProjectDS" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/ProjectDS" />
        <property name="proxyInterface" value="javax.sql.DataSource" />
    </bean>
    

    Difference here is the java:comp/env/ProjectDS and the proxy unterface.

    Hope it will work for you!