Skip to content

Instantly share code, notes, and snippets.

@serac
Last active April 5, 2018 16:23
Show Gist options
  • Save serac/7e006dc680f17c7f7b9af0c2e70f69f5 to your computer and use it in GitHub Desktop.
Save serac/7e006dc680f17c7f7b9af0c2e70f69f5 to your computer and use it in GitHub Desktop.
Custom Spring Boot Environment Configuration
/* https://www.gnu.org/licenses/gpl-3.0.en.html */
package your.app;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* Spring boot application listener that prepares the application environment based on the
* <code>--env=(dev|pprd|prod)</code> program option (primary) or <code>env</code> system property (backup).
*
* @author Marvin S. Addison
*/
public class EnvSpringApplicationRunListener implements SpringApplicationRunListener {
/** Name of program option that holds deployment environment name. */
public static final String ENV_ARG_PREFIX = "--env";
/** Name of property that holds deployment environment name. */
public static final String ENV_PROP = "env";
/** Recognized deployment environments. */
private static final List<String> SUPPORTED_ENVIRONMENTS = Arrays.asList("build", "dev", "pprd", "prod");
/** Logger instance. */
private final Logger logger = LoggerFactory.getLogger(EnvSpringApplicationRunListener.class);
/** Spring Boot application instance. */
private final SpringApplication application;
/** Program arguments. */
private final String[] args;
/**
* Creates a new instance.
*
* @param app Spring Boot application instance.
* @param programArgs Program arguments.
*/
public EnvSpringApplicationRunListener(final SpringApplication app, final String[] programArgs) {
application = app;
args = programArgs;
}
@Override
public void starting() {
final String env = getEnv();
if (!SUPPORTED_ENVIRONMENTS.contains(env)) {
throw new IllegalStateException("Unsupported deployment environment: " + env);
}
application.setAdditionalProfiles(env);
}
@Override
public void environmentPrepared(final ConfigurableEnvironment environment) {}
@Override
public void contextPrepared(final ConfigurableApplicationContext context) {}
@Override
public void contextLoaded(final ConfigurableApplicationContext context) {}
@Override
public void started(final ConfigurableApplicationContext context) {}
@Override
public void running(final ConfigurableApplicationContext context) {}
@Override
public void failed(final ConfigurableApplicationContext context, final Throwable exception) {}
/** @return Application environment name. */
public String getEnv() {
for (String arg : args) {
if (arg.startsWith(ENV_ARG_PREFIX)) {
final String[] parts = arg.split("=");
if (parts.length == 2) {
logger.info("Setting application environment to {} based on {} program option", parts[1], ENV_ARG_PREFIX);
return parts[1];
}
}
}
logger.info("Deployment environment not found in program options. Checking system properties");
final String env = System.getProperty(ENV_PROP);
if (env != null) {
return env;
}
throw new IllegalStateException("Cannot determine deployment environment. Please set either '" +
ENV_ARG_PREFIX + "' program option or '" +
ENV_PROP + "' system property");
}
}
org.springframework.boot.SpringApplicationRunListener=your.app.EnvSpringApplicationRunListener
@serac
Copy link
Author

serac commented Apr 5, 2018

This is the only way I have found of providing a custom configuration strategy that is used regardless of how the application is launched. In particular I care about consistency between the environment of a unit test and the running application.

Note that spring.factories has a well-defined classpath location, /META-INF/spring.factories.

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