I have a web application that works with several different configurations of Spring Security already. However, these difference configuration are all setup within my applicationContext configuration file. Therefore, in order to tweak these at a customer site, these would have to be modified INSIDE the WAR file. If customers manually modify the WAR file, then they'll lose their changes after redeploying a new WAR.
Is there a way to externalize this configuration? Is there a way I can load the configuration using JNDI somehow?
It's an interesting question. Since Spring Security should be configured in root webapp context, you can't externalize its configuration to other contexts. Also you can't change the set of config resources from inside the context. So, you should do it from outside:
You can use a well-known file system location:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
file:///C:\config.xml
</param-value>
</context-param>
System properties are resolved in contextConfigLocation
, so you can use it:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
file:///${configPath}
</param-value>
</context-param>
and -DconfigPath=...
You can override XmlWebApplicationContext.getResource()
and implement whatever you want:
public class MyXmlWebApplicationContext extends XmlWebApplicationContext {
private static final String JNDI_PREFIX = "jndi:/";
@Override
public Resource getResource(String location) {
if (location.startsWith(JNDI_PREFIX)) return getJndiResource(location);
else return super.getResource(location);
}
protected Resource getJndiResource(String location) { ... }
}
and
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
jndi:/...
</param-value>
</context-param>
<context-param>
<param-name>contextClass</param-name>
<param-value>com.example.MyXmlWebApplicationContext</param-value>
</context-param>
Alternatively you can use org.springmodules.commons.configuration.CommonsConfigurationFactoryBean to store and retrieve your configuration as key, value pair in database table
<bean name="DatabaseConfiguration" class="org.apache.commons.configuration.DatabaseConfiguration">
<constructor-arg type="javax.sql.DataSource" ref="dataSource"/>
<constructor-arg index="1" value="CONFIG_TABLE_NAME"/>
<constructor-arg index="2" value="KEY_COLUMN_NAME"/>
<constructor-arg index="3" value="VALUE_COLUMN_NAME"/>
</bean>
You can add a org.springframework.beans.factory.config.PropertyPlaceholderConfigurer, which references an external file, then use the ${key} syntax without your Spring configuration files to reference key/value pairs in the externalized property file.
Another solution is to specify an absolute path in your web.xml to reference a Spring contextConfigLocation.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/absolute_path/ldap.xml, /WEB-INF/context/dao-context.xml</param-value>
</context-param>
Here is a free configuration tool: http://go.eeye.com/icwt that tests your environment for highly recommended configuration updates, how the local OS is configured (identifies potential problem areas), identifies areas concerning APTs, and shows if your processes and code are signed.
Spring comes with a couple of options for externalizing
Spring configuration details into property files that can be managed outside of the
deployed application:
- Property placeholder configurers replace placeholder variables placed in property
values with values from an external properties file.
- Property overriders override bean property values with values from an external
properties file. In addition, the open source Jasypt project
offers alternative implementations ofS pring’s property placeholder configurer and overrider that can pull those values from encrypted properties files.
A placeholder configurer can be configured like this for classpath
A placeholder configurer can be configured like this for filepath
if db.properties contains as follows
jdbc.driverClassName=DriverclassName
jdbc.url=Driverclass://localhost/applicationname/
jdbc.username=test
jdbc.password=test1
Now we can replace the hardcoded values in the Spring configuration with place-holder variables based on the properties in db.properties
It depends. If you want modify authorizations, you can use Requestmap and save all the authorization configurations in database, then deliver different versions with external bootstrap data definitions.