Skip to content

Instantly share code, notes, and snippets.

@agentgt
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agentgt/8870316 to your computer and use it in GitHub Desktop.
Save agentgt/8870316 to your computer and use it in GitHub Desktop.
Spring Configuration Overlaying
import static java.util.Arrays.asList;
import static org.springframework.util.StringUtils.hasText;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePropertySource;
import org.springframework.util.StringUtils;
public class AbstractConfigResourcesFactoryBean {
private String defaultResources;
private boolean searchSystemEnvironment = true;
private String parameterName;
private String servletContextParamValue;
private ApplicationContext applicationContext;
private static enum ConfigParameterType {
SYSTEM_ENVIRONMENT(true),
SERVLET_CONFIG(true),
DEFAULT(false);
private boolean failIfParameterProvidedButNoneFound;
private ConfigParameterType(boolean failIfParameterProvidedButNoneFound) {
this.failIfParameterProvidedButNoneFound = failIfParameterProvidedButNoneFound;
}
public boolean isFailIfParameterProvidedButNoneFound() {
return failIfParameterProvidedButNoneFound;
}
}
public void setDefaultResources(String defaultValue) {
this.defaultResources = defaultValue;
}
public Resource[] getResources() {
ArrayList<Resource> rs = new ArrayList<Resource>();
add(rs, defaultResources, ConfigParameterType.DEFAULT);
add(rs, servletContextParamValue, ConfigParameterType.SERVLET_CONFIG);
add(rs, resolveSystemProperty(parameterName), ConfigParameterType.SYSTEM_ENVIRONMENT);
logger.info("Found the following\nconfig resources:\n "
+ StringUtils.collectionToDelimitedString(rs, "\n "));
return rs.toArray(new Resource[rs.size()]);
}
public List<ResourcePropertySource> getResourcePropertySources() throws IOException {
Resource[] rs = getResources();
List<ResourcePropertySource> rp = new ArrayList<ResourcePropertySource>(rs.length);
for (Resource r: rs) {
rp.add(new ResourcePropertySource(r));
}
return rp;
}
private int add(ArrayList<Resource> rs, String pattern, ConfigParameterType type) {
Resource[] r = loadConfig(pattern, type);
int files = -1;
if (r != null) {
files = r.length;
rs.addAll(asList(r));
}
return files;
}
private Resource[] loadConfig(String config, ConfigParameterType t) {
if (! hasText(config) ) {
logger.info("No config location specified by: {} for parameter: {}", t, parameterName);
return null;
}
logger.info("Config location specified by: " + t + " for parameter: " + parameterName
+ " Loading config from: " + config);
try {
Resource[] resources = applicationContext.getResources(config);
if (t.isFailIfParameterProvidedButNoneFound() && resources != null && resources.length == 0) {
throw new RuntimeException("Error no config files found for: " + config);
}
return resources;
} catch (IOException e) {
throw new RuntimeException("Error loading config: " + config, e);
}
}
/**
* Set the name of the ServletContext init parameter to expose.
* @param initParamName
*/
public void setParameterName(String initParamName) {
this.parameterName = initParamName;
}
public void setServletContext(ServletContext servletContext) {
if (this.parameterName == null) {
throw new IllegalArgumentException("initParamName is required");
}
String contextPath = servletContext.getContextPath().replaceAll("/", "");
String displayName = servletContext.getServletContextName();
List<String> parameterNamesToTry = new ArrayList<String>();
if (hasText(contextPath) && hasText(displayName)) {
parameterNamesToTry.add(displayName + "-" + contextPath + "-" + parameterName);
}
if (hasText(contextPath)) {
parameterNamesToTry.add(contextPath + "-" + parameterName);
}
if (hasText(displayName)) {
parameterNamesToTry.add(displayName + "-" + parameterName);
}
parameterNamesToTry.add(parameterName);
for (String p : parameterNamesToTry) {
this.servletContextParamValue = servletContext.getInitParameter(p);
if (this.servletContextParamValue != null) {
logger.info("Using servlet context parameter name: " + p);
break;
}
}
if (this.servletContextParamValue == null) {
logger.debug("No ServletContext init parameter with any of these names '" +
parameterNamesToTry + "' found");
}
}
/**
* Resolve the given key as JVM system property, and optionally also as
* system environment variable if no matching system property has been found.
* @param key the placeholder to resolve as system property key
* @return the system property value, or <code>null</code> if not found
* @see #setSearchSystemEnvironment
* @see java.lang.System#getProperty(String)
* @see java.lang.System#getenv(String)
*/
protected String resolveSystemProperty(String key) {
try {
String value = System.getProperty(key);
if (value == null && this.searchSystemEnvironment) {
value = System.getenv(key);
}
return value;
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not access system property '" + key + "': " + ex);
}
return null;
}
}
public void setSearchSystemEnvironment(boolean searchSystemEnvironment) {
this.searchSystemEnvironment = searchSystemEnvironment;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
private static final Logger logger = LoggerFactory.getLogger(AbstractConfigResourcesFactoryBean.class);
}
import static java.util.Collections.reverse;
import java.io.IOException;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.support.ResourcePropertySource;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;
public class MyConfigContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext context) {
ContextInitializerConfigResources resources = new ContextInitializerConfigResources(context,
"MyConfigParameter",
"classpath*:META-INF/spring/*.properties");
List<ResourcePropertySource> propertyFiles;
try {
propertyFiles = resources.getResourcePropertySources();
} catch (IOException e) {
throw new RuntimeException(e);
}
//Spring prefers primacy ordering so we reverse the order of the files.
reverse(propertyFiles);
for (ResourcePropertySource rp : propertyFiles) {
context.getEnvironment().getPropertySources().addLast(rp);
}
String profiles = context.getEnvironment().getProperty("MyConfig.profiles");
log.info("Using profiles: " + profiles);
if (StringUtils.hasText(profiles)) {
String[] ps = StringUtils.commaDelimitedListToStringArray(profiles);
context.getEnvironment().setActiveProfiles(ps);
}
}
private static class ContextInitializerConfigResources extends AbstractConfigResourcesFactoryBean {
private ContextInitializerConfigResources(ConfigurableApplicationContext context, String parameterName, String defaultResources) {
super();
setParameterName(parameterName);
setDefaultResources(defaultResources);
setApplicationContext(context);
if (context instanceof WebApplicationContext) {
WebApplicationContext c = (WebApplicationContext) context;
if (c.getServletContext() != null)
setServletContext(c.getServletContext());
}
setSearchSystemEnvironment(true);
}
}
private static final Logger log = LoggerFactory.getLogger(MyConfigContextInitializer.class);
}
@agentgt
Copy link
Author

agentgt commented Feb 7, 2014

Google how to setup ApplicationContextInitializer in Spring documentation.

@agentgt
Copy link
Author

agentgt commented Jun 2, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment