2019-03-27 12:22:40 +00:00

3412 lines
130 KiB
Plaintext

[[howto]]
= '`How-to`' guides
[partintro]
--
This section provides answers to some common '`how do I do that...`' type of questions
that often arise when using Spring Boot. This is by no means an exhaustive list, but it
does cover quite a lot.
If you are having a specific problem that we don't cover here, you might want to check out
https://stackoverflow.com/tags/spring-boot[stackoverflow.com] to see if someone has
already provided an answer; this is also a great place to ask new questions (please use
the `spring-boot` tag).
We're also more than happy to extend this section; If you want to add a '`how-to`' you
can send us a {github-code}[pull request].
--
[[howto-spring-boot-application]]
== Spring Boot application
[[howto-failure-analyzer]]
=== Create your own FailureAnalyzer
{dc-spring-boot}/diagnostics/FailureAnalyzer.{dc-ext}[`FailureAnalyzer`] is a great way
to intercept an exception on startup and turn it into a human-readable message, wrapped
into a {dc-spring-boot}/diagnostics/FailureAnalysis.{dc-ext}[`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`:
[source,properties,indent=0]
----
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
----
[[howto-troubleshoot-auto-configuration]]
=== Troubleshoot auto-configuration
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 `+*AutoConfiguration+` and read their sources, in particular 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 `autoconfig` endpoint ('`/autoconfig`' or the JMX equivalent) for
the same information.
* Look for classes that are `@ConfigurationProperties` (e.g.
{sc-spring-boot-autoconfigure}/web/ServerProperties.{sc-ext}[`ServerProperties`])
and read from there the available external configuration options. The
`@ConfigurationProperties` has a `name` attribute which acts as a prefix to external
properties, thus `ServerProperties` has `prefix="server"` and its configuration properties
are `server.port`, `server.address` etc. In a running Actuator app look at the
`configprops` endpoint.
* Look for use of `RelaxedPropertyResolver` to pull configuration values explicitly out of the
`Environment`. It often is used with a prefix.
* Look for `@Value` annotations that bind directly to the `Environment`. This is less
flexible than the `RelaxedPropertyResolver` approach, but does allow some relaxed binding,
specifically for OS environment variables (so `CAPITALS_AND_UNDERSCORES` are synonyms
for `period.separated`).
* Look for `@ConditionalOnExpression` annotations that switch features on and off in
response to SpEL expressions, normally evaluated with placeholders resolved from the
`Environment`.
[[howto-customize-the-environment-or-application-context]]
=== Customize the Environment or ApplicationContext before it starts
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 `addListeners` and `addInitializers`
methods on `SpringApplication` before you run it.
* Declaratively per application by setting `context.initializer.classes` or
`context.listener.classes`.
* Declaratively for all applications by adding a `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 (even
some before the context is created), and then registers the listeners for events published
by the `ApplicationContext` as well. See
_<<spring-boot-features.adoc#boot-features-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`:
[source,properties,indent=0]
----
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
----
[[howto-build-an-application-context-hierarchy]]
=== Build an ApplicationContext hierarchy (adding a parent or root context)
You can use the `ApplicationBuilder` class to create parent/child `ApplicationContext`
hierarchies. See _<<spring-boot-features.adoc#boot-features-fluent-builder-api>>_
in the '`Spring Boot features`' section for more information.
[[howto-create-a-non-web-application]]
=== Create a non-web application
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.
[[howto-properties-and-configuration]]
== Properties & configuration
[[howto-automatic-expansion]]
=== Automatically expand properties at build time
Rather than hardcoding some properties that are also specified in your project's build
configuration, you can automatically expand them using the existing build configuration
instead. This is possible in both Maven and Gradle.
[[howto-automatic-expansion-maven]]
==== Automatic property expansion using Maven
You can automatically expand properties from the Maven project using resource
filtering. If you use the `spring-boot-starter-parent` you can then refer to your
Maven '`project properties`' via `@..@` placeholders, e.g.
[source,properties,indent=0]
----
app.encoding=@project.build.sourceEncoding@
app.java.version=@java.version@
----
TIP: The `spring-boot:run` can add `src/main/resources` directly to the classpath
(for hot reloading purposes) if you enable the `addResources` flag. This circumvents
the resource filtering and this feature. You can use the `exec:java` goal instead
or customize the plugin's configuration, see the
{spring-boot-maven-plugin-site}/usage.html[plugin usage page] for more details.
If you don't use the starter parent, in your `pom.xml` you need (inside the `<build/>`
element):
[source,xml,indent=0]
----
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
----
and (inside `<plugins/>`):
[source,xml,indent=0]
----
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
----
NOTE: The `useDefaultDelimiters` property is important if you are using standard Spring
placeholders in your configuration (e.g. `${foo}`). These may be expanded by the build if
that property is not set to `false`.
[[howto-automatic-expansion-gradle]]
==== Automatic property expansion using Gradle
You can automatically expand properties from the Gradle project by configuring the
Java plugin's `processResources` task to do so:
[source,groovy,indent=0]
----
processResources {
expand(project.properties)
}
----
You can then refer to your Gradle project's properties via placeholders, e.g.
[source,properties,indent=0]
----
app.name=${name}
app.description=${description}
----
NOTE: Gradle's `expand` method uses Groovy's `SimpleTemplateEngine` which transforms
`${..}` tokens. The `${..}` style conflicts with Spring's own property placeholder
mechanism. To use Spring property placeholders together with automatic expansion
the Spring property placeholders need to be escaped like `\${..}`.
[[howto-externalize-configuration]]
=== Externalize the configuration of SpringApplication
A `SpringApplication` has bean properties (mainly setters) so you can use its Java API as
you create the application to modify its behavior. Or you can externalize the
configuration using properties in `+spring.main.*+`. E.g. in `application.properties` you
might have.
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
spring.main.web-environment=false
spring.main.banner-mode=off
----
and then the Spring Boot banner will not be printed on startup, and the application will
not be a web application.
NOTE: The example above also demonstrates how flexible binding allows the use of
underscores (`_`) as well as dashes (`-`) in property names.
Properties defined in external configuration overrides the values specified via the Java
API with the notable exception of the sources used to create the `ApplicationContext`. Let's
consider this application
[source,java,indent=0]
----
new SpringApplicationBuilder()
.bannerMode(Banner.Mode.OFF)
.sources(demo.MyApp.class)
.run(args);
----
used with the following configuration:
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
spring.main.sources=com.acme.Config,com.acme.ExtraConfig
spring.main.banner-mode=console
----
The actual application will _now_ show the banner (as overridden by configuration) and use
three sources for the `ApplicationContext` (in that order): `demo.MyApp`, `com.acme.Config`,
`com.acme.ExtraConfig`.
[[howto-change-the-location-of-external-properties]]
=== Change the location of external properties of an application
By default properties from different sources are added to the Spring `Environment` in a
defined order (see _<<spring-boot-features.adoc#boot-features-external-config>>_ in
the '`Spring Boot features`' section for the exact order).
A nice way to augment and modify this is to add `@PropertySource` annotations to your
application sources. Classes passed to the `SpringApplication` static convenience
methods, and those added using `setSources()` are inspected to see if they have
`@PropertySources`, and if they do, those properties are added to the `Environment` early
enough to be used in all phases of the `ApplicationContext` lifecycle. Properties added
in this way have lower
priority than any added using the default locations (e.g. `application.properties`), system properties, environment variables or the command line.
You can also provide System properties (or environment variables) to change the behavior:
* `spring.config.name` (`SPRING_CONFIG_NAME`), defaults to `application` as the root of
the file name.
* `spring.config.location` (`SPRING_CONFIG_LOCATION`) is the file to load (e.g. a classpath
resource or a URL). A separate `Environment` property source is set up for this document
and it can be overridden by system properties, environment variables or the
command line.
No matter what you set in the environment, Spring Boot will always load
`application.properties` as described above. If YAML is used then files with the '`.yml`'
extension are also added to the list by default.
Spring Boot logs the configuration files that are loaded at `DEBUG` level and the
candidates it has not found at `TRACE` level.
See {sc-spring-boot}/context/config/ConfigFileApplicationListener.{sc-ext}[`ConfigFileApplicationListener`]
for more detail.
[[howto-use-short-command-line-arguments]]
=== Use '`short`' command line arguments
Some people like to use (for example) `--port=9000` instead of `--server.port=9000` to
set configuration properties on the command line. You can easily enable this by using
placeholders in `application.properties`, e.g.
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
server.port=${port:8080}
----
TIP: If you are inheriting from the `spring-boot-starter-parent` POM, the default filter
token of the `maven-resources-plugins` has been changed from `+${*}+` to `@` (i.e.
`@maven.token@` instead of `${maven.token}`) to prevent conflicts with Spring-style
placeholders. If you have enabled maven filtering for the `application.properties`
directly, you may want to also change the default filter token to use
https://maven.apache.org/plugins/maven-resources-plugin/resources-mojo.html#delimiters[other delimiters].
NOTE: In this specific case the port binding will work in a PaaS environment like Heroku
and Cloud Foundry, since in those two platforms the `PORT` environment variable is set
automatically and Spring can bind to capitalized synonyms for `Environment` properties.
[[howto-use-yaml-for-external-properties]]
=== Use YAML for external properties
YAML is a superset of JSON and as such is a very convenient syntax for storing external
properties in a hierarchical format. E.g.
[source,yaml,indent=0,subs="verbatim,quotes,attributes"]
----
spring:
application:
name: cruncher
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost/test
server:
port: 9000
----
Create a file called `application.yml` and stick it in the root of your classpath, and
also add `snakeyaml` to your dependencies (Maven coordinates `org.yaml:snakeyaml`, already
included if you use the `spring-boot-starter`). A YAML file is parsed to a Java
`Map<String,Object>` (like a JSON object), and Spring Boot flattens the map so that it
is 1-level deep and has period-separated keys, a lot like people are used to with
`Properties` files in Java.
The example YAML above corresponds to an `application.properties` file
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
spring.application.name=cruncher
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/test
server.port=9000
----
See _<<spring-boot-features.adoc#boot-features-external-config-yaml>>_ in
the '`Spring Boot features`' section for more information
about YAML.
[[howto-set-active-spring-profiles]]
=== Set the active Spring profiles
The Spring `Environment` has an API for this, but normally you would set a System property
(`spring.profiles.active`) or an OS environment variable (`SPRING_PROFILES_ACTIVE`). E.g.
launch your application with a `-D` argument (remember to put it before the main class
or jar archive):
[indent=0,subs="verbatim,quotes,attributes"]
----
$ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar
----
In Spring Boot you can also set the active profile in `application.properties`, e.g.
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
spring.profiles.active=production
----
A value set this way is replaced by the System property or environment variable setting,
but not by the `SpringApplicationBuilder.profiles()` method. Thus the latter Java API can
be used to augment the profiles without changing the defaults.
See _<<spring-boot-features.adoc#boot-features-profiles>>_ in
the '`Spring Boot features`' section for more information.
[[howto-change-configuration-depending-on-the-environment]]
=== Change configuration depending on the environment
A YAML file is actually a sequence of documents separated by `---` lines, and each
document is parsed separately to a flattened map.
If a YAML document contains a `spring.profiles` key, then the profiles value
(comma-separated list of profiles) is fed into the Spring
`Environment.acceptsProfiles()` and if any of those profiles is active that document is
included in the final merge (otherwise not).
Example:
[source,yaml,indent=0,subs="verbatim,quotes,attributes"]
----
server:
port: 9000
---
spring:
profiles: development
server:
port: 9001
---
spring:
profiles: production
server:
port: 0
----
In this example the default port is 9000, but if the Spring profile '`development`' is
active then the port is 9001, and if '`production`' is active then it is 0.
The YAML documents are merged in the order they are encountered (so later values override
earlier ones).
To do the same thing with properties files you can use `application-${profile}.properties`
to specify profile-specific values.
[[howto-discover-build-in-options-for-external-properties]]
=== Discover built-in options for external properties
Spring Boot binds external properties from `application.properties` (or `.yml`) (and
other places) into an application at runtime. There is not (and technically cannot be)
an exhaustive list of all supported properties in a single location because contributions
can come from additional jar files on your classpath.
A running application with the Actuator features has a `configprops` endpoint that shows
all the bound and bindable properties available through `@ConfigurationProperties`.
The appendix includes an <<appendix-application-properties#common-application-properties,
`application.properties`>> example with a list of the most common properties supported by
Spring Boot. The definitive list comes from searching the source code for
`@ConfigurationProperties` and `@Value` annotations, as well as the occasional use of
`RelaxedPropertyResolver`.
[[howto-embedded-servlet-containers]]
== Embedded servlet containers
[[howto-add-a-servlet-filter-or-listener]]
=== Add a Servlet, Filter or Listener to an application
There are two ways to add `Servlet`, `Filter`, `ServletContextListener` and the other
listeners supported by the Servlet spec to your application. You can either provide
Spring beans for them, or enable scanning for Servlet components.
[[howto-add-a-servlet-filter-or-listener-as-spring-bean]]
==== Add a Servlet, Filter or Listener using a Spring bean
To add a `Servlet`, `Filter`, or Servlet `*Listener` provide a `@Bean` definition for it.
This can be very useful when you want to inject configuration or dependencies. However,
you must be very careful that they don't cause eager initialization of too many other
beans because they have to be installed in the container very early in the application
lifecycle (e.g. it's not a good idea to have them depend on your `DataSource` or JPA
configuration). You can work around restrictions like that by initializing them lazily
when first used instead of on initialization.
In the case of `Filters` and `Servlets` you can also add mappings and init parameters by
adding a `FilterRegistrationBean` or `ServletRegistrationBean` instead of or as well as
the underlying component.
[NOTE]
====
If no `dispatcherType` is specified on a filter registration, it will match
`FORWARD`,`INCLUDE` and `REQUEST`. If async has been enabled, it will match `ASYNC` as
well.
If you are migrating a filter that has no `dispatcher` element in `web.xml` you will
need to specify a `dispatcherType` yourself:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Bean
public FilterRegistrationBean myFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
....
return registration;
}
----
====
[[howto-disable-registration-of-a-servlet-or-filter]]
===== Disable registration of a Servlet or Filter
As <<howto-add-a-servlet-filter-or-listener-as-spring-bean,described above>> any `Servlet`
or `Filter` beans will be registered with the servlet container automatically. To disable
registration of a particular `Filter` or `Servlet` bean create a registration bean for it
and mark it as disabled. For example:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Bean
public FilterRegistrationBean registration(MyFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
----
[[howto-add-a-servlet-filter-or-listener-using-scanning]]
==== Add Servlets, Filters, and Listeners using classpath scanning
`@WebServlet`, `@WebFilter`, and `@WebListener` annotated classes can be automatically
registered with an embedded servlet container by annotating a `@Configuration` class
with `@ServletComponentScan` and specifying the package(s) containing the components
that you want to register. By default, `@ServletComponentScan` will scan from the package
of the annotated class.
[[howto-change-the-http-port]]
=== Change the HTTP port
In a standalone application the main HTTP port defaults to `8080`, but can be set with
`server.port` (e.g. in `application.properties` or as a System property). Thanks to
relaxed binding of `Environment` values you can also use `SERVER_PORT` (e.g. as an OS
environment variable).
To switch off the HTTP endpoints completely, but still create a `WebApplicationContext`,
use `server.port=-1` (this is sometimes useful for testing).
For more details look at _<<spring-boot-features.adoc#boot-features-customizing-embedded-containers>>_
in the '`Spring Boot features`' section, or the
{sc-spring-boot-autoconfigure}/web/ServerProperties.{sc-ext}[`ServerProperties`] source
code.
[[howto-user-a-random-unassigned-http-port]]
=== Use a random unassigned HTTP port
To scan for a free port (using OS natives to prevent clashes) use `server.port=0`.
[[howto-discover-the-http-port-at-runtime]]
=== Discover the HTTP port at runtime
You can access the port the server is running on from log output or from the
`EmbeddedWebApplicationContext` via its `EmbeddedServletContainer`. The best way to get
that and be sure that it has initialized is to add a `@Bean` of type
`ApplicationListener<EmbeddedServletContainerInitializedEvent>` and pull the container
out of the event when it is published.
Tests that use `@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)` can
also inject the actual port into a field using the `@LocalServerPort` annotation. For
example:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MyWebIntegrationTests {
@Autowired
EmbeddedWebApplicationContext server;
@LocalServerPort
int port;
// ...
}
----
[NOTE]
====
`@LocalServerPort` is a meta-annotation for `@Value("${local.server.port}")`. Don't try
to inject the port in a regular application. As we just saw, the value is only set once
the container has initialized; contrary to a test, application code callbacks are
processed early (i.e. before the value is actually available).
====
[[howto-configure-ssl]]
=== Configure SSL
SSL can be configured declaratively by setting the various `+server.ssl.*+` properties,
typically in `application.properties` or `application.yml`. For example:
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret
----
See {sc-spring-boot}/context/embedded/Ssl.{sc-ext}[`Ssl`] for details of all of the
supported properties.
Using configuration like the example above means the application will no longer support
plain HTTP connector at port 8080. Spring Boot doesn't support the configuration of both
an HTTP connector and an HTTPS connector via `application.properties`. If you want to
have both then you'll need to configure one of them programmatically. It's recommended
to use `application.properties` to configure HTTPS as the HTTP connector is the easier of
the two to configure programmatically. See the
{github-code}/spring-boot-samples/spring-boot-sample-tomcat-multi-connectors[`spring-boot-sample-tomcat-multi-connectors`]
sample project for an example.
[[howto-configure-accesslogs]]
=== Configure Access Logging
Access logs can be configured for Tomcat and Undertow via their respective namespaces.
For instance, the following logs access on Tomcat with a
https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Access_Logging[custom pattern].
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
server.tomcat.basedir=my-tomcat
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
----
NOTE: The default location for logs is a `logs` directory relative to the tomcat base dir
and said directory is a temp directory by default so you may want to fix Tomcat's base
directory or use an absolute path for the logs. In the example above, the logs will
be available in `my-tomcat/logs` relative to the working directory of the application.
Access logging for undertow can be configured in a similar fashion
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
server.undertow.accesslog.enabled=true
server.undertow.accesslog.pattern=%t %a "%r" %s (%D ms)
----
Logs are stored in a `logs` directory relative to the working directory of the
application. This can be customized via `server.undertow.accesslog.directory`.
[[howto-use-behind-a-proxy-server]]
[[howto-use-tomcat-behind-a-proxy-server]]
=== Use behind a front-end proxy server
Your application might need to send `302` redirects or render content with absolute links
back to itself. When running behind a proxy, the caller wants a link to the proxy, and not
to the physical address of the machine hosting your app. Typically such situations are
handled via a contract with the proxy, which will add headers to tell the back end how to
construct links to itself.
If the proxy adds conventional `X-Forwarded-For` and `X-Forwarded-Proto` headers (most do
this out of the box) the absolute links should be rendered correctly as long as
`server.use-forward-headers` is set to `true` in your `application.properties`.
NOTE: If your application is running in Cloud Foundry or Heroku the
`server.use-forward-headers` property will default to `true` if not specified. In all
other instances it defaults to `false`.
[[howto-customize-tomcat-behind-a-proxy-server]]
==== Customize Tomcat's proxy configuration
If you are using Tomcat you can additionally configure the names of the headers used to
carry "`forwarded`" information:
[indent=0]
----
server.tomcat.remote-ip-header=x-your-remote-ip-header
server.tomcat.protocol-header=x-your-protocol-header
----
Tomcat is also configured with a default regular expression that matches internal
proxies that are to be trusted. By default, IP addresses in `10/8`, `192.168/16`,
`169.254/16` and `127/8` are trusted. You can customize the valve's configuration by
adding an entry to `application.properties`, e.g.
[indent=0]
----
server.tomcat.internal-proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}
----
NOTE: The double backslashes are only required when you're using a properties file for
configuration. If you are using YAML, single backslashes are sufficient and a value
that's equivalent to the one shown above would be `192\.168\.\d{1,3}\.\d{1,3}`.
NOTE: You can trust all proxies by setting the `internal-proxies` to empty (but don't do
this in production).
You can take complete control of the configuration of Tomcat's `RemoteIpValve` by
switching the automatic one off (i.e. set `server.use-forward-headers=false`) and adding
a new valve instance in a `TomcatEmbeddedServletContainerFactory` bean.
[[howto-configure-tomcat]]
=== Configure Tomcat
Generally you can follow the advice from
_<<howto-discover-build-in-options-for-external-properties>>_ about
`@ConfigurationProperties` (`ServerProperties` is the main one here), but also look at
`EmbeddedServletContainerCustomizer` and various Tomcat-specific `+*Customizers+` that you
can add in one of those. The Tomcat APIs are quite rich so once you have access to the
`TomcatEmbeddedServletContainerFactory` you can modify it in a number of ways. Or the
nuclear option is to add your own `TomcatEmbeddedServletContainerFactory`.
[[howto-enable-multiple-connectors-in-tomcat]]
=== Enable Multiple Connectors with Tomcat
Add a `org.apache.catalina.connector.Connector` to the
`TomcatEmbeddedServletContainerFactory` which can allow multiple connectors, e.g. HTTP and
HTTPS connector:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addAdditionalTomcatConnectors(createSslConnector());
return tomcat;
}
private Connector createSslConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
try {
File keystore = new ClassPathResource("keystore").getFile();
File truststore = new ClassPathResource("keystore").getFile();
connector.setScheme("https");
connector.setSecure(true);
connector.setPort(8443);
protocol.setSSLEnabled(true);
protocol.setKeystoreFile(keystore.getAbsolutePath());
protocol.setKeystorePass("changeit");
protocol.setTruststoreFile(truststore.getAbsolutePath());
protocol.setTruststorePass("changeit");
protocol.setKeyAlias("apitester");
return connector;
}
catch (IOException ex) {
throw new IllegalStateException("can't access keystore: [" + "keystore"
+ "] or truststore: [" + "keystore" + "]", ex);
}
}
----
[[howto-use-tomcat-legacycookieprocessor]]
=== Use Tomcat's LegacyCookieProcessor
The embedded Tomcat used by Spring Boot does not support "Version 0" of the Cookie
format out of the box, and you may see the following error:
[indent=0]
----
java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value
----
If at all possible, you should consider updating your code to only store values
compliant with later Cookie specifications. If, however, you're unable to change the
way that cookies are written, you can instead configure Tomcat to use a
`LegacyCookieProcessor`. To switch to the `LegacyCookieProcessor` use an
`EmbeddedServletContainerCustomizer` bean that adds a `TomcatContextCustomizer`:
[source,java,indent=0]
----
include::{code-examples}/context/embedded/TomcatLegacyCookieProcessorExample.java[tag=customizer]
----
[[howto-use-jetty-instead-of-tomcat]]
=== Use Jetty instead of Tomcat
The Spring Boot starters (`spring-boot-starter-web` in particular) use Tomcat as an
embedded container by default. You need to exclude those dependencies and include the
Jetty one instead. Spring Boot provides Tomcat and Jetty dependencies bundled together
as separate starters to help make this process as easy as possible.
Example in Maven:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
----
Example in Gradle:
[source,groovy,indent=0,subs="verbatim,quotes,attributes"]
----
configurations {
compile.exclude module: "spring-boot-starter-tomcat"
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:{spring-boot-version}")
compile("org.springframework.boot:spring-boot-starter-jetty:{spring-boot-version}")
// ...
}
----
[[howto-configure-jetty]]
=== Configure Jetty
Generally you can follow the advice from
_<<howto-discover-build-in-options-for-external-properties>>_ about
`@ConfigurationProperties` (`ServerProperties` is the main one here), but also look at
`EmbeddedServletContainerCustomizer`. The Jetty APIs are quite rich so once you have
access to the `JettyEmbeddedServletContainerFactory` you can modify it in a number
of ways. Or the nuclear option is to add your own `JettyEmbeddedServletContainerFactory`.
[[howto-use-undertow-instead-of-tomcat]]
=== Use Undertow instead of Tomcat
Using Undertow instead of Tomcat is very similar to <<howto-use-jetty-instead-of-tomcat,
using Jetty instead of Tomcat>>. You need to exclude the Tomcat dependencies and include
the Undertow starter instead.
Example in Maven:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
----
Example in Gradle:
[source,groovy,indent=0,subs="verbatim,quotes,attributes"]
----
configurations {
compile.exclude module: "spring-boot-starter-tomcat"
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:{spring-boot-version}")
compile("org.springframework.boot:spring-boot-starter-undertow:{spring-boot-version}")
// ...
}
----
[[howto-configure-undertow]]
=== Configure Undertow
Generally you can follow the advice from
_<<howto-discover-build-in-options-for-external-properties>>_ about
`@ConfigurationProperties` (`ServerProperties` and `ServerProperties.Undertow` are the
main ones here), but also look at
`EmbeddedServletContainerCustomizer`. Once you have access to the
`UndertowEmbeddedServletContainerFactory` you can use an `UndertowBuilderCustomizer` to
modify Undertow's configuration to meet your needs. Or the nuclear option is to add your
own `UndertowEmbeddedServletContainerFactory`.
[[howto-enable-multiple-listeners-in-undertow]]
=== Enable Multiple Listeners with Undertow
Add an `UndertowBuilderCustomizer` to the `UndertowEmbeddedServletContainerFactory` and
add a listener to the `Builder`:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
@Override
public void customize(Builder builder) {
builder.addHttpListener(8080, "0.0.0.0");
}
});
return factory;
}
----
[[howto-use-tomcat-7]]
=== Use Tomcat 7.x or 8.0
Tomcat 7 & 8.0 work with Spring Boot, but the default is to use Tomcat 8.5. If you cannot
use Tomcat 8.5 (for example, because you are using Java 1.6) you will need to change your
classpath to reference a different version.
[[howto-use-tomcat-7-maven]]
==== Use Tomcat 7.x or 8.0 with Maven
If you are using the starters and parent you can change the Tomcat version property
and additionally import `tomcat-juli`. E.g. for a simple webapp or service:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<properties>
<tomcat.version>7.0.59</tomcat.version>
</properties>
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-juli</artifactId>
<version>${tomcat.version}</version>
</dependency>
...
</dependencies>
----
==== Use Tomcat 7.x or 8.0 with Gradle
[[howto-use-tomcat-7-gradle]]
With Gradle, you can change the Tomcat version by setting the `tomcat.version` property
and then additionally include `tomcat-juli`:
[source,groovy,indent=0,subs="verbatim,quotes,attributes"]
----
ext['tomcat.version'] = '7.0.59'
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
compile group:'org.apache.tomcat', name:'tomcat-juli', version:property('tomcat.version')
}
----
[[howto-use-jetty-9.2]]
=== Use Jetty 9.2
Jetty 9.2 works with Spring Boot, but the default is to use Jetty 9.3. If you cannot use
Jetty 9.3 (for example, because you are using Java 7) you will need to change your
classpath to reference Jetty 9.2.
[[howto-use-jetty-9.2-maven]]
==== Use Jetty 9.2 with Maven
If you are using the starters and parent you can just add the Jetty starter and override
the `jetty.version` property:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<properties>
<jetty.version>9.2.17.v20160517</jetty.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
----
[[howto-use-jetty-9.2-gradle]]
==== Use Jetty 9.2 with Gradle
You can set the `jetty.version` property. For example, for a simple webapp or service:
[source,groovy,indent=0,subs="verbatim,quotes,attributes"]
----
ext['jetty.version'] = '9.2.17.v20160517'
dependencies {
compile ('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
compile ('org.springframework.boot:spring-boot-starter-jetty')
}
----
[[howto-use-jetty-8]]
=== Use Jetty 8
Jetty 8 works with Spring Boot, but the default is to use Jetty 9.3. If you cannot use
Jetty 9.3 (for example, because you are using Java 1.6) you will need to change your
classpath to reference Jetty 8. You will also need to exclude Jetty's WebSocket-related
dependencies.
[[howto-use-jetty-8-maven]]
==== Use Jetty 8 with Maven
If you are using the starters and parent you can just add the Jetty starter with
the required WebSocket exclusion and change the version properties, e.g. for a simple
webapp or service:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<properties>
<jetty.version>8.1.15.v20140411</jetty.version>
<jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
----
[[howto-use-jetty-8-gradle]]
==== Use Jetty 8 with Gradle
You can set the `jetty.version` property and exclude the WebSocket dependency, e.g. for a
simple webapp or service:
[source,groovy,indent=0,subs="verbatim,quotes,attributes"]
----
ext['jetty.version'] = '8.1.15.v20140411'
dependencies {
compile ('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
compile ('org.springframework.boot:spring-boot-starter-jetty') {
exclude group: 'org.eclipse.jetty.websocket'
}
}
----
[[howto-create-websocket-endpoints-using-serverendpoint]]
=== Create WebSocket endpoints using @ServerEndpoint
If you want to use `@ServerEndpoint` in a Spring Boot application that used an embedded
container, you must declare a single `ServerEndpointExporter` `@Bean`:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
----
This bean will register any `@ServerEndpoint` annotated beans with the underlying
WebSocket container. When deployed to a standalone servlet container this role is
performed by a servlet container initializer and the `ServerEndpointExporter` bean is
not required.
[[how-to-enable-http-response-compression]]
=== Enable HTTP response compression
HTTP response compression is supported by Jetty, Tomcat, and Undertow. It can be enabled
via `application.properties`:
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
server.compression.enabled=true
----
By default, responses must be at least 2048 bytes in length for compression to be
performed. This can be configured using the `server.compression.min-response-size`
property.
By default, responses will only be compressed if their content type is one of the
following:
- `text/html`
- `text/xml`
- `text/plain`
- `text/css`
This can be configured using the `server.compression.mime-types` property.
[[howto-spring-mvc]]
== Spring MVC
[[howto-write-a-json-rest-service]]
=== Write a JSON REST service
Any Spring `@RestController` in a Spring Boot application should render JSON response by
default as long as Jackson2 is on the classpath. For example:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@RestController
public class MyController {
@RequestMapping("/thing")
public MyThing thing() {
return new MyThing();
}
}
----
As long as `MyThing` can be serialized by Jackson2 (e.g. a normal POJO or Groovy object)
then `http://localhost:8080/thing` will serve a JSON representation of it by default.
Sometimes in a browser you might see XML responses because browsers tend to send accept
headers that prefer XML.
[[howto-write-an-xml-rest-service]]
=== Write an XML REST service
If you have the Jackson XML extension (`jackson-dataformat-xml`) on the classpath, it will
be used to render XML responses and the very same example as we used for JSON would work.
To use it, add the following dependency to your project:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
----
You may also want to add a dependency on Woodstox. It's faster than the default StAX
implementation provided by the JDK and also adds pretty print support and improved
namespace handling:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
</dependency>
----
If Jackson's XML extension is not available, JAXB (provided by default in the JDK) will
be used, with the additional requirement to have `MyThing` annotated as
`@XmlRootElement`:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@XmlRootElement
public class MyThing {
private String name;
// .. getters and setters
}
----
To get the server to render XML instead of JSON you might have to send an
`Accept: text/xml` header (or use a browser).
[[howto-customize-the-jackson-objectmapper]]
=== Customize the Jackson ObjectMapper
Spring MVC (client and server side) uses `HttpMessageConverters` to negotiate content
conversion in an HTTP exchange. If Jackson is on the classpath you already get the
default converter(s) provided by `Jackson2ObjectMapperBuilder`, an instance of which
is auto-configured for you.
The `ObjectMapper` (or `XmlMapper` for Jackson XML converter) instance created by default
has the following customized properties:
* `MapperFeature.DEFAULT_VIEW_INCLUSION` is disabled
* `DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES` is disabled
Spring Boot has also some features to make it easier to customize this behavior.
You can configure the `ObjectMapper` and `XmlMapper` instances using the environment.
Jackson provides an extensive suite of simple on/off features that can be used to
configure various aspects of its processing. These features are described in six enums in
Jackson which map onto properties in the environment:
|===
|Jackson enum|Environment property
|`com.fasterxml.jackson.databind.DeserializationFeature`
|`spring.jackson.deserialization.<feature_name>=true\|false`
|`com.fasterxml.jackson.core.JsonGenerator.Feature`
|`spring.jackson.generator.<feature_name>=true\|false`
|`com.fasterxml.jackson.databind.MapperFeature`
|`spring.jackson.mapper.<feature_name>=true\|false`
|`com.fasterxml.jackson.core.JsonParser.Feature`
|`spring.jackson.parser.<feature_name>=true\|false`
|`com.fasterxml.jackson.databind.SerializationFeature`
|`spring.jackson.serialization.<feature_name>=true\|false`
|`com.fasterxml.jackson.annotation.JsonInclude.Include`
|`spring.jackson.serialization-inclusion=always\|non_null\|non_absent\|non_default\|non_empty`
|===
For example, to enable pretty print, set `spring.jackson.serialization.indent_output=true`.
Note that, thanks to the use of <<boot-features-external-config-relaxed-binding,
relaxed binding>>, the case of `indent_output` doesn't have to match the case of the
corresponding enum constant which is `INDENT_OUTPUT`.
This environment-based configuration is applied to the auto-configured
`Jackson2ObjectMapperBuilder` bean, and will apply to any mappers created
using the builder, including the auto-configured `ObjectMapper` bean.
The context's `Jackson2ObjectMapperBuilder` can be customized by one or more
`Jackson2ObjectMapperBuilderCustomizer` beans. Such customizer beans can be ordered and
Boot's own customizer has an order of 0, allowing additional customization to be applied
both before and after Boot's customization.
Any beans of type `com.fasterxml.jackson.databind.Module` will be automatically registered
with the auto-configured `Jackson2ObjectMapperBuilder` and applied to any `ObjectMapper`
instances that it creates. This provides a global mechanism for contributing custom
modules when you add new features to your application.
If you want to replace the default `ObjectMapper` completely, either define a `@Bean` of
that type and mark it as `@Primary`, or, if you prefer the builder-based
approach, define a `Jackson2ObjectMapperBuilder` `@Bean`. Note that in either case this
will disable all auto-configuration of the `ObjectMapper.
If you provide any `@Beans` of type `MappingJackson2HttpMessageConverter` then
they will replace the default value in the MVC configuration. Also, a convenience bean is
provided of type `HttpMessageConverters` (always available if you use the default MVC
configuration) which has some useful methods to access the default and user-enhanced
message converters.
See also the _<<howto-customize-the-responsebody-rendering>>_ section and the
{sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[`WebMvcAutoConfiguration`]
source code for more details.
[[howto-customize-the-responsebody-rendering]]
=== Customize the @ResponseBody rendering
Spring uses `HttpMessageConverters` to render `@ResponseBody` (or responses from
`@RestController`). You can contribute additional converters by simply adding beans of
that type in a Spring Boot context. If a bean you add is of a type that would have been
included by default anyway (like `MappingJackson2HttpMessageConverter` for JSON
conversions) then it will replace the default value. A convenience bean is provided of
type `HttpMessageConverters` (always available if you use the default MVC configuration)
which has some useful methods to access the default and user-enhanced message converters
(useful, for example if you want to manually inject them into a custom `RestTemplate`).
As in normal MVC usage, any `WebMvcConfigurerAdapter` beans that you provide can also
contribute converters by overriding the `configureMessageConverters` method, but unlike
with normal MVC, you can supply only additional converters that you need (because Spring
Boot uses the same mechanism to contribute its defaults). Finally, if you opt-out of the
Spring Boot default MVC configuration by providing your own `@EnableWebMvc` configuration,
then you can take control completely and do everything manually using
`getMessageConverters` from `WebMvcConfigurationSupport`.
See the {sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[`WebMvcAutoConfiguration`]
source code for more details.
[[howto-multipart-file-upload-configuration]]
=== Handling Multipart File Uploads
Spring Boot embraces the Servlet 3 `javax.servlet.http.Part` API to support uploading
files. By default Spring Boot configures Spring MVC with a maximum file of 1Mb per
file and a maximum of 10Mb of file data in a single request. You may override these
values, as well as the location to which intermediate data is stored (e.g., to the `/tmp`
directory) and the threshold past which data is flushed to disk by using the properties
exposed in the `MultipartProperties` class. If you want to specify that files be
unlimited, for example, set the `spring.http.multipart.max-file-size` property to `-1`.
The multipart support is helpful when you want to receive multipart encoded file data as
a `@RequestParam`-annotated parameter of type `MultipartFile` in a Spring MVC controller
handler method.
See the {sc-spring-boot-autoconfigure}/web/MultipartAutoConfiguration.{sc-ext}[`MultipartAutoConfiguration`]
source for more details.
[[howto-switch-off-the-spring-mvc-dispatcherservlet]]
=== Switch off the Spring MVC DispatcherServlet
Spring Boot wants to serve all content from the root of your application `/` down. If you
would rather map your own servlet to that URL you can do it, but of course you may lose
some of the other Boot MVC features. To add your own servlet and map it to the root
resource just declare a `@Bean` of type `Servlet` and give it the special bean name
`dispatcherServlet` (You can also create a bean of a different type with that name if
you want to switch it off and not replace it).
[[howto-switch-off-default-mvc-configuration]]
=== Switch off the Default MVC configuration
The easiest way to take complete control over MVC configuration is to provide your own
`@Configuration` with the `@EnableWebMvc` annotation. This will leave all MVC
configuration in your hands.
[[howto-customize-view-resolvers]]
=== Customize ViewResolvers
A `ViewResolver` is a core component of Spring MVC, translating view names in
`@Controller` to actual `View` implementations. Note that `ViewResolvers` are mainly
used in UI applications, rather than REST-style services (a `View` is not used to render
a `@ResponseBody`). There are many implementations of `ViewResolver` to choose from, and
Spring on its own is not opinionated about which ones you should use. Spring Boot, on the
other hand, installs one or two for you depending on what it finds on the classpath and
in the application context. The `DispatcherServlet` uses all the resolvers it finds in
the application context, trying each one in turn until it gets a result, so if you are
adding your own you have to be aware of the order and in which position your resolver is
added.
`WebMvcAutoConfiguration` adds the following `ViewResolvers` to your context:
* An `InternalResourceViewResolver` with bean id '`defaultViewResolver`'. This one locates
physical resources that can be rendered using the `DefaultServlet` (e.g. static
resources and JSP pages if you are using those). It applies a prefix and a suffix to the
view name and then looks for a physical resource with that path in the servlet context
(defaults are both empty, but accessible for external configuration via
`spring.mvc.view.prefix` and `spring.mvc.view.suffix`). It can be overridden by providing a
bean of the same type.
* A `BeanNameViewResolver` with id '`beanNameViewResolver`'. This is a useful member of the
view resolver chain and will pick up any beans with the same name as the `View` being
resolved. It shouldn't be necessary to override or replace it.
* A `ContentNegotiatingViewResolver` with id '`viewResolver`' is only added if there *are*
actually beans of type `View` present. This is a '`master`' resolver, delegating to all
the others and attempting to find a match to the '`Accept`' HTTP header sent by the
client. There is a useful
https://spring.io/blog/2013/06/03/content-negotiation-using-views[blog about `ContentNegotiatingViewResolver`]
that you might like to study to learn more, and also look at the source code for detail.
You can switch off the auto-configured
`ContentNegotiatingViewResolver` by defining a bean named '`viewResolver`'.
* If you use Thymeleaf you will also have a `ThymeleafViewResolver` with id
'`thymeleafViewResolver`'. It looks for resources by surrounding the view name with a
prefix and suffix (externalized to `spring.thymeleaf.prefix` and
`spring.thymeleaf.suffix`, defaults '`classpath:/templates/`' and '`.html`'
respectively). It can be overridden by providing a bean of the same name.
* If you use FreeMarker you will also have a `FreeMarkerViewResolver` with id
'`freeMarkerViewResolver`'. It looks for resources in a loader path (externalized to
`spring.freemarker.templateLoaderPath`, default '`classpath:/templates/`') by
surrounding the view name with a prefix and suffix (externalized to `spring.freemarker.prefix`
and `spring.freemarker.suffix`, with empty and '`.ftl`' defaults respectively). It can
be overridden by providing a bean of the same name.
* If you use Groovy templates (actually if groovy-templates is on your classpath) you will
also have a `GroovyMarkupViewResolver` with id '`groovyMarkupViewResolver`'. It
looks for resources in a loader path by surrounding the view name with a prefix and
suffix (externalized to `spring.groovy.template.prefix` and
`spring.groovy.template.suffix`, defaults '`classpath:/templates/`' and '`.tpl`'
respectively). It can be overridden by providing a bean of the same name.
* If you use Velocity you will also have a `VelocityViewResolver` with id '`velocityViewResolver`'.
It looks for resources in a loader path (externalized to `spring.velocity.resourceLoaderPath`,
default '`classpath:/templates/`') by surrounding the view name with a prefix and suffix
(externalized to `spring.velocity.prefix` and `spring.velocity.suffix`, with empty and '`.vm`'
defaults respectively). It can be overridden by providing a bean of the same name.
Check out {sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[`WebMvcAutoConfiguration`],
{sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[`ThymeleafAutoConfiguration`],
{sc-spring-boot-autoconfigure}/freemarker/FreeMarkerAutoConfiguration.{sc-ext}[`FreeMarkerAutoConfiguration`],
{sc-spring-boot-autoconfigure}/groovy/template/GroovyTemplateAutoConfiguration.{sc-ext}[`GroovyTemplateAutoConfiguration`] and
{sc-spring-boot-autoconfigure}/velocity/VelocityAutoConfiguration.{sc-ext}[`VelocityAutoConfiguration`]
[[howto-customize-view-resolvers-velocity]]
=== Velocity
By default, Spring Boot configures a `VelocityViewResolver`. If you need a
`VelocityLayoutViewResolver` instead, you can easily configure your own by creating a bean
with name `velocityViewResolver`. You can also inject the `VelocityProperties` instance to
apply the base defaults to your custom view resolver.
The following example replaces the auto-configured velocity view resolver with a
`VelocityLayoutViewResolver` defining a customized `layoutUrl` and all settings that would
have been applied from the auto-configuration:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Bean(name = "velocityViewResolver")
public VelocityLayoutViewResolver velocityViewResolver(VelocityProperties properties) {
VelocityLayoutViewResolver resolver = new VelocityLayoutViewResolver();
properties.applyToViewResolver(resolver);
resolver.setLayoutUrl("layout/default.vm");
return resolver;
}
----
[[howto-use-thymeleaf-3]]
=== Use Thymeleaf 3
By default, `spring-boot-starter-thymeleaf` uses Thymeleaf 2.1. If you are using the
`spring-boot-starter-parent`, you can use Thymeleaf 3 by overriding the
`thymeleaf.version` and `thymeleaf-layout-dialect.version` properties, for example:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<properties>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>
</properties>
----
NOTE: if you are managing dependencies yourself, look at `spring-boot-dependencies` for
the list of artifacts that are related to those two versions.
To avoid a warning message about the HTML 5 template mode being deprecated and the HTML
template mode being used instead, you may also want to explicitly configure
`spring.thymeleaf.mode` to be `HTML`, for example:
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
spring.thymeleaf.mode: HTML
----
Please refer to the
{github-code}/spring-boot-samples/spring-boot-sample-web-thymeleaf3[Thymeleaf 3 sample] to
see this in action.
If you are using any of the other auto-configured Thymeleaf Extras (Spring Security,
Data Attribute, or Java 8 Time) you should also override each of their versions to one
that is compatible with Thymeleaf 3.0.
[[howto-http-clients]]
== HTTP clients
[[howto-http-clients-proxy-configuration]]
=== Configure RestTemplate to use a proxy
As described in <<spring-boot-features.adoc#boot-features-restclient-customization>>,
a `RestTemplateCustomizer` can be used with `RestTemplateBuilder` to build a customized
`RestTemplate`. This is the recommended approach for creating a `RestTemplate` configured
to use a proxy.
The exact details of the proxy configuration depend on the underlying client request
factory that is being used. Here's an example of configuring
`HttpComponentsClientRequestFactory` with an `HttpClient` that uses a proxy for all hosts
except `192.168.0.5`.
[source,java,indent=0]
----
include::{code-examples}/web/client/RestTemplateProxyCustomizationExample.java[tag=customizer]
----
[[howto-logging]]
== Logging
Spring Boot has no mandatory logging dependency, except for the Commons Logging API, of
which there are many implementations to choose from. To use https://logback.qos.ch[Logback]
you need to include it and `jcl-over-slf4j` (which implements the Commons Logging API) on
the classpath. The simplest way to do that is through the starters which all depend on
`spring-boot-starter-logging`. For a web application you only need
`spring-boot-starter-web` since it depends transitively on the logging starter. For
example, using Maven:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
----
Spring Boot has a `LoggingSystem` abstraction that attempts to configure logging based on
the content of the classpath. If Logback is available it is the first choice.
If the only change you need to make to logging is to set the levels of various loggers
then you can do that in `application.properties` using the "logging.level" prefix, e.g.
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
----
You can also set the location of a file to log to (in addition to the console) using
"logging.file".
To configure the more fine-grained settings of a logging system you need to use the native
configuration format supported by the `LoggingSystem` in question. By default Spring Boot
picks up the native configuration from its default location for the system (e.g.
`classpath:logback.xml` for Logback), but you can set the location of the config file
using the "logging.config" property.
[[howto-configure-logback-for-logging]]
=== Configure Logback for logging
If you put a `logback.xml` in the root of your classpath it will be picked up from
there
(or `logback-spring.xml` to take advantage of the templating features provided by Boot).
Spring Boot provides a default base configuration that you can include if you just
want to set levels, e.g.
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.springframework.web" level="DEBUG"/>
</configuration>
----
If you look at that `base.xml` in the spring-boot jar, you will see that it uses
some useful System properties which the `LoggingSystem` takes care of creating for you.
These are:
* `${PID}` the current process ID.
* `${LOG_FILE}` if `logging.file` was set in Boot's external configuration.
* `${LOG_PATH}` if `logging.path` was set (representing a directory for
log files to live in).
* `${LOG_EXCEPTION_CONVERSION_WORD}` if `logging.exception-conversion-word` was set in
Boot's external configuration.
Spring Boot also provides some nice ANSI colour terminal output on a console (but not in
a log file) using a custom Logback converter. See the default `base.xml` configuration
for details.
If Groovy is on the classpath you should be able to configure Logback with
`logback.groovy` as well (it will be given preference if present).
[[howto-configure-logback-for-logging-fileonly]]
==== Configure logback for file only output
If you want to disable console logging and write output only to a file you need a custom
`logback-spring.xml` that imports `file-appender.xml` but not `console-appender.xml`:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</configuration>
----
You also need to add `logging.file` to your `application.properties`:
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
logging.file=myapplication.log
----
[[howto-configure-log4j-for-logging]]
=== Configure Log4j for logging
Spring Boot supports https://logging.apache.org/log4j/2.x[Log4j 2] for logging
configuration if it is on the classpath. If you are using the starters for
assembling dependencies that means you have to exclude Logback and then include log4j 2
instead. If you aren't using the starters then you need to provide `jcl-over-slf4j`
(at least) in addition to Log4j 2.
The simplest path is probably through the starters, even though it requires some
jiggling with excludes, .e.g. in Maven:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
----
NOTE: The use of the Log4j starters gathers together the dependencies for common logging
requirements (e.g. including having Tomcat use `java.util.logging` but configuring the
output using Log4j 2). See the Actuator Log4j 2 samples for more detail and to see it in
action.
[[howto-configure-log4j-for-logging-yaml-or-json-config]]
==== Use YAML or JSON to configure Log4j 2
In addition to its default XML configuration format, Log4j 2 also supports YAML and JSON
configuration files. To configure Log4j 2 to use an alternative configuration file format,
add the appropriate dependencies to the classpath and name your
configuration files to match your chosen file format:
[cols="10,75,15"]
|===
|Format|Dependencies|File names
|YAML
a| `com.fasterxml.jackson.core:jackson-databind` +
`com.fasterxml.jackson.dataformat:jackson-dataformat-yaml`
a| `log4j2.yaml` +
`log4j2.yml`
|JSON
a| `com.fasterxml.jackson.core:jackson-databind`
a| `log4j2.json` +
`log4j2.jsn`
|===
[[howto-data-access]]
== Data Access
[[howto-configure-a-datasource]]
=== Configure a custom DataSource
To configure your own `DataSource` define a `@Bean` of that type in your configuration.
Spring Boot will reuse your `DataSource` anywhere one is required, including database
initialization. If you need to externalize some settings, you can easily bind your
`DataSource` to the environment (see
<<spring-boot-features.adoc#boot-features-external-config-3rd-party-configuration>>).
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Bean
@ConfigurationProperties(prefix="app.datasource")
public DataSource dataSource() {
return new FancyDataSource();
}
----
[source,properties,indent=0]
----
app.datasource.url=jdbc:h2:mem:mydb
app.datasource.username=sa
app.datasource.pool-size=30
----
Assuming that your `FancyDataSource` has regular JavaBean properties for the url, the
username and the pool size, these settings will be bound automatically before the
`DataSource` is made available to other components. The regular
<<howto-initialize-a-database-using-spring-jdbc,database initialization>> will also happen
(so the relevant sub-set of `spring.datasource.*` can still be used with your custom
configuration).
You can apply the same principle if you are configuring a custom JNDI `DataSource`:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Bean(destroyMethod="")
@ConfigurationProperties(prefix="app.datasource")
public DataSource dataSource() throws Exception {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
return dataSourceLookup.getDataSource("java:comp/env/jdbc/YourDS");
}
----
Spring Boot also provides a utility builder class `DataSourceBuilder` that can be used to
create one of the standard data sources (if it is on the classpath). The builder can
detect the one to use based on what's available on the classpath. It also auto detects the
driver based on the JDBC url.
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
include::{code-examples}/jdbc/BasicDataSourceExample.java[tag=configuration]
----
To run an app with that `DataSource`, all that is needed really is the connection
information; pool-specific settings can also be provided, check the implementation that
is going to be used at runtime for more details.
[source,properties,indent=0]
----
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
----
There is a catch however. Because the actual type of the connection pool is not exposed,
no keys are generated in the metadata for your custom `DataSource` and no completion is
available in your IDE (The `DataSource` interface doesn't expose any property). Also, if
you happen to _only_ have Hikari on the classpath, this basic setup will not work because
Hikari has no `url` parameter (but a `jdbcUrl` parameter). You will have to rewrite
your configuration as follows:
[source,properties,indent=0]
----
app.datasource.jdbc-url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.maximum-pool-size=30
----
You can fix that by forcing the connection pool to use and return a dedicated
implementation rather than `DataSource`. You won't be able to change the implementation
at runtime but the list of options will be explicit.
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
include::{code-examples}/jdbc/SimpleDataSourceExample.java[tag=configuration]
----
You can even go further by leveraging what `DataSourceProperties` does for you, that is
providing a default embedded database if no url is provided with a sensible username and
password for it. You can easily initialize a `DataSourceBuilder` from the state of any
`DataSourceProperties` so you could just as well inject the one Spring Boot creates
automatically. However, that would split your configuration in two namespaces: url,
username, password, type and driver on `spring.datasource` and the rest on your custom
namespace (`app.datasource`). To avoid that, you can redefine a custom
`DataSourceProperties` on your custom namespace:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
include::{code-examples}/jdbc/ConfigurableDataSourceExample.java[tag=configuration]
----
This setup puts you _in pair_ with what Spring Boot does for you by default, except that
a dedicated connection pool is chosen (in code) and its settings are exposed in the same
namespace. Because `DataSourceProperties` is taking care of the `url`/`jdbcUrl`
translation for you, you can configure it like this:
[source,properties,indent=0]
----
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.maximum-pool-size=30
----
NOTE: Because your custom configuration chooses to go with Hikari, `app.datasource.type`
will have no effect. In practice the builder will be initialized with whatever value you
might set there and then overridden by the call to `.type()``.
See _<<spring-boot-features.adoc#boot-features-configure-datasource>>_ in the
'`Spring Boot features`' section and the
{sc-spring-boot-autoconfigure}/jdbc/DataSourceAutoConfiguration.{sc-ext}[`DataSourceAutoConfiguration`]
class for more details.
[[howto-two-datasources]]
=== Configure Two DataSources
If you need to configure multiple data sources, you can apply the same tricks that are
described in the previous section. You must, however, mark one of the `DataSource`
`@Primary` as various auto-configurations down the road expect to be able to get one by
type.
If you create your own `DataSource`, the auto-configuration will back off. In the example
below, we provide the _exact_ same features set than what the auto-configuration provides
on the primary data source:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
include::{code-examples}/jdbc/SimpleTwoDataSourcesExample.java[tag=configuration]
----
TIP: `fooDataSourceProperties` has to be flagged `@Primary` so that the database
initializer feature uses your copy (should you use that).
Both data sources are also bound for advanced customizations. For instance you could
configure them as follows:
[source,properties,indent=0]
----
app.datasource.foo.type=com.zaxxer.hikari.HikariDataSource
app.datasource.foo.maximum-pool-size=30
app.datasource.bar.url=jdbc:mysql://localhost/test
app.datasource.bar.username=dbuser
app.datasource.bar.password=dbpass
app.datasource.bar.max-total=30
----
Of course, you can apply the same concept to the secondary `DataSource` as well:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
include::{code-examples}/jdbc/CompleteTwoDataSourcesExample.java[tag=configuration]
----
This final example configures two data sources on custom namespaces with the same logic
than what Spring Boot would do in auto-configuration.
[[howto-use-spring-data-repositories]]
=== Use Spring Data repositories
Spring Data can create implementations for you of `@Repository` interfaces of various
flavors. Spring Boot will handle all of that for you as long as those `@Repositories`
are included in the same package (or a sub-package) of your `@EnableAutoConfiguration`
class.
For many applications all you will need is to put the right Spring Data dependencies on
your classpath (there is a `spring-boot-starter-data-jpa` for JPA and a
`spring-boot-starter-data-mongodb` for Mongodb), create some repository interfaces to handle your
`@Entity` objects. Examples are in the {github-code}/spring-boot-samples/spring-boot-sample-data-jpa[JPA sample]
or the {github-code}/spring-boot-samples/spring-boot-sample-data-mongodb[Mongodb sample].
Spring Boot tries to guess the location of your `@Repository` definitions, based on the
`@EnableAutoConfiguration` it finds. To get more control, use the `@EnableJpaRepositories`
annotation (from Spring Data JPA).
[[howto-separate-entity-definitions-from-spring-configuration]]
=== Separate @Entity definitions from Spring configuration
Spring Boot tries to guess the location of your `@Entity` definitions, based on the
`@EnableAutoConfiguration` it finds. To get more control, you can use the `@EntityScan`
annotation, e.g.
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Configuration
@EnableAutoConfiguration
@EntityScan(basePackageClasses=City.class)
public class Application {
//...
}
----
[[howto-configure-jpa-properties]]
=== Configure JPA properties
Spring Data JPA already provides some vendor-independent configuration options (e.g.
for SQL logging) and Spring Boot exposes those, and a few more for hibernate as external
configuration properties. The most common options to set are:
[indent=0,subs="verbatim,quotes,attributes"]
----
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.hibernate.naming.physical-strategy=com.example.MyPhysicalNamingStrategy
spring.jpa.database=H2
spring.jpa.show-sql=true
----
The `ddl-auto` setting is a special case in that it has different defaults depending on
whether you are using an embedded database (`create-drop`) or not (`none`). In addition
all properties in `+spring.jpa.properties.*+` are passed through as normal JPA properties
(with the prefix stripped) when the local `EntityManagerFactory` is created.
Spring Boot provides a consistent naming strategy regardless of the Hibernate generation
that you are using. If you are using Hibernate 4, you can customize it using
`spring.jpa.hibernate.naming.strategy`; Hibernate 5 defines a `Physical` and `Implicit`
naming strategies: Spring Boot configures `SpringPhysicalNamingStrategy` by default. This
implementation provides the same table structure as Hibernate 4. If you'd rather use
Hibernate 5's default instead, set the following property:
[indent=0,subs="verbatim,quotes,attributes"]
----
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
----
See {sc-spring-boot-autoconfigure}/orm/jpa/HibernateJpaAutoConfiguration.{sc-ext}[`HibernateJpaAutoConfiguration`]
and {sc-spring-boot-autoconfigure}/orm/jpa/JpaBaseConfiguration.{sc-ext}[`JpaBaseConfiguration`]
for more details.
[[howto-use-custom-entity-manager]]
=== Use a custom EntityManagerFactory
To take full control of the configuration of the `EntityManagerFactory`, you need to add
a `@Bean` named '`entityManagerFactory`'. Spring Boot auto-configuration switches off its
entity manager based on the presence of a bean of that type.
[[howto-use-two-entity-managers]]
=== Use Two EntityManagers
Even if the default `EntityManagerFactory` works fine, you will need to define a new one
because otherwise the presence of the second bean of that type will switch off the
default. To make it easy to do that you can use the convenient `EntityManagerBuilder`
provided by Spring Boot, or if you prefer you can just use the
`LocalContainerEntityManagerFactoryBean` directly from Spring ORM.
Example:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
// add two data sources configured as above
@Bean
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(customerDataSource())
.packages(Customer.class)
.persistenceUnit("customers")
.build();
}
@Bean
public LocalContainerEntityManagerFactoryBean orderEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(orderDataSource())
.packages(Order.class)
.persistenceUnit("orders")
.build();
}
----
The configuration above almost works on its own. To complete the picture you need to
configure `TransactionManagers` for the two `EntityManagers` as well. One of them could
be picked up by the default `JpaTransactionManager` in Spring Boot if you mark it as
`@Primary`. The other would have to be explicitly injected into a new instance. Or you
might be able to use a JTA transaction manager spanning both.
If you are using Spring Data, you need to configure `@EnableJpaRepositories` accordingly:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Configuration
@EnableJpaRepositories(basePackageClasses = Customer.class,
entityManagerFactoryRef = "customerEntityManagerFactory")
public class CustomerConfiguration {
...
}
@Configuration
@EnableJpaRepositories(basePackageClasses = Order.class,
entityManagerFactoryRef = "orderEntityManagerFactory")
public class OrderConfiguration {
...
}
----
[[howto-use-traditional-persistence-xml]]
=== Use a traditional persistence.xml
Spring doesn't require the use of XML to configure the JPA provider, and Spring Boot
assumes you want to take advantage of that feature. If you prefer to use `persistence.xml`
then you need to define your own `@Bean` of type `LocalEntityManagerFactoryBean` (with
id '`entityManagerFactory`', and set the persistence unit name there.
See
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java[`JpaBaseConfiguration`]
for the default settings.
[[howto-use-spring-data-jpa--and-mongo-repositories]]
=== Use Spring Data JPA and Mongo repositories
Spring Data JPA and Spring Data Mongo can both create `Repository` implementations for you
automatically. If they are both present on the classpath, you might have to do some extra
configuration to tell Spring Boot which one (or both) you want to create repositories for
you. The most explicit way to do that is to use the standard Spring Data
`+@Enable*Repositories+` and tell it the location of your `Repository` interfaces
(where '`*`' is '`Jpa`' or '`Mongo`' or both).
There are also flags `+spring.data.*.repositories.enabled+` that you can use to switch the
auto-configured repositories on and off in external configuration. This is useful for
instance in case you want to switch off the Mongo repositories and still use the
auto-configured `MongoTemplate`.
The same obstacle and the same features exist for other auto-configured Spring Data
repository types (Elasticsearch, Solr). Just change the names of the annotations and flags
respectively.
[[howto-use-exposing-spring-data-repositories-rest-endpoint]]
=== Expose Spring Data repositories as REST endpoint
Spring Data REST can expose the `Repository` implementations as REST endpoints for you as
long as Spring MVC has been enabled for the application.
Spring Boot exposes as set of useful properties from the `spring.data.rest` namespace that
customize the
{spring-data-rest-javadoc}/core/config/RepositoryRestConfiguration.{dc-ext}[`RepositoryRestConfiguration`].
If you need to provide additional customization, you should use a
{spring-data-rest-javadoc}/webmvc/config/RepositoryRestConfigurer.{dc-ext}[`RepositoryRestConfigurer`]
bean.
[[howto-configure-a-component-that-is-used-by-JPA]]
=== Configure a component that is used by JPA
If you want to configure a component that will be used by JPA then you need to ensure
that the component is initialized before JPA. Where the component is auto-configured
Spring Boot will take care of this for you. For example, when Flyway is auto-configured,
Hibernate is configured to depend upon Flyway so that the latter has a chance to
initialize the database before Hibernate tries to use it.
If you are configuring a component yourself, you can use an
`EntityManagerFactoryDependsOnPostProcessor` subclass as a convenient way of setting up
the necessary dependencies. For example, if you are using Hibernate Search with
Elasticsearch as its index manager then any `EntityManagerFactory` beans must be
configured to depend on the `elasticsearchClient` bean:
[source,java,indent=0]
----
include::{code-examples}/elasticsearch/HibernateSearchElasticsearchExample.java[tag=configuration]
----
[[howto-database-initialization]]
== Database initialization
An SQL database can be initialized in different ways depending on what your stack is. Or
of course you can do it manually as long as the database is a separate process.
[[howto-initialize-a-database-using-jpa]]
=== Initialize a database using JPA
JPA has features for DDL generation, and these can be set up to run on startup against the
database. This is controlled through two external properties:
* `spring.jpa.generate-ddl` (boolean) switches the feature on and off and is vendor
independent.
* `spring.jpa.hibernate.ddl-auto` (enum) is a Hibernate feature that controls the
behavior in a more fine-grained way. See below for more detail.
[[howto-initialize-a-database-using-hibernate]]
=== Initialize a database using Hibernate
You can set `spring.jpa.hibernate.ddl-auto` explicitly and the standard Hibernate property
values are `none`, `validate`, `update`, `create`, `create-drop`. Spring Boot chooses a
default value for you based on whether it thinks your database is embedded (default
`create-drop`) or not (default `none`). An embedded database is detected by looking at the
`Connection` type: `hsqldb`, `h2` and `derby` are embedded, the rest are not. Be careful
when switching from in-memory to a '`real`' database that you don't make assumptions about
the existence of the tables and data in the new platform. You either have to set `ddl-auto`
explicitly, or use one of the other mechanisms to initialize the database.
NOTE: You can output the schema creation by enabling the `org.hibernate.SQL` logger. This
is done for you automatically if you enable the <<boot-features-logging-console-output,debug mode>>.
In addition, a file named `import.sql` in the root of the classpath will be executed on
startup if Hibernate creates the schema from scratch (that is if the `ddl-auto` property
is set to `create` or `create-drop`). This can be useful for demos and for testing if you
are careful, but probably not something you want to be on the classpath in production. It
is a Hibernate feature (nothing to do with Spring).
[[howto-initialize-a-database-using-spring-jdbc]]
=== Initialize a database using Spring JDBC
Spring JDBC has a `DataSource` initializer feature. Spring Boot enables it by default and
loads SQL from the standard locations `schema.sql` and `data.sql` (in the root of the
classpath). In addition Spring Boot will load the `schema-${platform}.sql`
and `data-${platform}.sql` files (if present), where
`platform` is the value of `spring.datasource.platform`, e.g. you might choose to set
it to the vendor name of the database (`hsqldb`, `h2`, `oracle`, `mysql`,
`postgresql` etc.). Spring Boot enables the fail-fast feature of the Spring JDBC
initializer by default, so if the scripts cause exceptions the application will fail
to start. The script locations can be changed by setting `spring.datasource.schema` and
`spring.datasource.data`, and neither location will be processed if
`spring.datasource.initialize=false`.
To disable the fail-fast you can set `spring.datasource.continue-on-error=true`. This can be
useful once an application has matured and been deployed a few times, since the scripts
can act as '`poor man's migrations`' -- inserts that fail mean that the data is already
there, so there would be no need to prevent the application from running, for instance.
If you want to use the `schema.sql` initialization in a JPA app (with
Hibernate) then `ddl-auto=create-drop` will lead to errors if
Hibernate tries to create the same tables. To avoid those errors set
`ddl-auto` explicitly to "" (preferable) or "none". Whether or not you use
`ddl-auto=create-drop` you can always use `data.sql` to initialize new
data.
[[howto-initialize-a-spring-batch-database]]
=== Initialize a Spring Batch database
If you are using Spring Batch then it comes pre-packaged with SQL initialization scripts
for most popular database platforms. Spring Boot will detect your database type, and
execute those scripts by default, and in this case will switch the fail fast setting to
false (errors are logged but do not prevent the application from starting). This is
because the scripts are known to be reliable and generally do not contain bugs, so errors
are ignorable, and ignoring them makes the scripts idempotent. You can switch off the
initialization explicitly using `spring.batch.initializer.enabled=false`.
[[howto-use-a-higher-level-database-migration-tool]]
=== Use a higher-level database migration tool
Spring Boot supports two higher-level migration tools: https://flywaydb.org/[Flyway]
and https://www.liquibase.org/[Liquibase].
[[howto-execute-flyway-database-migrations-on-startup]]
==== Execute Flyway database migrations on startup
To automatically run Flyway database migrations on startup, add the
`org.flywaydb:flyway-core` to your classpath.
The migrations are scripts in the form `V<VERSION>__<NAME>.sql` (with `<VERSION>` an
underscore-separated version, e.g. '`1`' or '`2_1`'). By default they live in a folder
`classpath:db/migration` but you can modify that using `flyway.locations` (a list). See
the Flyway class from flyway-core for details of available settings like schemas etc. In
addition Spring Boot provides a small set of properties in
{sc-spring-boot-autoconfigure}/flyway/FlywayProperties.{sc-ext}[`FlywayProperties`]
that can be used to disable the migrations, or switch off the location checking. Spring
Boot will call `Flyway.migrate()` to perform the database migration. If you would like
more control, provide a `@Bean` that implements
{sc-spring-boot-autoconfigure}/flyway/FlywayMigrationStrategy.{sc-ext}[`FlywayMigrationStrategy`].
TIP: If you want to make use of https://flywaydb.org/documentation/callbacks.html[Flyway
callbacks], those scripts should also live in the `classpath:db/migration` folder.
By default Flyway will autowire the (`@Primary`) `DataSource` in your context and
use that for migrations. If you like to use a different `DataSource` you can create
one and mark its `@Bean` as `@FlywayDataSource` - if you do that remember to create
another one and mark it as `@Primary` if you want two data sources.
Or you can use Flyway's native `DataSource` by setting `flyway.[url,user,password]`
in external properties.
There is a {github-code}/spring-boot-samples/spring-boot-sample-flyway[Flyway sample] so
you can see how to set things up.
You can also use Flyway to provide data for specific scenarios. For example, you can
place test-specific migrations in `src/test/resources` and they will only be run when your
application starts for testing. If you want to be more sophisticated you can use
profile-specific configuration to customize `flyway.locations` so that certain migrations
will only run when a particular profile is active. For example, in
`application-dev.properties` you could set `flyway.locations` to
`classpath:/db/migration, claspath:/dev/db/migration` and migrations in `dev/db/migration`
will only run when the `dev` profile is active.
[[howto-execute-liquibase-database-migrations-on-startup]]
==== Execute Liquibase database migrations on startup
To automatically run Liquibase database migrations on startup, add the
`org.liquibase:liquibase-core` to your classpath.
The master change log is by default read from `db/changelog/db.changelog-master.yaml` but
can be set using `liquibase.change-log`. In addition to YAML, Liquibase also supports
JSON, XML, and SQL change log formats.
By default Liquibase will autowire the (`@Primary`) `DataSource` in your context and use
that for migrations. If you like to use a different `DataSource` you can create one and
mark its `@Bean` as `@LiquibaseDataSource` - if you do that remember to create another one
and mark it as `@Primary` if you want two data sources. Or you can use Liquibase's native
`DataSource` by setting `liquibase.[url,user,password]` in external properties.
See
{sc-spring-boot-autoconfigure}/liquibase/LiquibaseProperties.{sc-ext}[`LiquibaseProperties`]
for details of available settings like contexts, default schema etc.
There is a {github-code}/spring-boot-samples/spring-boot-sample-liquibase[Liquibase sample]
so you can see how to set things up.
[[howto-messaging]]
== Messaging
[[howto-jms-disable-transaction]]
=== Disable transacted JMS session
If your JMS broker does not support transacted session, you will have to disable the
support of transactions altogether. If you create your own `JmsListenerContainerFactory`
there is nothing to do since it won't be transacted by default. If you want to use
the `DefaultJmsListenerContainerFactoryConfigurer` to reuse Spring Boot's default, you
can disable transacted session as follows:
[source,java,indent=0]
----
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(
ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory listenerFactory =
new DefaultJmsListenerContainerFactory();
configurer.configure(listenerFactory, connectionFactory);
listenerFactory.setTransactionManager(null);
listenerFactory.setSessionTransacted(false);
return listenerFactory;
}
----
This overrides the default factory and this should be applied to any other factory that
your application defines, if any.
[[howto-batch-applications]]
== Batch applications
NOTE: By default, batch applications require a `DataSource` to store job details. If you
want to deviate from that, you'll need to implement `BatchConfigurer`, see
{spring-batch-javadoc}/core/configuration/annotation/EnableBatchProcessing.html[The
Javadoc of `@EnableBatchProcessing`] for more details.
[[howto-execute-spring-batch-jobs-on-startup]]
=== Execute Spring Batch jobs on startup
Spring Batch auto-configuration is enabled by adding `@EnableBatchProcessing`
(from Spring Batch) somewhere in your context.
By default it executes *all* `Jobs` in the application context on startup (see
{sc-spring-boot-autoconfigure}/batch/JobLauncherCommandLineRunner.{sc-ext}[JobLauncherCommandLineRunner]
for details). You can narrow down to a specific job or jobs by specifying
`spring.batch.job.names` (comma-separated job name patterns).
If the application context includes a `JobRegistry` then the jobs in
`spring.batch.job.names` are looked up in the registry instead of being autowired from the
context. This is a common pattern with more complex systems where multiple jobs are
defined in child contexts and registered centrally.
See
{sc-spring-boot-autoconfigure}/batch/BatchAutoConfiguration.{sc-ext}[BatchAutoConfiguration]
and
https://github.com/spring-projects/spring-batch/blob/master/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java[@EnableBatchProcessing]
for more details.
[[howto-actuator]]
== Actuator
[[howto-change-the-http-port-or-address-of-the-actuator-endpoints]]
=== Change the HTTP port or address of the actuator endpoints
In a standalone application the Actuator HTTP port defaults to the same as the main HTTP
port. To make the application listen on a different port set the external property
`management.port`. To listen on a completely different network address (e.g. if you have
an internal network for management and an external one for user applications) you can
also set `management.address` to a valid IP address that the server is able to bind to.
For more detail look at the
{sc-spring-boot-actuator}/autoconfigure/ManagementServerProperties.{sc-ext}[`ManagementServerProperties`]
source code and
_<<production-ready-features.adoc#production-ready-customizing-management-server-port>>_
in the '`Production-ready features`' section.
[[howto-customize-the-whitelabel-error-page]]
=== Customize the '`whitelabel`' error page
Spring Boot installs a '`whitelabel`' error page that you will see in browser client if
you encounter a server error (machine clients consuming JSON and other media types should
see a sensible response with the right error code).
NOTE: Set `server.error.whitelabel.enabled=false` to switch the default error page off
which will restore the default of the servlet container that you are using. Note that
Spring Boot will still attempt to resolve the error view so you'd probably add you own
error page rather than disabling it completely.
Overriding the error page with your own depends on the templating technology that you are
using. For example, if you are using Thymeleaf you would add an `error.html` template and
if you are using FreeMarker you would add an `error.ftl` template. In general what you
need is a `View` that resolves with a name of `error`, and/or a `@Controller` that handles
the `/error` path. Unless you replaced some of the default configuration you should find
a `BeanNameViewResolver` in your `ApplicationContext` so a `@Bean` with id `error` would
be a simple way of doing that. Look at
{sc-spring-boot-autoconfigure}/web/ErrorMvcAutoConfiguration.{sc-ext}[`ErrorMvcAutoConfiguration`] for more options.
See also the section on <<boot-features-error-handling, Error Handling>> for details of
how to register handlers in the servlet container.
[[howto-use-actuator-with-jersey]]
=== Actuator and Jersey
Actuator HTTP endpoints are only available for Spring MVC-based applications. If you want
to use Jersey and still use the actuator you will need to enable Spring MVC (by depending
on `spring-boot-starter-web`, for example). By default, both Jersey and the Spring MVC
dispatcher servlet are mapped to the same path (`/`). You will need to change the path for
one of them (by configuring `server.servlet-path` for Spring MVC or
`spring.jersey.application-path` for Jersey). For example, if you add
`server.servlet-path=/system` into `application.properties`, the actuator HTTP endpoints
will be available under `/system`.
[[howto-security]]
== Security
[[howto-switch-off-spring-boot-security-configuration]]
=== Switch off the Spring Boot security configuration
If you define a `@Configuration` with `@EnableWebSecurity` anywhere in your application
it will switch off the default webapp security settings in Spring Boot (but leave the
Actuator's security enabled). To tweak the defaults try setting properties in
`+security.*+` (see
{sc-spring-boot-autoconfigure}/security/SecurityProperties.{sc-ext}[`SecurityProperties`]
for details of available settings) and `SECURITY` section of
<<common-application-properties-security,Common application properties>>.
[[howto-change-the-authenticationmanager-and-add-user-accounts]]
=== Change the AuthenticationManager and add user accounts
If you provide a `@Bean` of type `AuthenticationManager` the default one will not be
created, so you have the full feature set of Spring Security available (e.g.
https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#jc-authentication[various authentication options]).
Spring Security also provides a convenient `AuthenticationManagerBuilder` which can be
used to build an `AuthenticationManager` with common options. The recommended way to
use this in a webapp is to inject it into a void method in a
`WebSecurityConfigurerAdapter`, e.g.
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("barry").password("password").roles("USER"); // ... etc.
}
// ... other stuff for application security
}
----
You will get the best results if you put this in a nested class, or a standalone class
(i.e. not mixed in with a lot of other `@Beans` that might be allowed to influence the
order of instantiation). The {github-code}/spring-boot-samples/spring-boot-sample-web-secure[secure web sample]
is a useful template to follow.
If you experience instantiation issues (e.g. using JDBC or JPA for the user detail store)
it might be worth extracting the `AuthenticationManagerBuilder` callback into a
`GlobalAuthenticationConfigurerAdapter` (in the `init()` method so it happens before the
authentication manager is needed elsewhere), e.g.
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Configuration
public class AuthenticationManagerConfiguration extends
GlobalAuthenticationConfigurerAdapter {
@Override
public void init(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication() // ... etc.
}
}
----
[[howto-enable-https]]
=== Enable HTTPS when running behind a proxy server
Ensuring that all your main endpoints are only available over HTTPS is an important
chore for any application. If you are using Tomcat as a servlet container, then
Spring Boot will add Tomcat's own `RemoteIpValve` automatically if it detects some
environment settings, and you should be able to rely on the `HttpServletRequest` to
report whether it is secure or not (even downstream of a proxy server that handles the
real SSL termination). The standard behavior is determined by the presence or absence of
certain request headers (`x-forwarded-for` and `x-forwarded-proto`), whose names are
conventional, so it should work with most front end proxies. You can switch on the valve
by adding some entries to `application.properties`, e.g.
[source,properties,indent=0]
----
server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto
----
(The presence of either of those properties will switch on the valve. Or you can add the
`RemoteIpValve` yourself by adding a `TomcatEmbeddedServletContainerFactory` bean.)
Spring Security can also be configured to require a secure channel for all (or some
requests). To switch that on in a Spring Boot application you just need to set
`security.require_ssl` to `true` in `application.properties`.
[[howto-hotswapping]]
== Hot swapping
[[howto-reload-static-content]]
=== Reload static content
There are several options for hot reloading. The recommended approach is to use
<<using-spring-boot.adoc#using-boot-devtools,`spring-boot-devtools`>> as it provides
additional development-time features such as support for fast application restarts
and LiveReload as well as sensible development-time configuration (e.g. template caching).
Devtools works by monitoring the classpath for changes. This means that static resource
changes must be "built" for the change to take affect. By default, this happens
automatically in Eclipse when you save your changes. In IntelliJ IDEA, Make Project will
trigger the necessary build. Due to the
<<using-spring-boot.adoc#using-boot-devtools-restart-exclude, default restart
exclusions>>, changes to static resources will not trigger a restart of your application.
They will, however, trigger a live reload.
Alternatively, running in an IDE (especially with debugging on) is a good way to do
development (all modern IDEs allow reloading of static resources and usually also
hot-swapping of Java class changes).
Finally, the <<build-tool-plugins.adoc#build-tool-plugins, Maven and Gradle plugins>> can
be configured (see the `addResources` property) to support running from the command line
with reloading of static files directly from source. You can use that with an external
css/js compiler process if you are writing that code with higher level tools.
[[howto-reload-thymeleaf-template-content]]
=== Reload templates without restarting the container
Most of the templating technologies supported by Spring Boot include a configuration
option to disable caching (see below for details). If you're using the
`spring-boot-devtools` module these properties will be
<<using-spring-boot.adoc#using-boot-devtools-property-defaults,automatically configured>>
for you at development time.
[[howto-reload-thymeleaf-content]]
==== Thymeleaf templates
If you are using Thymeleaf, then set `spring.thymeleaf.cache` to `false`. See
{sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[`ThymeleafAutoConfiguration`]
for other Thymeleaf customization options.
[[howto-reload-freemarker-content]]
==== FreeMarker templates
If you are using FreeMarker, then set `spring.freemarker.cache` to `false`. See
{sc-spring-boot-autoconfigure}/freemarker/FreeMarkerAutoConfiguration.{sc-ext}[`FreeMarkerAutoConfiguration`]
for other FreeMarker customization options.
[[howto-reload-groovy-template-content]]
==== Groovy templates
If you are using Groovy templates, then set `spring.groovy.template.cache` to `false`. See
{sc-spring-boot-autoconfigure}/groovy/template/GroovyTemplateAutoConfiguration.{sc-ext}[`GroovyTemplateAutoConfiguration`]
for other Groovy customization options.
[[howto-reload-velocity-content]]
==== Velocity templates
If you are using Velocity, then set `spring.velocity.cache` to `false`. See
{sc-spring-boot-autoconfigure}/velocity/VelocityAutoConfiguration.{sc-ext}[`VelocityAutoConfiguration`]
for other Velocity customization options.
[[howto-reload-fast-restart]]
=== Fast application restarts
The `spring-boot-devtools` module includes support for automatic application restarts.
Whilst not as fast a technologies such as https://zeroturnaround.com/software/jrebel/[JRebel]
or https://github.com/spring-projects/spring-loaded[Spring Loaded] it's usually
significantly faster than a "`cold start`". You should probably give it a try before
investigating some of the more complex reload options discussed below.
For more details see the <<using-spring-boot.adoc#using-boot-devtools>> section.
[[howto-reload-java-classes-without-restarting]]
=== Reload Java classes without restarting the container
Modern IDEs (Eclipse, IDEA, etc.) all support hot swapping of bytecode, so if you make a
change that doesn't affect class or method signatures it should reload cleanly with no
side effects.
https://github.com/spring-projects/spring-loaded[Spring Loaded] goes a little further in
that it can reload class definitions with changes in the method signatures. With some
customization it can force an `ApplicationContext` to refresh itself (but there is no
general mechanism to ensure that would be safe for a running application anyway, so it
would only ever be a development time trick probably).
[[howto-reload-springloaded-maven]]
==== Configuring Spring Loaded for use with Maven
To use Spring Loaded with the Maven command line, just add it as a dependency in the
Spring Boot plugin declaration, e.g.
[source,xml,indent=0]
----
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.6.RELEASE</version>
</dependency>
</dependencies>
</plugin>
----
This normally works pretty well with Eclipse and IntelliJ IDEA as long as they have their
build configuration aligned with the Maven defaults (Eclipse m2e does this out of the
box).
[[howto-reload-springloaded-gradle-and-intellij-idea]]
==== Configuring Spring Loaded for use with Gradle and IntelliJ IDEA
You need to jump through a few hoops if you want to use Spring Loaded in combination with
Gradle and IntelliJ IDEA. By default, IntelliJ IDEA will compile classes into a different
location than Gradle, causing Spring Loaded monitoring to fail.
To configure IntelliJ IDEA correctly you can use the `idea` Gradle plugin:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
buildscript {
repositories { jcenter() }
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:{spring-boot-version}"
classpath 'org.springframework:springloaded:1.2.6.RELEASE'
}
}
apply plugin: 'idea'
idea {
module {
inheritOutputDirs = false
outputDir = file("$buildDir/classes/main/")
}
}
// ...
----
NOTE: IntelliJ IDEA must be configured to use the same Java version as the command line
Gradle task and `springloaded` *must* be included as a `buildscript` dependency.
You can also additionally enable '`Make Project Automatically`' inside IntelliJ IDEA to
automatically compile your code whenever a file is saved.
[[howto-build]]
== Build
[[howto-build-info]]
=== Generate build information
Both the Maven and Gradle plugin allow to generate build information containing
the coordinates, name and version of the project. The plugin can also be configured
to add additional properties through configuration. When such file is present,
Spring Boot auto-configures a `BuildProperties` bean.
To generate build information with Maven, add an execution for the `build-info` goal:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>{spring-boot-version}</version>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
----
TIP: Check the {spring-boot-maven-plugin-site}/[Spring Boot Maven Plugin documentation]
for more details.
And to do the same with Gradle:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
springBoot {
buildInfo()
}
----
Additional properties can be added using the DSL:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
springBoot {
buildInfo {
additionalProperties = [
'foo': 'bar'
]
}
}
----
[[howto-git-info]]
=== Generate git information
Both Maven and Gradle allow to generate a `git.properties` file containing information
about the state of your `git` source code repository when the project was built.
For Maven users the `spring-boot-starter-parent` POM includes a pre-configured plugin to
generate a `git.properties` file. Simply add the following declaration to your POM:
[source,xml,indent=0]
----
<build>
<plugins>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</plugin>
</plugins>
</build>
----
Gradle users can achieve the same result using the
https://plugins.gradle.org/plugin/com.gorylenko.gradle-git-properties[`gradle-git-properties`] plugin
[source,groovy,indent=0]
----
plugins {
id "com.gorylenko.gradle-git-properties" version "1.4.6"
}
----
[[howto-customize-dependency-versions-with-maven]]
[[howto-customize-dependency-versions]]
=== Customize dependency versions
If you use a Maven build that inherits directly or indirectly from `spring-boot-dependencies`
(for instance `spring-boot-starter-parent`) but you want to override a specific
third-party dependency you can add appropriate `<properties>` elements. Browse
the {github-code}/spring-boot-dependencies/pom.xml[`spring-boot-dependencies`]
POM for a complete list of properties. For example, to pick a different `slf4j` version
you would add the following:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<properties>
<slf4j.version>1.7.5<slf4j.version>
</properties>
----
NOTE: This only works if your Maven project inherits (directly or indirectly) from
`spring-boot-dependencies`. If you have added `spring-boot-dependencies` in your
own `dependencyManagement` section with `<scope>import</scope>` you have to redefine
the artifact yourself instead of overriding the property.
WARNING: Each Spring Boot release is designed and tested against a specific set of
third-party dependencies. Overriding versions may cause compatibility issues.
To override dependency versions in Gradle, you can specify a version as shown below:
[source,groovy,indent=0]
----
ext['slf4j.version'] = '1.7.5'
----
For additional information, please refer to the
https://github.com/spring-gradle-plugins/dependency-management-plugin[Gradle Dependency
Management Plugin documentation].
[[howto-create-an-executable-jar-with-maven]]
=== Create an executable JAR with Maven
The `spring-boot-maven-plugin` can be used to create an executable '`fat`' JAR. If you
are using the `spring-boot-starter-parent` POM you can simply declare the plugin and
your jars will be repackaged:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
----
If you are not using the parent POM you can still use the plugin, however, you must
additionally add an `<executions>` section:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>{spring-boot-version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
----
See the {spring-boot-maven-plugin-site}/usage.html[plugin documentation] for full usage
details.
[[howto-create-an-additional-executable-jar]]
=== Use a Spring Boot application as a dependency
Like a war file, a Spring Boot application is not intended to be used as a dependency. If
your application contains classes that you want to share with other projects, the
recommended approach is to move that code into a separate module. The separate module can
then be depended upon by your application and other projects.
If you cannot rearrange your code as recommended above, Spring Boot's Maven and Gradle
plugins must be configured to produce a separate artifact that is suitable for use as a
dependency. The executable archive cannot be used as a dependency as the
<<appendix-executable-jar-format.adoc#executable-jar-jar-file-structure,executable jar
format>> packages application classes in `BOOT-INF/classes`. This means
that they cannot be found when the executable jar is used as a dependency.
To produce the two artifacts, one that can be used as a dependency and one that is
executable, a classifier must be specified. This classifier is applied to the name of the
executable archive, leaving the default archive for use as dependency.
To configure a classifier of `exec` in Maven, the following configuration can be used:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
----
And when using Gradle, the following configuration can be used:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
bootRepackage {
classifier = 'exec'
}
----
[[howto-extract-specific-libraries-when-an-executable-jar-runs]]
=== Extract specific libraries when an executable jar runs
Most nested libraries in an executable jar do not need to be unpacked in order to run,
however, certain libraries can have problems. For example, JRuby includes its own nested
jar support which assumes that the `jruby-complete.jar` is always directly available as a
file in its own right.
To deal with any problematic libraries, you can flag that specific nested jars should be
automatically unpacked to the '`temp folder`' when the executable jar first runs.
For example, to indicate that JRuby should be flagged for unpack using the Maven Plugin
you would add the following configuration:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<requiresUnpack>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</plugin>
</plugins>
</build>
----
And to do that same with Gradle:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
springBoot {
requiresUnpack = ['org.jruby:jruby-complete']
}
----
[[howto-create-a-nonexecutable-jar]]
=== Create a non-executable JAR with exclusions
Often if you have an executable and a non-executable jar as build products, the executable
version will have additional configuration files that are not needed in a library jar.
E.g. the `application.yml` configuration file might excluded from the non-executable JAR.
Here's how to do that in Maven:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>exec</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<!-- Need this to ensure application.yml is excluded -->
<forceCreation>true</forceCreation>
<excludes>
<exclude>application.yml</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
----
In Gradle you can create a new JAR archive with standard task DSL features, and then have
the `bootRepackage` task depend on that one using its `withJarTask` property:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
jar {
baseName = 'spring-boot-sample-profile'
version = '0.0.0'
excludes = ['**/application.yml']
}
task('execJar', type:Jar, dependsOn: 'jar') {
baseName = 'spring-boot-sample-profile'
version = '0.0.0'
classifier = 'exec'
from sourceSets.main.output
}
bootRepackage {
withJarTask = tasks['execJar']
}
----
[[howto-remote-debug-maven-run]]
=== Remote debug a Spring Boot application started with Maven
To attach a remote debugger to a Spring Boot application started with Maven you can use
the `jvmArguments` property of the {spring-boot-maven-plugin-site}/[maven plugin].
Check {spring-boot-maven-plugin-site}/examples/run-debug.html[this example] for more details.
[[howto-remote-debug-gradle-run]]
=== Remote debug a Spring Boot application started with Gradle
To attach a remote debugger to a Spring Boot application started with Gradle you can use
the `jvmArgs` property of `bootRun` task or `--debug-jvm` command line option.
`build.gradle`:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
bootRun {
jvmArgs "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
}
----
Command line:
[indent=0]
----
$ gradle bootRun --debug-jvm
----
Check {gradle-userguide}/application_plugin.html[Gradle Application Plugin] for more
details.
[[howto-build-an-executable-archive-with-ant]]
=== Build an executable archive from Ant without using spring-boot-antlib
To build with Ant you need to grab dependencies, compile and then create a jar or war
archive. To make it executable you can either use the `spring-boot-antlib`
module, or you can follow these instructions:
. If you are building a jar, package the application's classes and resources in a nested
`BOOT-INF/classes` directory. If you are building a war, package the application's
classes in a nested `WEB-INF/classes` directory as usual.
. Add the runtime dependencies in a nested `BOOT-INF/lib` directory for a jar or
`WEB-INF/lib` for a war. Remember *not* to compress the entries in the archive.
. Add the `provided` (embedded container) dependencies in a nested `BOOT-INF/lib`
directory for jar or `WEB-INF/lib-provided` for a war. Remember *not* to compress the
entries in the archive.
. Add the `spring-boot-loader` classes at the root of the archive (so the `Main-Class`
is available).
. Use the appropriate launcher, e.g. `JarLauncher` for a jar file, as a `Main-Class`
attribute in the manifest and specify the other properties it needs as manifest entries,
principally a `Start-Class`.
Example:
[source,xml,indent=0]
----
<target name="build" depends="compile">
<jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
<mappedresources>
<fileset dir="target/classes" />
<globmapper from="*" to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<fileset dir="src/main/resources" erroronmissingdir="false"/>
<globmapper from="*" to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<fileset dir="${lib.dir}/runtime" />
<globmapper from="*" to="BOOT-INF/lib/*"/>
</mappedresources>
<zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
<manifest>
<attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
<attribute name="Start-Class" value="${start-class}" />
</manifest>
</jar>
</target>
----
The {github-code}/spring-boot-samples/spring-boot-sample-ant[Ant Sample] has a
`build.xml` with a `manual` task that should work if you run it with
[indent=0,subs="verbatim,quotes,attributes"]
----
$ ant -lib <folder containing ivy-2.2.jar> clean manual
----
after which you can run the application with
[indent=0,subs="verbatim,quotes,attributes"]
----
$ java -jar target/*.jar
----
[[howto-use-java-6]]
=== How to use Java 6
If you want to use Spring Boot with Java 6 there are a small number of configuration
changes that you will have to make. The exact changes depend on your application's
functionality.
[[howto-use-java-6-embedded-container]]
==== Embedded servlet container compatibility
If you are using one of Boot's embedded Servlet containers you will have to use a
Java 6-compatible container. Both Tomcat 7 and Jetty 8 are Java 6 compatible. See
<<howto-use-tomcat-7>> and <<howto-use-jetty-8>> for details.
[[howto-use-java-6-jackson]]
==== Jackson
Jackson 2.7 and later requires Java 7. If you want to use Jackson with Java 6 you
will have to downgrade to Jackson 2.6.
[[how-to-use-java-6-jta-api]]
==== JTA API compatibility
While the Java Transaction API itself doesn't require Java 7 the official API jar
contains classes that have been built to require Java 7. If you are using JTA then
you will need to replace the official JTA 1.2 API jar with one that has been built
to work on Java 6. To do so, exclude any transitive dependencies on
`javax.transaction:javax.transaction-api` and replace them with a dependency on
`org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Final`
[[howto-traditional-deployment]]
== Traditional deployment
[[howto-create-a-deployable-war-file]]
=== Create a deployable war file
The first step in producing a deployable war file is to provide a
`SpringBootServletInitializer` subclass and override its `configure` method. This makes
use of Spring Framework's Servlet 3.0 support and allows you to configure your
application when it's launched by the servlet container. Typically, you update your
application's main class to extend `SpringBootServletInitializer`:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
----
The next step is to update your build configuration so that your project produces a war file
rather than a jar file. If you're using Maven and using `spring-boot-starter-parent` (which
configures Maven's war plugin for you) all you need to do is modify `pom.xml` to change the
packaging to war:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<packaging>war</packaging>
----
If you're using Gradle, you need to modify `build.gradle` to apply the war plugin to the
project:
[source,groovy,indent=0,subs="verbatim,quotes,attributes"]
----
apply plugin: 'war'
----
The final step in the process is to ensure that the embedded servlet container doesn't
interfere with the servlet container to which the war file will be deployed. To do so, you
need to mark the embedded servlet container dependency as provided.
If you're using Maven:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
<dependencies>
<!-- … -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- … -->
</dependencies>
----
And if you're using Gradle:
[source,groovy,indent=0,subs="verbatim,quotes,attributes"]
----
dependencies {
// …
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
// …
}
----
NOTE: If you are using a version of Gradle that supports compile only dependencies (2.12
or later), you should continue to use `providedRuntime`. Among other limitations,
`compileOnly` dependencies are not on the test classpath so any web-based integration
tests will fail.
If you're using the <<build-tool-plugins.adoc#build-tool-plugins, Spring Boot build tools>>,
marking the embedded servlet container dependency as provided will produce an executable war
file with the provided dependencies packaged in a `lib-provided` directory. This means
that, in addition to being deployable to a servlet container, you can also run your
application using `java -jar` on the command line.
TIP: Take a look at Spring Boot's sample applications for a
{github-code}/spring-boot-samples/spring-boot-sample-traditional/pom.xml[Maven-based example]
of the above-described configuration.
[[howto-create-a-deployable-war-file-for-older-containers]]
=== Create a deployable war file for older servlet containers
Older Servlet containers don't have support for the `ServletContextInitializer` bootstrap
process used in Servlet 3.0. You can still use Spring and Spring Boot in these containers
but you are going to need to add a `web.xml` to your application and configure it to load
an `ApplicationContext` via a `DispatcherServlet`.
[[howto-convert-an-existing-application-to-spring-boot]]
=== Convert an existing application to Spring Boot
For a non-web application it should be easy (throw away the code that creates your
`ApplicationContext` and replace it with calls to `SpringApplication` or
`SpringApplicationBuilder`). Spring MVC web applications are generally amenable to first
creating a deployable war application, and then migrating it later to an executable war
and/or jar. Useful reading is in the https://spring.io/guides/gs/convert-jar-to-war/[Getting
Started Guide on Converting a jar to a war].
Create a deployable war by extending `SpringBootServletInitializer` (e.g. in a class
called `Application`), and add the Spring Boot `@SpringBootApplication` annotation.
Example:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
// Customize the application or call application.sources(...) to add sources
// Since our example is itself a @Configuration class (via @SpringBootApplication)
// we actually don't need to override this method.
return application;
}
}
----
Remember that whatever you put in the `sources` is just a Spring `ApplicationContext` and
normally anything that already works should work here. There might be some beans you can
remove later and let Spring Boot provide its own defaults for them, but it should be
possible to get something working first.
Static resources can be moved to `/public` (or `/static` or `/resources` or
`/META-INF/resources`) in the classpath root. Same for `messages.properties` (Spring Boot
detects this automatically in the root of the classpath).
Vanilla usage of Spring `DispatcherServlet` and Spring Security should require no further
changes. If you have other features in your application, using other servlets or filters
for instance, then you may need to add some configuration to your `Application` context,
replacing those elements from the `web.xml` as follows:
* A `@Bean` of type `Servlet` or `ServletRegistrationBean` installs that bean in the
container as if it was a `<servlet/>` and `<servlet-mapping/>` in `web.xml`.
* A `@Bean` of type `Filter` or `FilterRegistrationBean` behaves similarly (like a
`<filter/>` and `<filter-mapping/>`.
* An `ApplicationContext` in an XML file can be added through an `@ImportResource` in
your `Application`. Or simple cases where annotation configuration is heavily used
already can be recreated in a few lines as `@Bean` definitions.
Once the war is working we make it executable by adding a `main` method to our
`Application`, e.g.
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
----
[NOTE]
====
If you intend to start your application as a war or as an executable application, you
need to share the customizations of the builder in a method that is both available to the
`SpringBootServletInitializer` callback and the `main` method, something like:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return configureApplication(builder);
}
public static void main(String[] args) {
configureApplication(new SpringApplicationBuilder()).run(args);
}
private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) {
return builder.sources(Application.class).bannerMode(Banner.Mode.OFF);
}
}
----
====
Applications can fall into more than one category:
* Servlet 3.0+ applications with no `web.xml`.
* Applications with a `web.xml`.
* Applications with a context hierarchy.
* Applications without a context hierarchy.
All of these should be amenable to translation, but each might require slightly different
tricks.
Servlet 3.0+ applications might translate pretty easily if they already use the Spring
Servlet 3.0+ initializer support classes. Normally all the code from an existing
`WebApplicationInitializer` can be moved into a `SpringBootServletInitializer`. If your
existing application has more than one `ApplicationContext` (e.g. if it uses
`AbstractDispatcherServletInitializer`) then you might be able to squash all your context
sources into a single `SpringApplication`. The main complication you might encounter is if
that doesn't work and you need to maintain the context hierarchy. See the
<<howto-build-an-application-context-hierarchy, entry on building a hierarchy>> for
examples. An existing parent context that contains web-specific features will usually
need to be broken up so that all the `ServletContextAware` components are in the child
context.
Applications that are not already Spring applications might be convertible to a Spring
Boot application, and the guidance above might help, but your mileage may vary.
[[howto-weblogic]]
=== Deploying a WAR to WebLogic
To deploy a Spring Boot application to WebLogic you must ensure that your servlet
initializer *directly* implements `WebApplicationInitializer` (even if you extend from a
base class that already implements it).
A typical initializer for WebLogic would be something like this:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.web.WebApplicationInitializer;
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer {
}
----
If you use logback, you will also need to tell WebLogic to prefer the packaged version
rather than the version that pre-installed with the server. You can do this by adding a
`WEB-INF/weblogic.xml` file with the following contents:
[source,xml,indent=0]
----
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app
xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
https://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd
http://xmlns.oracle.com/weblogic/weblogic-web-app
https://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
<wls:container-descriptor>
<wls:prefer-application-packages>
<wls:package-name>org.slf4j</wls:package-name>
</wls:prefer-application-packages>
</wls:container-descriptor>
</wls:weblogic-web-app>
----
[[howto-servlet-2-5]]
=== Deploying a WAR in an Old (Servlet 2.5) Container
Spring Boot uses Servlet 3.0 APIs to initialize the `ServletContext` (register `Servlets`
etc.) so you can't use the same application out of the box in a Servlet 2.5 container.
It *is* however possible to run a Spring Boot application on an older container with some
special tools. If you include `org.springframework.boot:spring-boot-legacy` as a
dependency (https://github.com/scratches/spring-boot-legacy[maintained separately] to the
core of Spring Boot and currently available at 1.0.2.RELEASE), all you should need to do
is create a `web.xml` and declare a context listener to create the application context and
your filters and servlets. The context listener is a special purpose one for Spring Boot,
but the rest of it is normal for a Spring application in Servlet 2.5. Example:
[source,xml,indent=0]
----
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>demo.Application</param-value>
</context-param>
<listener>
<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>metricsFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>metricsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
----
In this example we are using a single application context (the one created by the context
listener) and attaching it to the `DispatcherServlet` using an init parameter. This is
normal in a Spring Boot application (you normally only have one application context).