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?
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.