I just solved a similar problem in a slightly different way. Our customer wants to configure database connection details, integration server locations and ports etc. without rebuilding the war. Using environment property to point an external file containing the information may or may not be okay, but it felt a bit dirty trick. Anyway, here's a slightly more enterprisey way.
For database connections we use JNDI lookup and below is the current solution for integration server parametrization. The parameters can come from at least three different sources now:
- properties-file, which is overridable with Maven profiles and requires single line of xml in spring configuration to be accessible. This is obviously inside the war file.
- web.xml context-param. This is also, of course, inside the war file.
- Tomcat server can override the init parameters with context.xml which can be outside the war. This happens to be the same file where JNDI context is defined, which is nice.
Below is the implementation for configuration accessor bean. It can run in servlet context and also without one (for some unit tests it makes little sense to kickstart a full-blown web server, but we nevertheless need to satisfy spring bean injections).
I don't mean this to be a perfect solution, but it is one. Didn't find anything like this with google.
@Service
public class IntegrationConfigurationImpl implements
IntegrationConfiguration, InitializingBean,
ServletContextAware, ApplicationContextAware {
private static final String SERVER_HOST_PROPERTY = "integration.server.host";
private static final String SERVER_PORT_PROPERTY = "integration.server.port";
private static final String PROPERTY_BEAN_NAME = "integrationProperties";
private ServletContext servletContext;
private ApplicationContext applicationContext;
private static final Logger log = LoggerFactory.getLogger(IntegrationConfigurationImpl.class);
private String serverHost = "foo";
private int serverPort = 42;
@Override
public String getServerHost() {
return serverHost;
}
@Override
public int getServerPort() {
return serverPort;
}
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
// konfiguraation validointi..
if (servletContext == null) {
log.info("servlet context not set, not running as a web application. Trying to get properties from application context");
if (applicationContext.containsBean(PROPERTY_BEAN_NAME)) {
Properties p = (Properties)applicationContext.getBean(PROPERTY_BEAN_NAME);
serverHost = p.getProperty(SERVER_HOST_PROPERTY);
serverPort = Integer.valueOf(p.getProperty(SERVER_PORT_PROPERTY)).intValue();
} else {
log.info("Property bean not found :" + PROPERTY_BEAN_NAME);
}
} else {
serverHost = servletContext.getInitParameter(SERVER_HOST_PROPERTY);
serverPort = Integer.valueOf(servletContext.getInitParameter(SERVER_PORT_PROPERTY)).intValue();
}
log.info("Using integration server " + getServerHost() + ", port " + getServerPort());
}
}