I'm using Spring 3.2 in a web application and I'd like to have a .properties
file within the classpath which contains default values. The user should be able to use JNDI to define a location where another .properties
is stored which overrides the default values.
The following works as long as the user has set the configLocation
as JNDI property.
@Configuration
@PropertySource({ "classpath:default.properties", "file:${java:comp/env/configLocation}/override.properties" })
public class AppConfig
{
}
However, the external overrides should be optional and so should the JNDI property.
Currently I get an exception (java.io.FileNotFoundException: comp\env\configLocation\app.properties (The system cannot find the path specified)
when the JNDI property is missing.
How can I define optional .properties
that are used only when the JNDI property (configLocation
) is set? Is this even possible with @PropertySource
or is there another solution?
Try the following. Create a ApplicationContextInitializer
In a Web Context: ApplicationContextInitializer<ConfigurableWebApplicationContext>
and register it in the web.xml via:
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>...ContextInitializer</param-value>
</context-param>
In the ContextInitializer you can add your property files via classpath and file system (haven't tried JNDI though).
public void initialize(ConfigurableWebApplicationContext applicationContext) {
String activeProfileName = null;
String location = null;
try {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String appconfigDir = environment.getProperty(APPCONFIG);
if (appconfigDir == null ) {
logger.error("missing property: " + APPCONFIG);
appconfigDir = "/tmp";
}
String[] activeProfiles = environment.getActiveProfiles();
for ( int i = 0; i < activeProfiles.length; i++ ) {
activeProfileName = activeProfiles[i];
MutablePropertySources propertySources = environment.getPropertySources();
location = "file://" + appconfigDir + activeProfileName + ".properties";
addPropertySource(applicationContext, activeProfileName,
location, propertySources);
location = "classpath:/" + activeProfileName + ".properties";
addPropertySource(applicationContext, activeProfileName,
location, propertySources);
}
logger.debug("environment: '{}'", environment.getProperty("env"));
} catch (IOException e) {
logger.info("could not find properties file for active Spring profile '{}' (tried '{}')", activeProfileName, location);
e.printStackTrace();
}
}
private void addPropertySource(ConfigurableWebApplicationContext applicationContext, String activeProfileName,
String location, MutablePropertySources propertySources) throws IOException {
Resource resource = applicationContext.getResource(location);
if ( resource.exists() ) {
ResourcePropertySource propertySource = new ResourcePropertySource(location);
propertySources.addLast(propertySource);
} else {
logger.info("could not find properties file for active Spring profile '{}' (tried '{}')", activeProfileName, location);
}
}
The code above tries to find a property file per active profile (see: How to set active spring 3.1 environment profile via a properites file and not via an env variable or system property)