# Thread: Tomcat, war files and PropertyPlaceholderConfigurer

1. Member
Join Date
Aug 2004
Posts
56

## Tomcat, war files and PropertyPlaceholderConfigurer

Hi,
I'm looking for a way to keep my property files outside the war file of my application. So far I've put those property files in the web application itself, and referred to them by the classpath.
Yet, I'd prefer to keep them out so that I don't need to unpack/change/repack the war file every time I deploy the application to a different database/ip/database user/so on.

How do you solve this problem (in particular, using Tomcat as the web container?)

Best regards
Andrea Aime

2. Senior Member
Join Date
Aug 2004
Location
Melbourne, Australia
Posts
1,104
I'm looking for a way to keep my property files outside the war file of my application
Which properties? If it's PropertyPlaceholderConfigurer, you can use something like:
<property name="location"><value>file:/temp/jdbc.properties</value></property>

so that I don't need to unpack/change/repack the war file every time I deploy the application
Usually you can pretty much automate this - loading different properties for different environments so it isn't much of a hassle. It can also be version controlled which is generally safer.

3. Member
Join Date
Aug 2004
Posts
56
Originally Posted by katentim
I'm looking for a way to keep my property files outside the war file of my application
Which properties? If it's PropertyPlaceholderConfigurer, you can use something like:
<property name="location"><value>file:/temp/jdbc.properties</value></property>
That's a fixed location. Bad idea, my clients may want to redeploy the application on a different filesystem/operating system.

so that I don't need to unpack/change/repack the war file every time I deploy the application
Usually you can pretty much automate this - loading different properties for different environments so it isn't much of a hassle. It can also be version controlled which is generally safer.[/quote]

Not that I can control this much... I would like to provide my client IT department with simple instructions on how to move the application, the database and so on.

4. Senior Member
Join Date
Aug 2004
Location
Melbourne, Australia
Posts
1,104
That's a fixed location. Bad idea, my clients may want to redeploy the application on a different filesystem/operating system.
What about a simple install program to modify the WAR appropriately? Maybe a setup page on the WAR to edit some configuration parameters on installation?

5. Senior Member
Join Date
Oct 2004
Location
Herndon, VA, US
Posts
648
There was some discussion about JNDI based property placeholder last week. It could be an alternative for you. I don't remember which forum it was now though - either this or "Web".

6. Member
Join Date
Aug 2004
Posts
56
Well, so far I've put a property file with the same name as the application in tomcat/shared/classes. It's easy to modify, and should not conflict with other applications (and I don't need to write an application to modify the war file)
Yet, I'd prefer a solution where only my application sees that file...

7. Senior Member
Join Date
Sep 2004
Posts
1,086
Solution I used is to simply omit a path and put the file in the current folder. Also, putting the file on the server classpath is is a good solution (tomcat/common/classes).

8. Junior Member
Join Date
Dec 2004
Location
Duluth, MN
Posts
18
In order to keep my configurations somewhat container- and OS-independent, I use a combination of a JNDI environment variable and a PropertyPlaceholderConfigurer to load and apply configuration information. Under Tomcat, here's how it works.

First, in the application's context.xml, I define a resource string containing the path to the configuration file:

Code:
    <Context ...>
<!-- Location of the deployment configuration file -->
<Environment name="config/configurationPath"
type="java.lang.String"
value="file&#58;C&#58;\path\to\config.properties" />
...
</Context>
Then in my Spring bean files, I extract the value from JNDI and define and configure the PropertyPlaceholderConfigurer as such:

Code:
    <beans ...>

<!-- Import deployment configuration file path from JNDI -->
<bean id="configurationPath"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java&#58;comp/env/config/configurationPath</value>
</property>
</bean>

<!-- Load our substitution properties into a Properties object. -->
<bean id="configurationProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<ref bean="configurationPath" />
</property>
</bean>

<!-- Property configurer for pulling property settings from
applicationContext.properties -->
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties">
<ref bean="configurationProperties" />
</property>
</bean>
...
</beans>
Obviously, this can be simplified and collapsed into fewer bean definitions as you desire. I used 3 separate definitions in the project from which this example was extracted, but the reasons for that are unrelated to this thread.

This scheme allows the deployer to move the configuration file to any location that can be specified via a Spring resource string. WARs need not be unpacked (though unpacking them doesn't hurt either.) With a few minor changes, you could also cause the configuration to default back to an in-WAR 'classpath:' configuration file if you so desired.

I apologize if I'm not answering the correct question here. Always a possibility. :-)

9. Junior Member
Join Date
Aug 2004
Posts
2
You could use a subclass of PropertyPlaceHolderConfigurer that resolves placeholders as environment entry:

Code:
package org.sprfr;

import java.util.Properties;

import javax.naming.NamingException;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.jndi.JndiTemplate;

public class EnvEntryPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer implements InitializingBean &#123;

public static String CONTAINER_PREFIX = "java&#58;comp/env/";

private boolean resourceRef = true;

public void setResourceRef&#40;boolean resourceRef&#41; &#123;
this.resourceRef = resourceRef;
&#125;

public boolean isResourceRef&#40;&#41; &#123;
return resourceRef;
&#125;

private boolean envEntryOverride = false;

private JndiTemplate jndiTemplate;

public void setEnvEntryOverride&#40;boolean contextOverride&#41; &#123;
this.envEntryOverride = contextOverride;
&#125;

public void afterPropertiesSet&#40;&#41; throws Exception &#123;
this.jndiTemplate = new JndiTemplate&#40;&#41;;
&#125;

protected String resolvePlaceholder&#40;String placeholder, Properties props&#41; &#123;
String value = null;
if &#40;this.envEntryOverride&#41; &#123;
value = resolveEnvEntryPlaceholder&#40;placeholder&#41;;
&#125;
if &#40;value == null&#41; &#123;
value = super.resolvePlaceholder&#40;placeholder, props&#41;;
&#125;
if &#40;value == null&#41; &#123;
value = resolveEnvEntryPlaceholder&#40;placeholder&#41;;
&#125;
return value;
&#125;

protected String resolveEnvEntryPlaceholder&#40;String placeholder&#41; &#123;
String value = null;
Object envEntry = null;
try &#123;
String jndiNameToUse = convertJndiName&#40;placeholder&#41;;
envEntry = jndiTemplate.lookup&#40;jndiNameToUse&#41;;
&#125; catch &#40;NamingException e&#41; &#123;
logger.error&#40;"Naming Exception while trying to lookup env entry " + placeholder, e&#41;;
&#125;
if &#40;envEntry != null&#41; &#123;
value = envEntry.toString&#40;&#41;;
&#125;
return value;
&#125;

protected String convertJndiName&#40;String jndiName&#41; &#123;
if &#40;isResourceRef&#40;&#41; && !jndiName.startsWith&#40;CONTAINER_PREFIX&#41; && jndiName.indexOf&#40;'&#58;'&#41; == -1&#41; &#123;
jndiName = &#40;new StringBuffer&#40;CONTAINER_PREFIX&#41;.append&#40;jndiName&#41;&#41;.toString&#40;&#41;;
&#125;
return jndiName;
&#125;
&#125;

Code:
<bean id="propertyConfigurer" class="org.sprfr.EnvEntryPropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath&#58;/app.properties</value>
<value>classpath&#58;/jdbc.properties</value>
</list>
</property>
</bean>
You add a context file descriptor in $CATALINA_HOME/conf/[enginename]/[hostname]/[context].xml where you define the environment entry : Code: <Context reloadable="false" debug="0"> <Environment name="myentry" type="java.lang.String" value="myvalue"/> </Context> And use it in your context: Code:  <bean id="myBean" class="MyBean"> <property name="myProperty"><value>$&#123;myentry&#125;</value></property>
</bean>
You can also define a default value in your app.properties and set envEntryOverride to true on propertyConfigurer. So you could deploy your war without context descriptor. And if you need to override some properties, you create one.

Hope this helps.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•