Search code examples
javatomcatservletsjdbcweb.xml

porting web app to Tomcat: javax.naming.NameNotFoundException:


New user of Tomcat (8.5.9) on Linux CentOS 7 with Java SE 8. I must be making a simple mistake. This should be a textbook example how to configure a JDBC connection pool for tomcat.

I have this error:

javax.naming.NameNotFoundException: Name [jdbc/pool1] is not bound in this Context. Unable to find [jdbc]

Any idea what I could doing wrong? Tomcat states It is NOT recommended to place <Context> elements directly in the server.xml file. Thus, my setup:

$CATALINA_HOME/webapps/myapp/META-INF/context.xml is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
  <Resource name="jdbc/pool1"
            auth="Container"
            type="javax.sql.DataSource"
            username="xx"
            password="xx"
            driverClassName="oracle.jdbc.OracleDriver"
            url="xx"
            maxTotal="256"
            maxIdle="8"
            initialSize="4"
            removeAbandonedTimeout="7200"
            removeAbandonedOnBorrow="true"/>

  <Resource name="jdbc/pool2"
            auth="Container"
            type="javax.sql.DataSource"
            username="xx"
            password="xx"
            driverClassName="oracle.jdbc.OracleDriver"
            url="xx"
            maxTotal="256"
            maxIdle="8"
            initialSize="4"
            removeAbandonedTimeout="7200"
            removeAbandonedOnBorrow="true"/>

  <ResourceLink name="jdbc/pool1"
                global="jdbc/pool1"
                type="javax.sql.DataSource"/>

  <ResourceLink name="jdbc/pool2"
                global="jdbc/pool2"
                type="javax.sql.DataSource"/>
</Context>

$CATALINA_HOME/webapps/myapp/WEB-INF/web.xml is as follows:

...
<resource-ref>
        <description>xxx</description>
        <res-ref-name>jdbc/pool1</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
    <resource-ref>
        <description>xxx</description>
        <res-ref-name>jdbc/pool1</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
 </resource-ref>
 ...

The code causing the exception:

 Context context = new InitialContext();
 DataSource ds = (DataSource)context.lookup("jdbc/pool1");
 conn = ds.getConnection();

I have not modified $CATALINA_HOME/conf/server.xml at all. Did I configure something incorrectly, or am I missing setting another file up somewhere?

UPDATE 1

I tried adding the above ResourceLinks to the GlobalNamingResources tag in the $CATALINA_HOME/conf/server.xml file, then stopping/starting Tomcat, but I got the same error.

UPDATE 2

I then added the Resource tags from context.xml above also to the server.xml file (GlobalNamingResources tag), stopping/starting tomcat, and got same error.

UPDATE 3

I got everything working with Andreas' expert help (thanks!) by changing the way java calls the pool:

Context initCtx = new InitialContext();
Context context = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) context.lookup("jdbc/pool1");
conn = ds.getConnection();  

Also, the ResourceLinks should not be in server.xml (they simply generate a warning in tomcat log).


Solution

  • Your $CATALINA_BASE/conf/server.xml file should contain the full <Resource> element. Remember to also add the JDBC driver jar file to Tomcat's $CATALINA_BASE/lib folder, since it is Tomcat, not your webapp, that needs it when the <Resource> is defined in server.xml.

    Next, the META-INF/context.xml is a template that is used the first time your webapp is deployed. It gets copied to $CATALINA_BASE/conf/Catalina/localhost/myapp.xml, and is likely not updated/refreshed if you change META-INF/context.xml.

    The .../Catalina/localhost/myapp.xml file should contain the <ResourceLink> element, mapping the name used by the webapp to the name used in server.xml. Keeping those two names the same is easiest, but not required.

    Tomcat works fine without the <resource-ref> elements in WEB-INF/web.xml, but it's better if they are there, for compatibility with other Servlet containers.

    Note: $CATALINA_BASE is usually the same as $CATALINA_HOME, i.e. the folder where Tomcat is installed, unless you explicitly configure it otherwise.

    So, $CATALINA_BASE/conf/server.xml:

    <?xml version='1.0' encoding='utf-8'?>
    <Server ...>
        ...
        <GlobalNamingResources>
            ...
            <Resource name="jdbc/pool1" auth="Container" type="javax.sql.DataSource" ... />
            <Resource name="jdbc/pool2" auth="Container" type="javax.sql.DataSource" ... />
            ...
        </GlobalNamingResources>
        ...
    </Server>
    

    and $CATALINA_BASE/conf/Catalina/localhost/myapp.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
        <ResourceLink name="jdbc/pool1" global="jdbc/pool1" type="javax.sql.DataSource"/>
        <ResourceLink name="jdbc/pool2" global="jdbc/pool2" type="javax.sql.DataSource"/>
    </Context>
    

    and place ojdbcXXX.jar in $CATALINA_BASE/lib.