views:

862

answers:

3

What are the accepted practices for creating a Tomcat deployment that reads configuration parameters from a properties file?

It would be nice to be able to deliver a WAR file and specify that the client need only create or edit a properties file in a specific directory. Is this a somewhat regular way of doing things? Is there a better approach than this?

+1  A: 

We often distribute webapps by providing a WAR, and a Context XML file, which gets placed into your tomcat/conf/Catalina/localhost directory, and can load the webapp from any path. There is a reference document here. This provides the following advantages:

  • Context parameters can be configured here and read by the webapp
  • DataSources can be defined and configured here
  • The WAR can actually live anywhere on the filesystem, which means that if Tomcat gets upgraded, only this single configuration file needs to be moved to the new Tomcat install, the web application and any other files can stay where they are

If you really want a properties file, you can set a parameter in the context XML file pointing to your properties file, read the parameter in a ServletContextListener and then read in the properties file.

Adam Batkin
+1  A: 

The way we handle this:

  1. Have the client create a connection pool in GlobalNamingResources using a resource name we agree on. The database driver needs to be in Tomcat's classpath.
  2. Our war file includes a META-INF/context.xml files that has a ResourceLink linking to the connection pool configured in step 1.

This is a little more up front work than simply altering the context.xml connection information directly, but over time it should pay off. A development server would be setup with it's GlobalNamingResources pointing to development, and a test server point to test etc. Then, the same WAR file can be copied to each server without editing anything.

This isn't using properties files, but I think it achieves the same goal. Allowing a user/customer to setup the database connection information.

Example of GlobalNamingResource:

<Resource name="jdbc/dbconnection" auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@127.0.0.1:1546:SID"
username="scott" password="tiger" maxActive="8" maxIdle="4"
validationQuery="select 1 from dual"
testOnBorrow="true"/>

Example of context.xml in war file:

<Context path="/MyWebApp" docBase="MyWebApp" debug="5" reloadable="true">
    <ResourceLink name="jdbc/dbconnection" global="jdbc/dbconnection" 
          type="javax.sql.DataSource"/>
</Context>
Steve K
A: 

It's a good practice to store configuration out of the war zone. In our WAR, we have a default location to look for the property file. If the default doesn't work, you can specify the location via a JVM parameter or a context parameter defined in context fragment in conf/Catalina/[host] directory. For example,

<Context docBase="/server/app.war"
    swallowOutput="true" unpackWAR="false" useNaming="false">

    <Parameter name="config-file" value="/config/db.properties" override="true" />
</Context>
ZZ Coder