Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eclipse: Overriding JNDI Resource in Tomcat

I'm working on a Java web application in Eclipse and deploying to an instance of Tomcat that is run by Eclipse. I'm trying to get this application to talk to a database on another host via a JNDI Resource element.

The context.xml file included in the application attempts to connect to a MySQL server running on localhost, like so:

<?xml version="1.0" encoding="UTF-8"?>

<Context>
    <Environment name="log4j.configuration"
    value="/path/to/installed/log4j.properties"
    type="java.lang.String" />

    <Resource name="jdbc/configDB" auth="Container" type="javax.sql.DataSource"
    username="dbuser" password="dbpassword" driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/dbname" maxActive="8"
    validationQuery="SELECT 1" testOnBorrow="true" />

    <Environment name="mykey" value="installed" type="java.lang.String" />

</Context>

This configuration works when I install it on the actual host. That is, it reads the environment values correctly and connects to the database.

I can also install this on a separate host and edit /etc/tomcat6/conf/Catalina/localhost/myaplication.xml to change the JDBC URL, like so:

...
    <Resource name="jdbc/configDB" auth="Container" type="javax.sql.DataSource"
    username="dbuser" password="dbpassword" driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://otherhost:3306/dbname" maxActive="8"
    validationQuery="SELECT 1" testOnBorrow="true" />
...

This configuration also works. In other words, I'm pretty confident that my application is using the JNDI correctly.

So, now I want to deploy this to Tomcat on my desktop in Eclipse. I've added the project to Tomcat in the standard way, and I've edited the context.xml file for the server (i.e., the one that Eclipse shows under my Tomcat server in the "Servers" project) like so:

<?xml version="1.0" encoding="UTF-8"?>

<Context>
    <Environment name="log4j.configuration"
    value=C:\workspace\myapplication\src\main\resources\conf\log_to_tomcat_console_log4j.properties"
    type="java.lang.String" />

    <Resource name="jdbc/configDB" auth="Container" type="javax.sql.DataSource"
    username="dbuser" password="dbpassword" driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://otherhost:3306/dbname" maxActive="8"
    validationQuery="SELECT 1" testOnBorrow="true" />

    <Environment name="mykey" value="desktop" type="java.lang.String" />

</Context>

When I then restart Tomcat in Eclipse, log shows me that the path to the Log4J file is being read correctly (because it starts logging to the Tomcat console) and I even see it spit out the correct "mykey" value. However, initialisation fails when it tries to read from the configDB.

At first, I thought this was a connectivity issue, but after ruling that out, I restarted Tomcat in the debugger and inspected the DataSource read from JNDI; its URL points to localhost, meaning it's using the one in the application's context.xml file, not Tomcat's!

I've tried several ways to get this working, including putting this information in Tomcat's server.xml file, but nothing seems to work. Or, more accurately, it sort of kind of works because it's reading the Environment values but not the Resource.

What am I doing wrong here? How do I get Eclipse's Tomcat server to override this Resource?

like image 839
jpappe Avatar asked Mar 13 '14 10:03

jpappe


People also ask

Does Tomcat support JNDI?

Tomcat provides a JNDI InitialContext implementation instance for each web application running under it, in a manner that is compatible with those provided by a Java Enterprise Edition application server. The Java EE standard provides a standard set of elements in the /WEB-INF/web.

HOW JNDI works in Tomcat?

Actual benefit of DataSource comes when we use it with a JNDI Context. For example, connection pool in a web application deployed in a servlet container. Most of the popular servlet containers provide built-in support for DataSource through Resource configuration and JNDI context.

HOW JNDI DataSource works?

A JNDI DataSource object is a file that contains the configuration details necessary to connect to a database. The DataSource object must be registered on a JNDI server, where it is identified using a JNDI name. You can register your DataSource object directly on your application server via its JNDI service.


1 Answers

The basic problem here is, that the context.xml you edit in eclipse corresponds to the main context.xml in the conf directory of tomcat. And then the preferences in the application context file takes precedence. As you already described within normal deployment lifecycle of tomcat this is perfectly fine, because you just edit the application settings.

You could do the same with the context file created by eclipse (which is located somewhere at .metadata/.plugins/org.eclipse.wst.server.core/tmp0/conf/Catalina/localhost) but it will be overwritten as soon as you change something in the original context file (META-INF/context.xml). So actually you would need to make the changes there, but this is normally out of question because this file must be deployed without custom changes.

But here is a workaround: You can make eclipse use another META-INF/context.xml by abusing the deployment assembly. Make a new META-INF directory somewhere else and place a context.xml file with your setting there. Then in the project properties of your eclipse project at Deployment Assembly add an additional mapping from your new path/to/META-INF to META-INF.
Then eclipse will overwrite the original context.xml with your custom one and tomcat should take your settings.

like image 58
Markus Avatar answered Sep 26 '22 10:09

Markus