This section includes topics relating directly to Spring Boot applications.
FailureAnalyzer
is a great way
to intercept an exception on startup and turn it into a human-readable message, wrapped
in a FailureAnalysis
. Spring
Boot provides such an analyzer for application-context-related exceptions, JSR-303
validations, and more. You can also 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 cannot handle the exception, return null
to give another implementation a chance to handle the exception.
FailureAnalyzer
implementations must be registered in META-INF/spring.factories
.
The following example registers ProjectConstraintViolationFailureAnalyzer
:
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
Note | |
---|---|
If you need access to the |
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 can see it if you enable DEBUG
logging output. If you use
the spring-boot-actuator
(see the Actuator chapter),
there is also a conditions
endpoint that renders the report in JSON. Use that endpoint
to debug the application and see what features have been added (and which have not been
added) by Spring Boot at runtime.
Many more questions can be answered by looking at the source code and the Javadoc. When reading the code, remember the following rules of thumb:
*AutoConfiguration
and read their sources. Pay special
attention to the @Conditional*
annotations to find out what features they enable and
when. Add --debug
to the command line or a System property -Ddebug
to 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 the conditions
endpoint (/actuator/conditions
or the JMX
equivalent) for the same information.@ConfigurationProperties
(such as
ServerProperties
)
and read from there the available external configuration options. The
@ConfigurationProperties
annotation has a name
attribute that acts as a prefix to
external properties. Thus, ServerProperties
has prefix="server"
and its configuration
properties are server.port
, server.address
, and others. In a running Actuator app,
look at the configprops
endpoint.bind
method on the Binder
to pull configuration values
explicitly out of the Environment
in a relaxed manner. It is often used with a prefix.@Value
annotations that bind directly to the Environment
.@ConditionalOnExpression
annotations that switch features on and off in
response to SpEL expressions, normally evaluated with placeholders resolved from the
Environment
.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 customizations:
addListeners
and addInitializers
methods on SpringApplication
before you run it.context.initializer.classes
or
context.listener.classes
properties.META-INF/spring.factories
and packaging
a jar file that the applications all use as a library.The SpringApplication
sends some special ApplicationEvents
to the listeners (some
even 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 by using EnvironmentPostProcessor
. Each implementation should be registered in
META-INF/spring.factories
, as shown in the following example:
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
The implementation can load arbitrary files and add them to the Environment
. For
instance, the following 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 |
Caution | |
---|---|
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, you can use 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
leave the servlet API dependencies off the classpath. If you cannot do that (for example, you
run two 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.