Appearance
Spring Boot: “How-to” Guides - Part1
This section provides answers to some common ‘how do I do that…’ questions that often arise when using Spring Boot. Its coverage is not exhaustive, but it does cover quite a lot.
If you have a specific problem that we do not cover here, you might want to check 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 are also more than happy to extend this section. If you want to add a ‘how-to’, send us a pull request.
1. Spring Boot Application
This section includes topics relating directly to Spring Boot applications.
1.1. Create Your Own FailureAnalyzer
FailureAnalyzer is a great way to intercept an exception on startup and turn it into a human-readable message, wrapped in a FailureAnalysis. Spring Boot provides such an analyzer for application-context-related exceptions, JSR-303 validations, and more. You can also create your own.
AbstractFailureAnalyzer is a convenient extension of FailureAnalyzer that checks the presence of a specified exception type in the exception to handle. You can extend from that so that your implementation gets a chance to handle the exception only when it is actually present. If, for whatever reason, you cannot handle the exception, return null to give another implementation a chance to handle the exception.
FailureAnalyzer implementations must be registered in META-INF/spring.factories. The following example registers ProjectConstraintViolationFailureAnalyzer:
Properties
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzerTip:If you need access to the
BeanFactoryor theEnvironment, yourFailureAnalyzercan implementBeanFactoryAwareorEnvironmentAwarerespectively.
1.2. 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 can see it if you enable DEBUG logging output. If you use the spring-boot-actuator (see the Actuator chapter), there is also a conditions endpoint that renders the report in JSON. Use that endpoint to debug the application and see what features have been added (and which have not been added) by Spring Boot at runtime.
Many more questions can be answered by looking at the source code and the Javadoc. When reading the code, remember the following rules of thumb:
Look for classes called
*AutoConfigurationand read their sources. Pay special attention to the@Conditional*annotations to find out what features they enable and when. Add--debugto the command line or a System property-Ddebugto get a log on the console of all the auto-configuration decisions that were made in your app. In a running application with actuator enabled, look at theconditionsendpoint (/actuator/conditionsor the JMX equivalent) for the same information.Look for classes that are
@ConfigurationProperties(such asServerProperties) and read from there the available external configuration options. The@ConfigurationPropertiesannotation has anameattribute that acts as a prefix to external properties. Thus,ServerPropertieshasprefix="server"and its configuration properties areserver.port,server.address, and others. In a running application with actuator enabled, look at theconfigpropsendpoint.Look for uses of the
bindmethod on theBinderto pull configuration values explicitly out of theEnvironmentin a relaxed manner. It is often used with a prefix.Look for
@Valueannotations that bind directly to theEnvironment.Look for
@ConditionalOnExpressionannotations that switch features on and off in response to SpEL expressions, normally evaluated with placeholders resolved from theEnvironment.
1.3. 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 customizations:
Programmatically, per application, by calling the
addListenersandaddInitializersmethods onSpringApplicationbefore you run it.Declaratively, per application, by setting the
context.initializer.classesorcontext.listener.classesproperties.Declaratively, for all applications, by adding a
META-INF/spring.factoriesand packaging a jar file that the applications all use as a library.
The SpringApplication sends some special ApplicationEvents to the listeners (some even before the context is created) and then registers the listeners for events published by the ApplicationContext as well. See “Application Events and Listeners” in the ‘Spring Boot features’ section for a complete list.
It is also possible to customize the Environment before the application context is refreshed by using EnvironmentPostProcessor. Each implementation should be registered in META-INF/spring.factories, as shown in the following example:
Properties
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessorThe implementation can load arbitrary files and add them to the Environment. For instance, the following example loads a YAML configuration file from the classpath:
Java
import java.io.IOException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Resource path = new ClassPathResource("com/example/myapp/config.yml");
PropertySource<?> propertySource = loadYaml(path);
environment.getPropertySources().addLast(propertySource);
}
private PropertySource<?> loadYaml(Resource path) {
Assert.isTrue(path.exists(), () -> "Resource " + path + " does not exist");
try {
return this.loader.load("custom-resource", path).get(0);
}
catch (IOException ex) {
throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Note:The
Environmenthas already been prepared with all the usual property sources that Spring Boot loads by default. It is therefore possible to get the location of the file from the environment. The preceding example adds thecustom-resourceproperty source at the end of the list so that a key defined in any of the usual other locations takes precedence. A custom implementation may define another order.
Caution:While using
@PropertySourceon your@SpringBootApplicationmay seem to be a convenient way to load a custom resource in theEnvironment, we do not recommend it. Such property sources are not added to theEnvironmentuntil the application context is being refreshed. This is too late to configure certain properties such aslogging.*andspring.main.*which are read before refresh begins.
1.4. Build an ApplicationContext Hierarchy (Adding a Parent or Root Context)
You can use the ApplicationBuilder class to create parent/child ApplicationContext hierarchies. See “Fluent Builder API” in the ‘Spring Boot features’ section for more information.
1.5. 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, you can use the SpringApplication features of Spring Boot. A SpringApplication changes its ApplicationContext class, depending on whether it thinks it needs a web application or not. The first thing you can do to help it is to leave server-related dependencies (such as the servlet API) off the classpath. If you cannot do that (for example, you run two applications from the same code base) then you can explicitly call setWebApplicationType(WebApplicationType.NONE) 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.
2. Properties and Configuration
This section includes topics about setting and reading properties and configuration settings and their interaction with Spring Boot applications.
2.1. 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 by instead using the existing build configuration. This is possible in both Maven and Gradle.
2.1.1. Automatic Property Expansion Using Maven
You can automatically expand properties from the Maven project by using resource filtering. If you use the spring-boot-starter-parent, you can then refer to your Maven ‘project properties’ with @..@ placeholders, as shown in the following example:
Properties
app.encoding=@project.build.sourceEncoding@
app.java.version=@java.version@Tip:Only production configuration is filtered that way (in other words, no filtering is applied on
src/test/resources).
Note:If you enable the
addResourcesflag, thespring-boot:rungoal can addsrc/main/resourcesdirectly to the classpath (for hot reloading purposes). Doing so circumvents the resource filtering and this feature. Instead, you can use theexec:javagoal or customize the plugin’s configuration. See the plugin usage page for more details.
If you do not use the starter parent, you need to include the following element inside the <build/> element of your pom.xml:
XML
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>You also need to include the following element inside <plugins/>:
XML
<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>Tip:The
useDefaultDelimitersproperty is important if you use standard Spring placeholders (such as${placeholder}) in your configuration. If that property is not set tofalse, these may be expanded by the build.
2.1.2. 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, as shown in the following example:
Gradle
tasks.named('processResources') {
expand(project.properties)
}You can then refer to your Gradle project’s properties by using placeholders, as shown in the following example:
Properties
app.name=${name}
app.description=${description}Tip:Gradle’s
expandmethod uses Groovy’sSimpleTemplateEngine, which transforms${..}tokens. The${..}style conflicts with Spring’s own property placeholder mechanism. To use Spring property placeholders together with automatic expansion, escape the Spring property placeholders as follows:\${..}.
2.2. Externalize the Configuration of SpringApplication
A SpringApplication has bean property setters, so you can use its Java API as you create the application to modify its behavior. Alternatively, you can externalize the configuration by setting properties in spring.main.*. For example, in application.properties, you might have the following settings:
Properties
spring.main.web-application-type=none
spring.main.banner-mode=offThen the Spring Boot banner is not printed on startup, and the application is not starting an embedded web server.
Properties defined in external configuration override and replace the values specified with the Java API, with the notable exception of the primary sources. Primary sources are those provided to the SpringApplication constructor:
Java
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Or to sources(…) method of a SpringApplicationBuilder:
Java
import org.springframework.boot.Banner;
import org.springframework.boot.builder.SpringApplicationBuilder;
public class MyApplication {
public static void main(String[] args) {
new SpringApplicationBuilder()
.bannerMode(Banner.Mode.OFF)
.sources(MyApplication.class)
.run(args);
}
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Given the examples above, if we have the following configuration:
Properties
spring.main.sources=com.example.MyDatabaseConfig,com.example.MyJmsConfig
spring.main.banner-mode=consoleThe actual application will show the banner (as overridden by configuration) and uses three sources for the ApplicationContext. The application sources are:
MyApplication(from the code)MyDatabaseConfig(from the external config)MyJmsConfig(from the external config)
2.3. 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 “Externalized Configuration” in the ‘Spring Boot features’ section for the exact order).
You can also provide the following System properties (or environment variables) to change the behavior:
spring.config.name(SPRING_CONFIG_NAME): Defaults toapplicationas the root of the file name.spring.config.location(SPRING_CONFIG_LOCATION): The file to load (such as a classpath resource or a URL). A separateEnvironmentproperty 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 always loads application.properties as described above. By default, if YAML is used, then files with the ‘.yaml’ and ‘.yml’ extension are also added to the list.
Note:If you want detailed information about the files that are being loaded you can set the logging level of
org.springframework.boot.context.configtotrace.
2.4. 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 enable this behavior by using placeholders in application.properties, as shown in the following example:
Properties
server.port=${port:8080}Note:If you inherit from the
spring-boot-starter-parentPOM, the default filter token of themaven-resources-pluginshas been changed from${*}to@(that is,@maven.token@instead of${maven.token}) to prevent conflicts with Spring-style placeholders. If you have enabled Maven filtering for theapplication.propertiesdirectly, you may want to also change the default filter token to use other delimiters.
Tip:In this specific case, the port binding works in a PaaS environment such as Heroku or Cloud Foundry. In those two platforms, the
PORTenvironment variable is set automatically and Spring can bind to capitalized synonyms forEnvironmentproperties.
2.5. Use YAML for External Properties
YAML is a superset of JSON and, as such, is a convenient syntax for storing external properties in a hierarchical format, as shown in the following example:
YAML
spring:
application:
name: "cruncher"
datasource:
driver-class-name: "com.mysql.jdbc.Driver"
url: "jdbc:mysql://localhost/test"
server:
port: 9000Create a file called application.yaml and put it in the root of your classpath. Then 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 one level deep and has period-separated keys, as many people are used to with Properties files in Java.
The preceding example YAML corresponds to the following application.properties file:
Properties
spring.application.name=cruncher
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/test
server.port=9000See “Working With YAML” in the ‘Spring Boot features’ section for more information about YAML.
2.6. Set the Active Spring Profiles
The Spring Environment has an API for this, but you would normally set a System property (spring.profiles.active) or an OS environment variable (SPRING_PROFILES_ACTIVE). Also, you can launch your application with a -D argument (remember to put it before the main class or jar archive), as follows:
Bash
$ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jarIn Spring Boot, you can also set the active profile in application.properties, as shown in the following example:
Properties
spring.profiles.active=productionA 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 “Profiles” in the “Spring Boot features” section for more information.
2.7. Set the Default Profile Name
The default profile is a profile that is enabled if no profile is active. By default, the name of the default profile is default, but it could be changed using a System property (spring.profiles.default) or an OS environment variable (SPRING_PROFILES_DEFAULT).
In Spring Boot, you can also set the default profile name in application.properties, as shown in the following example:
Properties
spring.profiles.default=devSee “Profiles” in the “Spring Boot features” section for more information.
2.8. Change Configuration Depending on the Environment
Spring Boot supports multi-document YAML and Properties files (see Working With Multi-Document Files for details) which can be activated conditionally based on the active profiles.
If a document contains a spring.config.activate.on-profile key, then the profiles value (a comma-separated list of profiles or a profile expression) is fed into the Spring Environment.acceptsProfiles() method. If the profile expression matches then that document is included in the final merge (otherwise, it is not), as shown in the following example:
Properties
server.port=9000
#---
spring.config.activate.on-profile=development
server.port=9001
#---
spring.config.activate.on-profile=production
server.port=0In the preceding example, the default port is 9000. However, if the Spring profile called ‘development’ is active, then the port is 9001. If ‘production’ is active, then the port is 0.
Tip:The documents are merged in the order in which they are encountered. Later values override earlier values.
2.9. Discover Built-in Options for External Properties
Spring Boot binds external properties from application.properties (or YAML files 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 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 Binder. For more about the exact ordering of loading properties, see "Externalized Configuration".
3. Embedded Web Servers
Each Spring Boot web application includes an embedded web server. This feature leads to a number of how-to questions, including how to change the embedded server and how to configure the embedded server. This section answers those questions.
3.1. Use Another Web Server
Many Spring Boot starters include default embedded containers.
For servlet stack applications, the
spring-boot-starter-webincludes Tomcat by includingspring-boot-starter-tomcat, but you can usespring-boot-starter-jettyorspring-boot-starter-undertowinstead.For reactive stack applications, the
spring-boot-starter-webfluxincludes Reactor Netty by includingspring-boot-starter-reactor-netty, but you can usespring-boot-starter-tomcat,spring-boot-starter-jetty, orspring-boot-starter-undertowinstead.
When switching to a different HTTP server, you need to swap the default dependencies for those that you need instead. To help with this process, Spring Boot provides a separate starter for each of the supported HTTP servers.
The following Maven example shows how to exclude Tomcat and include Jetty for Spring MVC:
XML
<properties>
<servlet-api.version>3.1.0</servlet-api.version>
</properties>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- Exclude the Tomcat dependency -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>Tip:The version of the servlet API has been overridden as, unlike Tomcat 9 and Undertow 2, Jetty 9.4 does not support servlet 4.0.
If you wish to use Jetty 10, which does support servlet 4.0, you can do so as shown in the following example:
XML
<properties>
<jetty.version>10.0.8</jetty.version>
</properties>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- Exclude the Tomcat dependency -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
<exclusions>
<!-- Exclude the Jetty-9 specific dependencies -->
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-server-impl</artifactId>
</exclusion>
</exclusions>
</dependency>Note that along with excluding the Tomcat starter, a couple of Jetty9-specific dependencies also need to be excluded.
The following Gradle example configures the necessary dependencies and a module replacement to use Undertow in place of Reactor Netty for Spring WebFlux:
Gradle
dependencies {
implementation "org.springframework.boot:spring-boot-starter-undertow"
implementation "org.springframework.boot:spring-boot-starter-webflux"
modules {
module("org.springframework.boot:spring-boot-starter-reactor-netty") {
replacedBy("org.springframework.boot:spring-boot-starter-undertow", "Use Undertow instead of Reactor Netty")
}
}
}Tip:
spring-boot-starter-reactor-nettyis required to use theWebClientclass, so you may need to keep a dependency on Netty even when you need to include a different HTTP server.
3.2. Disabling the Web Server
If your classpath contains the necessary bits to start a web server, Spring Boot will automatically start it. To disable this behavior configure the WebApplicationType in your application.properties, as shown in the following example:
Properties
spring.main.web-application-type=none3.3. Change the HTTP Port
In a standalone application, the main HTTP port defaults to 8080 but can be set with server.port (for example, in application.properties or as a System property). Thanks to relaxed binding of Environment values, you can also use SERVER_PORT (for example, as an OS environment variable).
To switch off the HTTP endpoints completely but still create a WebApplicationContext, use server.port=-1 (doing so is sometimes useful for testing).
For more details, see “Customizing Embedded Servlet Containers” in the ‘Spring Boot Features’ section, or the ServerProperties source code.
3.4. Use a Random Unassigned HTTP Port
To scan for a free port (using OS natives to prevent clashes) use server.port=0.
3.5. Discover the HTTP Port at Runtime
You can access the port the server is running on from log output or from the WebServerApplicationContext through its WebServer. The best way to get that and be sure it has been initialized is to add a @Bean of type ApplicationListener<WebServerInitializedEvent> 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 by using the @LocalServerPort annotation, as shown in the following example:
Java
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.server.LocalServerPort;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyWebIntegrationTests {
@LocalServerPort
int port;
// ...
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Tip:
@LocalServerPortis a meta-annotation for@Value("${local.server.port}"). Do not try to inject the port in a regular application. As we just saw, the value is set only after the container has been initialized. Contrary to a test, application code callbacks are processed early (before the value is actually available).
3.6. Enable HTTP Response Compression
HTTP response compression is supported by Jetty, Tomcat, Reactor Netty, and Undertow. It can be enabled in application.properties, as follows:
Properties
server.compression.enabled=trueBy default, responses must be at least 2048 bytes in length for compression to be performed. You can configure this behavior by setting the server.compression.min-response-size property.
By default, responses are compressed only if their content type is one of the following:
text/htmltext/xmltext/plaintext/csstext/javascriptapplication/javascriptapplication/jsonapplication/xml
You can configure this behavior by setting the server.compression.mime-types property.
3.7. Configure SSL
SSL can be configured declaratively by setting the various server.ssl.* properties, typically in application.properties or application.yaml. The following example shows setting SSL properties using a Java KeyStore file:
Properties
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secretUsing configuration such as the preceding example means the application no longer supports a plain HTTP connector at port 8080. Spring Boot does not support the configuration of both an HTTP connector and an HTTPS connector through application.properties. If you want to have both, you need to configure one of them programmatically. We recommend using application.properties to configure HTTPS, as the HTTP connector is the easier of the two to configure programmatically.
3.7.1. Using PEM-encoded files
You can use PEM-encoded files instead of Java KeyStore files. You should use PKCS#8 key files wherever possible. PEM-encoded PKCS#8 key files start with a -----BEGIN PRIVATE KEY----- or -----BEGIN ENCRYPTED PRIVATE KEY----- header.
If you have files in other formats, e.g., PKCS#1 (-----BEGIN RSA PRIVATE KEY-----) or SEC 1 (-----BEGIN EC PRIVATE KEY-----), you can convert them to PKCS#8 using OpenSSL:
Bash
openssl pkcs8 -topk8 -nocrypt -in <input file> -out <output file>The following example shows setting SSL properties using PEM-encoded certificate and private key files:
Properties
server.port=8443
server.ssl.certificate=classpath:my-cert.crt
server.ssl.certificate-private-key=classpath:my-cert.key
server.ssl.trust-certificate=classpath:ca-cert.crtSee Ssl for details of all of the supported properties.
3.8. Configure HTTP/2
You can enable HTTP/2 support in your Spring Boot application with the server.http2.enabled configuration property. Both h2 (HTTP/2 over TLS) and h2c (HTTP/2 over TCP) are supported. To use h2, SSL must also be enabled. When SSL is not enabled, h2c will be used. You may, for example, want to use h2c when your application is running behind a proxy server that is performing TLS termination. The details of the h2 support depend on the chosen web server and the application environment, since that protocol is not supported out-of-the-box by all JDK 8 releases.
3.8.1. HTTP/2 With Tomcat
Spring Boot ships by default with Tomcat 9.0.x which supports h2c out of the box and h2 out of the box when using JDK 9 or later. Alternatively, h2 can be used on JDK 8 if the libtcnative library and its dependencies are installed on the host operating system.
The library directory must be made available, if not already, to the JVM library path. You can do so with a JVM argument such as -Djava.library.path=/usr/local/opt/tomcat-native/lib. More on this in the official Tomcat documentation.
Starting Tomcat 9.0.x on JDK 8 with HTTP/2 and SSL enabled but without that native support logs the following error:
Text
ERROR 8787 --- [ main] o.a.coyote.http11.Http11NioProtocol : The upgrade handler [org.apache.coyote.http2.Http2Protocol] for [h2] only supports upgrade via ALPN but has been configured for the ["https-jsse-nio-8443"] connector that does not support ALPN.This error is not fatal, and the application still starts with HTTP/1.1 SSL support.
3.8.2. HTTP/2 With Jetty
For HTTP/2 support, Jetty requires the additional org.eclipse.jetty.http2:http2-server dependency. To use h2c no other dependencies are required. To use h2, you also need to choose one of the following dependencies, depending on your deployment:
org.eclipse.jetty:jetty-alpn-java-serverfor applications running on JDK9+org.eclipse.jetty:jetty-alpn-openjdk8-serverfor applications running on JDK8u252+org.eclipse.jetty:jetty-alpn-conscrypt-serverand the Conscrypt library with no JDK requirement
3.8.3. HTTP/2 With Reactor Netty
The spring-boot-webflux-starter is using by default Reactor Netty as a server. Reactor Netty supports h2c using JDK 8 or later with no additional dependencies. Reactor Netty supports h2 using the JDK support with JDK 9 or later. For JDK 8 environments, or for optimal runtime performance, this server also supports h2 with native libraries. To enable that, your application needs to have an additional dependency.
Spring Boot manages the version for the io.netty:netty-tcnative-boringssl-static "uber jar", containing native libraries for all platforms. Developers can choose to import only the required dependencies using a classifier (see the Netty official documentation).
3.8.4. HTTP/2 With Undertow
As of Undertow 1.4.0+, both h2 and h2c are supported on JDK 8 without any additional dependencies.
3.9. Configure the Web Server
Generally, you should first consider using one of the many available configuration keys and customize your web server by adding new entries in your application.properties or application.yaml file. See “Discover Built-in Options for External Properties”). The server.* namespace is quite useful here, and it includes namespaces like server.tomcat.*, server.jetty.* and others, for server-specific features. See the list of Common Application Properties.
The previous sections covered already many common use cases, such as compression, SSL or HTTP/2. However, if a configuration key does not exist for your use case, you should then look at WebServerFactoryCustomizer. You can declare such a component and get access to the server factory relevant to your choice: you should select the variant for the chosen Server (Tomcat, Jetty, Reactor Netty, Undertow) and the chosen web stack (servlet or reactive).
The example below is for Tomcat with the spring-boot-starter-web (servlet stack):
Java
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
@Component
public class MyTomcatWebServerCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
// customize the factory here
}
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Tip:Spring Boot uses that infrastructure internally to auto-configure the server. Auto-configured
WebServerFactoryCustomizerbeans have an order of0and will be processed before any user-defined customizers, unless it has an explicit order that states otherwise.
Once you have got access to a WebServerFactory using the customizer, you can use it to configure specific parts, like connectors, server resources, or the server itself - all using server-specific APIs.
In addition Spring Boot provides:
| Server | Servlet stack | Reactive stack |
|---|---|---|
| Tomcat | TomcatServletWebServerFactory | TomcatReactiveWebServerFactory |
| Jetty | JettyServletWebServerFactory | JettyReactiveWebServerFactory |
| Undertow | UndertowServletWebServerFactory | UndertowReactiveWebServerFactory |
| Reactor | N/A | NettyReactiveWebServerFactory |
As a last resort, you can also declare your own WebServerFactory bean, which will override the one provided by Spring Boot. When you do so, auto-configured customizers are still applied on your custom factory, so use that option carefully.
3.10. Add a Servlet, Filter, or Listener to an Application
In a servlet stack application, that is with the spring-boot-starter-web, there are two ways to add Servlet, Filter, ServletContextListener, and the other listeners supported by the Servlet API to your application:
- Add a Servlet, Filter, or Listener by Using a Spring Bean
- Add Servlets, Filters, and Listeners by Using Classpath Scanning
3.10.1. Add a Servlet, Filter, or Listener by Using a Spring Bean
To add a Servlet, Filter, or servlet *Listener by using a Spring bean, you must provide a @Bean definition for it. Doing so can be very useful when you want to inject configuration or dependencies. However, you must be very careful that they do not cause eager initialization of too many other beans, because they have to be installed in the container very early in the application lifecycle. (For example, it is not a good idea to have them depend on your DataSource or JPA configuration.) You can work around such restrictions by initializing the beans 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 a ServletRegistrationBean instead of or in addition to the underlying component.
Tip:If no
dispatcherTypeis specified on a filter registration,REQUESTis used. This aligns with the servlet specification’s default dispatcher type.
Like any other Spring bean, you can define the order of servlet filter beans; please make sure to check the “Registering Servlets, Filters, and Listeners as Spring Beans” section.
3.10.1.1. Disable Registration of a Servlet or Filter
As described earlier, any Servlet or Filter beans are 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, as shown in the following example:
Java
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyFilterConfiguration {
@Bean
public FilterRegistrationBean<MyFilter> registration(MyFilter filter) {
FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>(filter);
registration.setEnabled(false);
return registration;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
3.10.2. Add Servlets, Filters, and Listeners by 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 scans from the package of the annotated class.
3.11. Configure Access Logging
Access logs can be configured for Tomcat, Undertow, and Jetty through their respective namespaces.
For instance, the following settings log access on Tomcat with a custom pattern.
Properties
server.tomcat.basedir=my-tomcat
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%t %a %r %s (%D ms)Tip:The default location for logs is a
logsdirectory relative to the Tomcat base directory. By default, thelogsdirectory is a temporary directory, so you may want to fix Tomcat’s base directory or use an absolute path for the logs. In the preceding example, the logs are available inmy-tomcat/logsrelative to the working directory of the application.
Access logging for Undertow can be configured in a similar fashion, as shown in the following example:
Properties
server.undertow.accesslog.enabled=true
server.undertow.accesslog.pattern=%t %a %r %s (%D ms)
server.undertow.options.server.record-request-start-time=trueNote that, in addition to enabling access logging and configuring its pattern, recording request start times has also been enabled. This is required when including the response time (%D) in the access log pattern. Logs are stored in a logs directory relative to the working directory of the application. You can customize this location by setting the server.undertow.accesslog.dir property.
Finally, access logging for Jetty can also be configured as follows:
Properties
server.jetty.accesslog.enabled=true
server.jetty.accesslog.filename=/var/log/jetty-access.logBy default, logs are redirected to System.err. For more details, see the Jetty documentation.
3.12. Running Behind a Front-end Proxy Server
If your application is running behind a proxy, a load-balancer or in the cloud, the request information (like the host, port, scheme…) might change along the way. Your application may be running on 10.10.10.10:8080, but HTTP clients should only see example.org.
RFC7239 "Forwarded Headers" defines the Forwarded HTTP header; proxies can use this header to provide information about the original request. You can configure your application to read those headers and automatically use that information when creating links and sending them to clients in HTTP 302 responses, JSON documents or HTML pages. There are also non-standard headers, like X-Forwarded-Host, X-Forwarded-Port, X-Forwarded-Proto, X-Forwarded-Ssl, and X-Forwarded-Prefix.
If the proxy adds the commonly used X-Forwarded-For and X-Forwarded-Proto headers, setting server.forward-headers-strategy to NATIVE is enough to support those. With this option, the Web servers themselves natively support this feature; you can check their specific documentation to learn about specific behavior.
If this is not enough, Spring Framework provides a ForwardedHeaderFilter for the servlet stack and a ForwardedHeaderTransformer for the reactive stack. You can use them in your application by setting server.forward-headers-strategy to FRAMEWORK.
Note:If you are using Tomcat and terminating SSL at the proxy,
server.tomcat.redirect-context-rootshould be set tofalse. This allows theX-Forwarded-Protoheader to be honored before any redirects are performed.
Tip:If your application runs in Cloud Foundry, Heroku or Kubernetes, the
server.forward-headers-strategyproperty defaults toNATIVE. In all other instances, it defaults toNONE.
3.12.1. Customize Tomcat’s Proxy Configuration
If you use Tomcat, you can additionally configure the names of the headers used to carry “forwarded” information, as shown in the following example:
Properties
server.tomcat.remoteip.remote-ip-header=x-your-remote-ip-header
server.tomcat.remoteip.protocol-header=x-your-protocol-headerTomcat is also configured with a regular expression that matches internal proxies that are to be trusted. See the server.tomcat.remoteip.internal-proxies entry in the appendix for its default value. You can customize the valve’s configuration by adding an entry to application.properties, as shown in the following example:
Properties
server.tomcat.remoteip.internal-proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}Tip:You can trust all proxies by setting the
internal-proxiesto empty (but do not do so in production).
You can take complete control of the configuration of Tomcat’s RemoteIpValve by switching the automatic one off (to do so, set server.forward-headers-strategy=NONE) and adding a new valve instance using a WebServerFactoryCustomizer bean.
3.13. Enable Multiple Connectors with Tomcat
You can add an org.apache.catalina.connector.Connector to the TomcatServletWebServerFactory, which can allow multiple connectors, including HTTP and HTTPS connectors, as shown in the following example:
Java
import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyTomcatConfiguration {
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> connectorCustomizer() {
return (tomcat) -> tomcat.addAdditionalTomcatConnectors(createConnector());
}
private Connector createConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(8081);
return connector;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
3.14. Use Tomcat’s LegacyCookieProcessor
By default, the embedded Tomcat used by Spring Boot does not support "Version 0" of the Cookie format, so you may see the following error:
Text
java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie valueIf at all possible, you should consider updating your code to only store values compliant with later Cookie specifications. If, however, you cannot change the way that cookies are written, you can instead configure Tomcat to use a LegacyCookieProcessor. To switch to the LegacyCookieProcessor, use an WebServerFactoryCustomizer bean that adds a TomcatContextCustomizer, as shown in the following example:
Java
import org.apache.tomcat.util.http.LegacyCookieProcessor;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyLegacyCookieProcessorConfiguration {
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
return (factory) -> factory
.addContextCustomizers((context) -> context.setCookieProcessor(new LegacyCookieProcessor()));
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
3.15. Enable Tomcat’s MBean Registry
Embedded Tomcat’s MBean registry is disabled by default. This minimizes Tomcat’s memory footprint. If you want to use Tomcat’s MBeans, for example so that they can be used by Micrometer to expose metrics, you must use the server.tomcat.mbeanregistry.enabled property to do so, as shown in the following example:
Properties
server.tomcat.mbeanregistry.enabled=true3.16. Enable Multiple Listeners with Undertow
Add an UndertowBuilderCustomizer to the UndertowServletWebServerFactory and add a listener to the Builder, as shown in the following example:
Java
import io.undertow.Undertow.Builder;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyUndertowConfiguration {
@Bean
public WebServerFactoryCustomizer<UndertowServletWebServerFactory> undertowListenerCustomizer() {
return (factory) -> factory.addBuilderCustomizers(this::addHttpListener);
}
private Builder addHttpListener(Builder builder) {
return builder.addHttpListener(8080, "0.0.0.0");
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
3.17. 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, as shown in the following example:
Java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration(proxyBeanMethods = false)
public class MyWebSocketConfiguration {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
The bean shown in the preceding example registers 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.
4. Spring MVC
Spring Boot has a number of starters that include Spring MVC. Note that some starters include a dependency on Spring MVC rather than include it directly. This section answers common questions about Spring MVC and Spring Boot.
4.1. 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, as shown in the following example:
Java
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@RequestMapping("/thing")
public MyThing thing() {
return new MyThing();
}
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
As long as MyThing can be serialized by Jackson2 (true for a normal POJO or Groovy object), then localhost:8080/thing serves a JSON representation of it by default. Note that, in a browser, you might sometimes see XML responses, because browsers tend to send accept headers that prefer XML.
4.2. Write an XML REST Service
If you have the Jackson XML extension (jackson-dataformat-xml) on the classpath, you can use it to render XML responses. The previous example that we used for JSON would work. To use the Jackson XML renderer, add the following dependency to your project:
XML
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>If Jackson’s XML extension is not available and JAXB is available, XML can be rendered with the additional requirement of having MyThing annotated as @XmlRootElement, as shown in the following example:
Java
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class MyThing {
private String name;
// getters/setters ...
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
JAXB is only available out of the box with Java 8. If you use a more recent Java generation, add the following dependency to your project:
XML
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>Tip:To get the server to render XML instead of JSON, you might have to send an
Accept: text/xmlheader (or use a browser).
4.3. 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_INCLUSIONis disabledDeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIESis disabledSerializationFeature.WRITE_DATES_AS_TIMESTAMPSis disabledSerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPSis disabled
Spring Boot also has some features to make it easier to customize this behavior.
You can configure the ObjectMapper and XmlMapper instances by using the environment. Jackson provides an extensive suite of on/off features that can be used to configure various aspects of its processing. These features are described in six enums (in Jackson) that map onto properties in the environment:
| Enum | Property | Values |
|---|---|---|
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.default-property-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 relaxed binding, the case of indent_output does not 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 applies to any mappers created by 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 (Boot’s own customizer has an order of 0), letting additional customization be applied both before and after Boot’s customization.
Any beans of type com.fasterxml.jackson.databind.Module are automatically registered with the auto-configured Jackson2ObjectMapperBuilder and are 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, doing so disables all auto-configuration of the ObjectMapper.
If you provide any @Beans of type MappingJackson2HttpMessageConverter, they replace the default value in the MVC configuration. Also, a convenience bean of type HttpMessageConverters is provided (and is always available if you use the default MVC configuration). It has some useful methods to access the default and user-enhanced message converters.
See the “Customize the @ResponseBody Rendering” section and the WebMvcAutoConfiguration source code for more details.
4.4. Customize the @ResponseBody Rendering
Spring uses HttpMessageConverters to render @ResponseBody (or responses from @RestController). You can contribute additional converters by adding beans of the appropriate type in a Spring Boot context. If a bean you add is of a type that would have been included by default anyway (such as MappingJackson2HttpMessageConverter for JSON conversions), it replaces the default value. A convenience bean of type HttpMessageConverters is provided and is always available if you use the default MVC configuration. It has some useful methods to access the default and user-enhanced message converters (For example, it can be useful if you want to manually inject them into a custom RestTemplate).
As in normal MVC usage, any WebMvcConfigurer beans that you provide can also contribute converters by overriding the configureMessageConverters method. However, 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, you can take control completely and do everything manually by using getMessageConverters from WebMvcConfigurationSupport.
See the WebMvcAutoConfiguration source code for more details.
4.5. 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 size of 1MB per file and a maximum of 10MB of file data in a single request. You may override these values, the location to which intermediate data is stored (for example, to the /tmp directory), and the threshold past which data is flushed to disk by using the properties exposed in the MultipartProperties class. For example, if you want to specify that files be unlimited, set the spring.servlet.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 MultipartAutoConfiguration source for more details.
Tip:It is recommended to use the container’s built-in support for multipart uploads rather than introducing an additional dependency such as Apache Commons File Upload.
4.6. Switch Off the Spring MVC DispatcherServlet
By default, all content is served from the root of your application (/). If you would rather map to a different path, you can configure one as follows:
Properties
spring.mvc.servlet.path=/mypathIf you have additional servlets you can declare a @Bean of type Servlet or ServletRegistrationBean for each and Spring Boot will register them transparently to the container. Because servlets are registered that way, they can be mapped to a sub-context of the DispatcherServlet without invoking it.
Configuring the DispatcherServlet yourself is unusual but if you really need to do it, a @Bean of type DispatcherServletPath must be provided as well to provide the path of your custom DispatcherServlet.
4.7. 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. Doing so leaves all MVC configuration in your hands.
4.8. 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. If you add 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
InternalResourceViewResolvernamed ‘defaultViewResolver’. This one locates physical resources that can be rendered by using theDefaultServlet(including static resources and JSP pages, if you use 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 (the defaults are both empty but are accessible for external configuration throughspring.mvc.view.prefixandspring.mvc.view.suffix). You can override it by providing a bean of the same type.A
BeanNameViewResolvernamed ‘beanNameViewResolver’. This is a useful member of the view resolver chain and picks up any beans with the same name as theViewbeing resolved. It should not be necessary to override or replace it.A
ContentNegotiatingViewResolvernamed ‘viewResolver’ is added only if there are actually beans of typeViewpresent. This is a composite 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 blog aboutContentNegotiatingViewResolverthat you might like to study to learn more, and you might also look at the source code for detail. You can switch off the auto-configuredContentNegotiatingViewResolverby defining a bean named ‘viewResolver’.If you use Thymeleaf, you also have a
ThymeleafViewResolvernamed ‘thymeleafViewResolver’. It looks for resources by surrounding the view name with a prefix and suffix. The prefix isspring.thymeleaf.prefix, and the suffix isspring.thymeleaf.suffix. The values of the prefix and suffix default to ‘classpath:/templates/’ and ‘.html’, respectively. You can overrideThymeleafViewResolverby providing a bean of the same name.If you use FreeMarker, you also have a
FreeMarkerViewResolvernamed ‘freeMarkerViewResolver’. It looks for resources in a loader path (which is externalized tospring.freemarker.templateLoaderPathand has a default value of ‘classpath:/templates/’) by surrounding the view name with a prefix and a suffix. The prefix is externalized tospring.freemarker.prefix, and the suffix is externalized tospring.freemarker.suffix. The default values of the prefix and suffix are empty and ‘.ftlh’, respectively. You can overrideFreeMarkerViewResolverby providing a bean of the same name.If you use Groovy templates (actually, if
groovy-templatesis on your classpath), you also have aGroovyMarkupViewResolvernamed ‘groovyMarkupViewResolver’. It looks for resources in a loader path by surrounding the view name with a prefix and suffix (externalized tospring.groovy.template.prefixandspring.groovy.template.suffix). The prefix and suffix have default values of ‘classpath:/templates/’ and ‘.tpl’, respectively. You can overrideGroovyMarkupViewResolverby providing a bean of the same name.If you use Mustache, you also have a
MustacheViewResolvernamed ‘mustacheViewResolver’. It looks for resources by surrounding the view name with a prefix and suffix. The prefix isspring.mustache.prefix, and the suffix isspring.mustache.suffix. The values of the prefix and suffix default to ‘classpath:/templates/’ and ‘.mustache’, respectively. You can overrideMustacheViewResolverby providing a bean of the same name.
For more detail, see the following sections:
WebMvcAutoConfigurationThymeleafAutoConfigurationFreeMarkerAutoConfigurationGroovyTemplateAutoConfiguration
5. Jersey
5.1. Secure Jersey endpoints with Spring Security
Spring Security can be used to secure a Jersey-based web application in much the same way as it can be used to secure a Spring MVC-based web application. However, if you want to use Spring Security’s method-level security with Jersey, you must configure Jersey to use setStatus(int) rather sendError(int). This prevents Jersey from committing the response before Spring Security has had an opportunity to report an authentication or authorization failure to the client.
The jersey.config.server.response.setStatusOverSendError property must be set to true on the application’s ResourceConfig bean, as shown in the following example:
Java
import java.util.Collections;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;
@Component
public class JerseySetStatusOverSendErrorConfig extends ResourceConfig {
public JerseySetStatusOverSendErrorConfig() {
register(Endpoint.class);
setProperties(Collections.singletonMap("jersey.config.server.response.setStatusOverSendError", true));
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
5.2. Use Jersey Alongside Another Web Framework
To use Jersey alongside another web framework, such as Spring MVC, it should be configured so that it will allow the other framework to handle requests that it cannot handle. First, configure Jersey to use a filter rather than a servlet by configuring the spring.jersey.type application property with a value of filter. Second, configure your ResourceConfig to forward requests that would have resulted in a 404, as shown in the following example.
Java
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletProperties;
import org.springframework.stereotype.Component;
@Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(Endpoint.class);
property(ServletProperties.FILTER_FORWARD_ON_404, true);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
6. HTTP Clients
Spring Boot offers a number of starters that work with HTTP clients. This section answers questions related to using them.
6.1. Configure RestTemplate to Use a Proxy
As described in RestTemplate Customization, you can use a RestTemplateCustomizer 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.
6.2. Configure the TcpClient used by a Reactor Netty-based WebClient
When Reactor Netty is on the classpath a Reactor Netty-based WebClient is auto-configured. To customize the client’s handling of network connections, provide a ClientHttpConnector bean. The following example configures a 60 second connect timeout and adds a ReadTimeoutHandler:
Java
import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import reactor.netty.http.client.HttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.client.reactive.ReactorResourceFactory;
@Configuration(proxyBeanMethods = false)
public class MyReactorNettyClientConfiguration {
@Bean
ClientHttpConnector clientHttpConnector(ReactorResourceFactory resourceFactory) {
HttpClient httpClient = HttpClient.create(resourceFactory.getConnectionProvider())
.runOn(resourceFactory.getLoopResources())
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60000)
.doOnConnected((connection) -> connection.addHandlerLast(new ReadTimeoutHandler(60)));
return new ReactorClientHttpConnector(httpClient);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Note:Note the use of
ReactorResourceFactoryfor the connection provider and event loop resources. This ensures efficient sharing of resources for the server receiving requests and the client making requests.
7. Logging
Spring Boot has no mandatory logging dependency, except for the Commons Logging API, which is typically provided by Spring Framework’s spring-jcl module. To use Logback, you need to include it and spring-jcl on the classpath. The recommended way to do that is through the starters, which all depend on spring-boot-starter-logging. For a web application, you need only spring-boot-starter-web, since it depends transitively on the logging starter. If you use Maven, the following dependency adds logging for you:
XML
<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, you can do so in application.properties by using the "logging.level" prefix, as shown in the following example:
Properties
logging.level.org.springframework.web=debug
logging.level.org.hibernate=errorYou can also set the location of a file to which to write the log (in addition to the console) by using logging.file.name.
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 (such as classpath:logback.xml for Logback), but you can set the location of the config file by using the logging.config property.
7.1. Configure Logback for Logging
If you need to apply customizations to logback beyond those that can be achieved with application.properties, you will need to add a standard logback configuration file. You can add a logback.xml file to the root of your classpath for logback to find. You can also use logback-spring.xml if you want to use the Spring Boot Logback extensions.
Note:The Logback documentation has a dedicated section that covers configuration in some detail.
Spring Boot provides a number of logback configurations that can be included in your own configuration. These includes are designed to allow certain common Spring Boot conventions to be re-applied.
The following files are provided under org/springframework/boot/logging/logback/:
defaults.xml- Provides conversion rules, pattern properties and common logger configurations.console-appender.xml- Adds aConsoleAppenderusing theCONSOLE_LOG_PATTERN.file-appender.xml- Adds aRollingFileAppenderusing theFILE_LOG_PATTERNandROLLING_FILE_NAME_PATTERNwith appropriate settings.
In addition, a legacy base.xml file is provided for compatibility with earlier versions of Spring Boot.
A typical custom logback.xml file would look something like this:
XML
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
<logger name="org.springframework.web" level="DEBUG"/>
</configuration>Your logback configuration file can also make use of System properties that the LoggingSystem takes care of creating for you:
${PID}: The current process ID.${LOG_FILE}: Whetherlogging.file.namewas set in Boot’s external configuration.${LOG_PATH}: Whetherlogging.file.path(representing a directory for log files to live in) was set in Boot’s external configuration.${LOG_EXCEPTION_CONVERSION_WORD}: Whetherlogging.exception-conversion-wordwas set in Boot’s external configuration.${ROLLING_FILE_NAME_PATTERN}: Whetherlogging.pattern.rolling-file-namewas set in Boot’s external configuration.
Spring Boot also provides some nice ANSI color terminal output on a console (but not in a log file) by using a custom Logback converter. See the CONSOLE_LOG_PATTERN in the defaults.xml configuration for an example.
If Groovy is on the classpath, you should be able to configure Logback with logback.groovy as well. If present, this setting is given preference.
Tip:Spring extensions are not supported with Groovy configuration. Any
logback-spring.groovyfiles will not be detected.
7.1.1. 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, as shown in the following example:
XML
<?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.name to your application.properties or application.yaml, as shown in the following example:
Properties
logging.file.name=myapplication.log7.2. Configure Log4j for Logging
Spring Boot supports Log4j 2 for logging configuration if it is on the classpath. If you use the starters for assembling dependencies, you have to exclude Logback and then include log4j 2 instead. If you do not use the starters, you need to provide (at least) spring-jcl in addition to Log4j 2.
The recommended path is through the starters, even though it requires some jiggling. The following example shows how to set up the starters in Maven:
XML
<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>Gradle provides a few different ways to set up the starters. One way is to use a module replacement. To do so, declare a dependency on the Log4j 2 starter and tell Gradle that any occurrences of the default logging starter should be replaced by the Log4j 2 starter, as shown in the following example:
Gradle
dependencies {
implementation "org.springframework.boot:spring-boot-starter-log4j2"
modules {
module("org.springframework.boot:spring-boot-starter-logging") {
replacedBy("org.springframework.boot:spring-boot-starter-log4j2", "Use Log4j2 instead of Logback")
}
}
}Tip:The Log4j starters gather together the dependencies for common logging requirements (such as having Tomcat use
java.util.loggingbut configuring the output using Log4j 2).
Tip:To ensure that debug logging performed using
java.util.loggingis routed into Log4j 2, configure its JDK logging adapter by setting thejava.util.logging.managersystem property toorg.apache.logging.log4j.jul.LogManager.
7.2.1. 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, as shown in the following example:
| Format | Dependencies | File names |
|---|---|---|
| YAML | com.fasterxml.jackson.core:jackson-databind + com.fasterxml.jackson.dataformat:jackson-dataformat-yaml | log4j2.yaml + log4j2.yml |
| JSON | com.fasterxml.jackson.core:jackson-databind | log4j2.json + log4j2.jsn |
7.2.2. Use Composite Configuration to Configure Log4j 2
Log4j 2 has support for combining multiple configuration files into a single composite configuration. To use this support in Spring Boot, configure logging.log4j2.config.override with the locations of one or more secondary configuration files. The secondary configuration files will be merged with the primary configuration, whether the primary’s source is Spring Boot’s defaults, a standard location such as log4j.xml, or the location configured by the logging.config property.
Next section: Data Access.