On this page
71. Spring Boot application
FailureAnalyzer is a great way to intercept an exception on startup and turn it into a human-readable message, wrapped into a FailureAnalysis . Spring Boot provides such analyzer for application context related exceptions, JSR-303 validations and more. It is actually very easy to create your own.
AbstractFailureAnalyzer is a convenient extension of FailureAnalyzer that checks the presence of a specified exception type in the exception to handle. You can extend from that so that your implementation gets a chance to handle the exception only when it is actually present. If for whatever reason you can’t handle the exception, return null to give another implementation a chance to handle the exception.
FailureAnalyzer implementations are to be registered in a META-INF/spring.factories: the following registers ProjectConstraintViolationFailureAnalyzer:
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
The Spring Boot auto-configuration tries its best to ‘do the right thing’, but sometimes things fail and it can be hard to tell why.
There is a really useful ConditionEvaluationReport available in any Spring Boot ApplicationContext. You will see it if you enable DEBUG logging output. If you use the spring-boot-actuator there is also an autoconfig endpoint that renders the report in JSON. Use that to debug the application and see what features have been added (and which not) by Spring Boot at runtime.
Many more questions can be answered by looking at the source code and the Javadoc. Some rules of thumb:
- Look for classes called
*AutoConfigurationand read their sources, in particular the@Conditional*annotations to find out what features they enable and when. Add--debugto the command line or a System property-Ddebugto get a log on the console of all the auto-configuration decisions that were made in your app. In a running Actuator app look at theautoconfigendpoint (‘/autoconfig’ or the JMX equivalent) for the same information. - Look for classes that are
@ConfigurationProperties(e.g.ServerProperties) and read from there the available external configuration options. The@ConfigurationPropertieshas anameattribute which acts as a prefix to external properties, thusServerPropertieshasprefix="server"and its configuration properties areserver.port,server.addressetc. In a running Actuator app look at theconfigpropsendpoint. - Look for use of
RelaxedPropertyResolverto pull configuration values explicitly out of theEnvironment. It often is used with a prefix. - Look for
@Valueannotations that bind directly to theEnvironment. This is less flexible than theRelaxedPropertyResolverapproach, but does allow some relaxed binding, specifically for OS environment variables (soCAPITALS_AND_UNDERSCORESare synonyms forperiod.separated). - Look for
@ConditionalOnExpressionannotations that switch features on and off in response to SpEL expressions, normally evaluated with placeholders resolved from theEnvironment.
A SpringApplication has ApplicationListeners and ApplicationContextInitializers that are used to apply customizations to the context or environment. Spring Boot loads a number of such customizations for use internally from META-INF/spring.factories. There is more than one way to register additional ones:
- Programmatically per application by calling the
addListenersandaddInitializersmethods onSpringApplicationbefore you run it. - Declaratively per application by setting
context.initializer.classesorcontext.listener.classes. - Declaratively for all applications by adding a
META-INF/spring.factoriesand packaging a jar file that the applications all use as a library.
The SpringApplication sends some special ApplicationEvents to the listeners (even some before the context is created), and then registers the listeners for events published by the ApplicationContext as well. See Section 23.5, “Application events and listeners” in the ‘Spring Boot features’ section for a complete list.
It is also possible to customize the Environment before the application context is refreshed using EnvironmentPostProcessor. Each implementation should be registered in META-INF/spring.factories:
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
The implementation can load arbitrary files and add them to the Environment. For instance, this example loads a YAML configuration file from the classpath:
public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor {
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
Resource path = new ClassPathResource("com/example/myapp/config.yml");
PropertySource<?> propertySource = loadYaml(path);
environment.getPropertySources().addLast(propertySource);
}
private PropertySource<?> loadYaml(Resource path) {
if (!path.exists()) {
throw new IllegalArgumentException("Resource " + path + " does not exist");
}
try {
return this.loader.load("custom-resource", path, null);
}
catch (IOException ex) {
throw new IllegalStateException(
"Failed to load yaml configuration from " + path, ex);
}
}
}
![]() |
Tip |
|---|---|
The |
![]() |
Note |
|---|---|
While using |
You can use the ApplicationBuilder class to create parent/child ApplicationContext hierarchies. See Section 23.4, “Fluent builder API” in the ‘Spring Boot features’ section for more information.
Not all Spring applications have to be web applications (or web services). If you want to execute some code in a main method, but also bootstrap a Spring application to set up the infrastructure to use, then it’s easy with the SpringApplication features of Spring Boot. A SpringApplication changes its ApplicationContext class depending on whether it thinks it needs a web application or not. The first thing you can do to help it is to just leave the servlet API dependencies off the classpath. If you can’t do that (e.g. you are running 2 applications from the same code base) then you can explicitly call setWebEnvironment(false) on your SpringApplication instance, or set the applicationContextClass property (through the Java API or with external properties). Application code that you want to run as your business logic can be implemented as a CommandLineRunner and dropped into the context as a @Bean definition.
![[Tip]](/images/spring-boot/1.5.9.RELEASE/tip.png)
![[Note]](/images/spring-boot/1.5.9.RELEASE/note.png)