Spring Boot Reference
Spring Boot Reference
Phillip Webb, Dave Syer, Josh Long, Stéphane Nicoll, Rob Winch, Andy
Wilkinson, Marcel Overdijk, Christian Dupuis, Sébastien Deleuze, Michael
Simons, Vedran Pavić, Jay Bryant, Madhura Bhave, Eddú Meléndez, Scott
Frederick
3.0.0-SNAPSHOT
Table of Contents
1. Legal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Getting Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3. Documentation Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3.5. Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.6. Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.7. Messaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.8. IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
4. Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Maven Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Gradle Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Manual Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
MacPorts Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Command-line Completion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6.1.2. Maven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.1.3. Gradle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
6.1.4. Ant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
6.1.5. Starters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
6.4. Auto-configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Excluding Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Disabling Restart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Known Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
6.8.4. LiveReload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Remote Update. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7. Core Features. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
7.1. SpringApplication. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Liveness State. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Readiness State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Wildcard Locations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Property Placeholders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Activation Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Constructor binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Third-party Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Relaxed Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Properties Conversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
@ConfigurationProperties Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
7.3. Profiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
ConfigDataApplicationContextInitializer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
TestPropertyValues. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
OutputCapture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
TestRestTemplate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
runApplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Extensions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
8. Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
HttpMessageConverters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
MessageCodesResolver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
ConfigurableWebBindingInitializer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
9. Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
MongoTemplate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
11. IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
Generic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
Hazelcast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Couchbase. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Redis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Caffeine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
Simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
None . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
OS Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
AppOptics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
Atlas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
Datadog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
Dynatrace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
Elastic. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
Ganglia. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
Graphite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
Humio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
Influx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
JMX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
KairosDB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Prometheus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
SignalFx. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
Simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
Stackdriver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
StatsD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
Wavefront. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
Examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
Examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
17.11.1. Change the HTTP Port or Address of the Actuator Endpoints . . . . . . . . . . . . . . . . . . . . . . 463
17.15.8. Remote Debug a Spring Boot Application Started with Maven. . . . . . . . . . . . . . . . . . . . . 476
17.15.9. Build an Executable Archive from Ant without Using spring-boot-antlib . . . . . . . . . . . 476
Appendices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
Any . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614
Handle As . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615
B.3. Generating Your Own Metadata by Using the Annotation Processor . . . . . . . . . . . . . . . . . . . . . 619
1
Chapter 1. Legal
Copyright © 2012-2022
Copies of this document may be made for your own use and for distribution to others, provided
that you do not charge any fee for such copies and further provided that each copy contains this
Copyright Notice, whether distributed in print or electronically.
2
Chapter 2. Getting Help
If you have trouble with Spring Boot, we would like to help.
• Try the How-to documents. They provide solutions to the most common questions.
• Learn the Spring basics. Spring Boot builds on many other Spring projects. Check the spring.io
web-site for a wealth of reference documentation. If you are starting out with Spring, try one of
the guides.
All of Spring Boot is open source, including the documentation. If you find problems
NOTE
with the docs or if you want to improve them, please get involved.
3
Chapter 3. Documentation Overview
This section provides a brief overview of Spring Boot reference documentation. It serves as a map
for the rest of the document.
Depending on the version that you are upgrading to, you can find some additional tips here:
• Profiles: Profiles
4
• Logging: Logging
3.5. Web
If you develop Spring Boot web applications, take a look at the following content:
3.6. Data
If your application deals with a datastore, you can see how to configure that here:
• SQL: Configuring a SQL Datastore, Embedded Database support, Connection pools, and more.
• NOSQL: Auto-configuration for NOSQL stores such as Redis, MongoDB, Neo4j, and others.
3.7. Messaging
If your application uses any messaging protocol, see one or more of the following sections:
• JMS: Auto-configuration for ActiveMQ and Artemis, Sending and Receiving messages through
JMS
3.8. IO
If your application needs IO capabilities, see one or more of the following sections:
5
• JTA: Distributed Transactions with JTA
• Efficient Container Images: Tips to optimize container images such as Docker images
• Cloud Native Buildpacks: Support for Cloud Native Buildpacks with Maven and Gradle
6
Chapter 4. Getting Started
If you are getting started with Spring Boot, or “Spring” in general, start by reading this section. It
answers the basic “what?”, “how?” and “why?” questions. It includes an introduction to Spring
Boot, along with installation instructions. We then walk you through building your first Spring Boot
application, discussing some core principles as we go.
You can use Spring Boot to create Java applications that can be started by using java -jar or more
traditional war deployments. We also provide a command line tool that runs “spring scripts”.
• Provide a radically faster and widely accessible getting-started experience for all Spring
development.
• Be opinionated out of the box but get out of the way quickly as requirements start to diverge
from the defaults.
• Provide a range of non-functional features that are common to large classes of projects (such as
embedded servers, security, metrics, health checks, and externalized configuration).
Maven 3.5+
7
Name Servlet Version
You can also deploy Spring Boot applications to any servlet 5.0+ compatible container.
$ java -version
If you are new to Java development or if you want to experiment with Spring Boot, you might want
to try the Spring Boot CLI (Command Line Interface) first. Otherwise, read on for “classic”
installation instructions.
You can use Spring Boot in the same way as any standard Java library. To do so, include the
appropriate spring-boot-*.jar files on your classpath. Spring Boot does not require any special
tools integration, so you can use any IDE or text editor. Also, there is nothing special about a Spring
Boot application, so you can run and debug a Spring Boot application as you would any other Java
program.
Although you could copy Spring Boot jars, we generally recommend that you use a build tool that
supports dependency management (such as Maven or Gradle).
Maven Installation
Spring Boot is compatible with Apache Maven 3.3 or above. If you do not already have Maven
installed, you can follow the instructions at maven.apache.org.
On many operating systems, Maven can be installed with a package manager. If you
use OSX Homebrew, try brew install maven. Ubuntu users can run sudo apt-get
TIP
install maven. Windows users with Chocolatey can run choco install maven from an
elevated (administrator) prompt.
Spring Boot dependencies use the org.springframework.boot groupId. Typically, your Maven POM file
inherits from the spring-boot-starter-parent project and declares dependencies to one or more
“Starters”. Spring Boot also provides an optional Maven plugin to create executable jars.
More details on getting started with Spring Boot and Maven can be found in the Getting Started
section of the Maven plugin’s reference guide.
8
Gradle Installation
Spring Boot is compatible with Gradle 7.x (7.3 or later). If you do not already have Gradle installed,
you can follow the instructions at gradle.org.
Spring Boot dependencies can be declared by using the org.springframework.boot group. Typically,
your project declares dependencies to one or more “Starters”. Spring Boot provides a useful Gradle
plugin that can be used to simplify dependency declarations and to create executable jars.
Gradle Wrapper
The Gradle Wrapper provides a nice way of “obtaining” Gradle when you need to build a
project. It is a small script and library that you commit alongside your code to bootstrap the
build process. See docs.gradle.org/current/userguide/gradle_wrapper.html for details.
More details on getting started with Spring Boot and Gradle can be found in the Getting Started
section of the Gradle plugin’s reference guide.
The Spring Boot CLI (Command Line Interface) is a command line tool that you can use to quickly
prototype with Spring. It lets you run Groovy scripts, which means that you have a familiar Java-
like syntax without so much boilerplate code.
You do not need to use the CLI to work with Spring Boot, but it is a quick way to get a Spring
application off the ground without an IDE.
Manual Installation
You can download the Spring CLI distribution from the Spring software repository:
• spring-boot-cli-3.0.0-SNAPSHOT-bin.zip
• spring-boot-cli-3.0.0-SNAPSHOT-bin.tar.gz
Once downloaded, follow the INSTALL.txt instructions from the unpacked archive. In summary,
there is a spring script (spring.bat for Windows) in a bin/ directory in the .zip file. Alternatively,
you can use java -jar with the .jar file (the script helps you to be sure that the classpath is set
correctly).
SDKMAN! (The Software Development Kit Manager) can be used for managing multiple versions of
various binary SDKs, including Groovy and the Spring Boot CLI. Get SDKMAN! from sdkman.io and
install Spring Boot by using the following commands:
9
$ sdk install springboot
$ spring --version
Spring CLI v3.0.0-SNAPSHOT
If you develop features for the CLI and want access to the version you built, use the following
commands:
The preceding instructions install a local instance of spring called the dev instance. It points at your
target build location, so every time you rebuild Spring Boot, spring is up-to-date.
$ sdk ls springboot
================================================================================
Available Springboot Versions
================================================================================
> + dev
* 3.0.0-SNAPSHOT
================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
If you are on a Mac and use Homebrew, you can install the Spring Boot CLI by using the following
commands:
If you do not see the formula, your installation of brew might be out-of-date. In that
NOTE
case, run brew update and try again.
10
MacPorts Installation
If you are on a Mac and use MacPorts, you can install the Spring Boot CLI by using the following
command:
Command-line Completion
The Spring Boot CLI includes scripts that provide command completion for the BASH and zsh shells.
You can source the script (also named spring) in any shell or put it in your personal or system-wide
bash completion initialization. On a Debian system, the system-wide scripts are in /shell-
completion/bash and all scripts in that directory are executed when a new shell starts. For example,
to run the script manually if you have installed by using SDKMAN!, use the following commands:
$ . ~/.sdkman/candidates/springboot/current/shell-completion/bash/spring
$ spring <HIT TAB HERE>
grab help jar run test version
If you install the Spring Boot CLI by using Homebrew or MacPorts, the command-
NOTE
line completion scripts are automatically registered with your shell.
If you are on a Windows and use Scoop, you can install the Spring Boot CLI by using the following
commands:
If you do not see the app manifest, your installation of scoop might be out-of-date.
NOTE
In that case, run scoop update and try again.
You can use the following web application to test your installation. To start, create a file called
app.groovy, as follows:
11
@RestController
class ThisWillActuallyRun {
@RequestMapping("/")
String home() {
"Hello World!"
}
Open localhost:8080 in your favorite web browser. You should see the following output:
Hello World!
The spring.io web site contains many “Getting Started” guides that use Spring Boot. If
you need to solve a specific problem, check there first.
TIP You can shortcut the steps below by going to start.spring.io and choosing the "Web"
starter from the dependencies searcher. Doing so generates a new project structure so
that you can start coding right away. Check the start.spring.io user guide for more
details.
Before we begin, open a terminal and run the following commands to ensure that you have valid
versions of Java and Maven installed:
$ java -version
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)
12
$ mvn -v
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T14:33:14-
04:00)
Maven home: /usr/local/Cellar/maven/3.3.9/libexec
Java version: 1.8.0_102, vendor: Oracle Corporation
We need to start by creating a Maven pom.xml file. The pom.xml is the recipe that is used to build your
project. Open your favorite text editor and add the following:
13
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<!-- (you do not need this if you are using a .RELEASE version) -->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>https://repo.spring.io/snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>https://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
The preceding listing should give you a working build. You can test it by running mvn package (for
now, you can ignore the “jar will be empty - no content was marked for inclusion!” warning).
At this point, you could import the project into an IDE (most modern Java IDEs
NOTE include built-in support for Maven). For simplicity, we continue to use a plain text
editor for this example.
14
4.4.2. Adding Classpath Dependencies
Spring Boot provides a number of “Starters” that let you add jars to your classpath. Our
applications for smoke tests use the spring-boot-starter-parent in the parent section of the POM.
The spring-boot-starter-parent is a special starter that provides useful Maven defaults. It also
provides a dependency-management section so that you can omit version tags for “blessed”
dependencies.
Other “Starters” provide dependencies that you are likely to need when developing a specific type
of application. Since we are developing a web application, we add a spring-boot-starter-web
dependency. Before that, we can look at what we currently have by running the following
command:
$ mvn dependency:tree
[INFO] com.example:myproject:jar:0.0.1-SNAPSHOT
The mvn dependency:tree command prints a tree representation of your project dependencies. You
can see that spring-boot-starter-parent provides no dependencies by itself. To add the necessary
dependencies, edit your pom.xml and add the spring-boot-starter-web dependency immediately
below the parent section:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
If you run mvn dependency:tree again, you see that there are now a number of additional
dependencies, including the Tomcat web server and Spring Boot itself.
To finish our application, we need to create a single Java file. By default, Maven compiles sources
from src/main/java, so you need to create that directory structure and then add a file named
src/main/java/MyApplication.java to contain the following code:
15
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@EnableAutoConfiguration
public class MyApplication {
@RequestMapping("/")
String home() {
return "Hello World!";
}
Although there is not much code here, quite a lot is going on. We step through the important parts
in the next few sections.
The first annotation on our MyApplication class is @RestController. This is known as a stereotype
annotation. It provides hints for people reading the code and for Spring that the class plays a
specific role. In this case, our class is a web @Controller, so Spring considers it when handling
incoming web requests.
The @RequestMapping annotation provides “routing” information. It tells Spring that any HTTP
request with the / path should be mapped to the home method. The @RestController annotation tells
Spring to render the resulting string directly back to the caller.
The second class-level annotation is @EnableAutoConfiguration. This annotation tells Spring Boot to
“guess” how you want to configure Spring, based on the jar dependencies that you have added.
Since spring-boot-starter-web added Tomcat and Spring MVC, the auto-configuration assumes that
you are developing a web application and sets up Spring accordingly.
16
Starters and Auto-configuration
Auto-configuration is designed to work well with “Starters”, but the two concepts are not
directly tied. You are free to pick and choose jar dependencies outside of the starters. Spring
Boot still does its best to auto-configure your application.
The final part of our application is the main method. This is a standard method that follows the Java
convention for an application entry point. Our main method delegates to Spring Boot’s
SpringApplication class by calling run. SpringApplication bootstraps our application, starting Spring,
which, in turn, starts the auto-configured Tomcat web server. We need to pass MyApplication.class
as an argument to the run method to tell SpringApplication which is the primary Spring component.
The args array is also passed through to expose any command-line arguments.
At this point, your application should work. Since you used the spring-boot-starter-parent POM,
you have a useful run goal that you can use to start the application. Type mvn spring-boot:run from
the root project directory to start the application. You should see output similar to the following:
$ mvn spring-boot:run
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.0-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started MyApplication in 2.222 seconds (JVM running for 6.514)
If you open a web browser to localhost:8080, you should see the following output:
Hello World!
We finish our example by creating a completely self-contained executable jar file that we could run
in production. Executable jars (sometimes called “fat jars”) are archives containing your compiled
classes along with all of the jar dependencies that your code needs to run.
17
Executable jars and Java
Java does not provide a standard way to load nested jar files (jar files that are themselves
contained within a jar). This can be problematic if you are looking to distribute a self-
contained application.
To solve this problem, many developers use “uber” jars. An uber jar packages all the classes
from all the application’s dependencies into a single archive. The problem with this approach
is that it becomes hard to see which libraries are in your application. It can also be
problematic if the same filename is used (but with different content) in multiple jars.
Spring Boot takes a different approach and lets you actually nest jars directly.
To create an executable jar, we need to add the spring-boot-maven-plugin to our pom.xml. To do so,
insert the following lines just below the dependencies section:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Save your pom.xml and run mvn package from the command line, as follows:
18
$ mvn package
If you look in the target directory, you should see myproject-0.0.1-SNAPSHOT.jar. The file should be
around 10 MB in size. If you want to peek inside, you can use jar tvf, as follows:
You should also see a much smaller file named myproject-0.0.1-SNAPSHOT.jar.original in the target
directory. This is the original jar file that Maven created before it was repackaged by Spring Boot.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.0-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started MyApplication in 2.536 seconds (JVM running for 2.864)
19
your own applications. If you are a task-oriented type of developer, you might want to jump over to
spring.io and follow some of the getting started guides that solve specific “How do I do that with
Spring?” problems. We also have Spring Boot-specific “How-to” reference documentation.
Otherwise, the next logical step is to read Developing with Spring Boot. If you are really impatient,
you could also jump ahead and read about Spring Boot features.
20
Chapter 5. Upgrading Spring Boot
Instructions for how to upgrade from earlier versions of Spring Boot are provided on the project
wiki. Follow the links in the release notes section to find the version that you want to upgrade to.
Upgrading instructions are always the first item in the release notes. If you are more than one
release behind, please make sure that you also review the release notes of the versions that you
jumped.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId>
<scope>runtime</scope>
</dependency>
Properties that are added late to the environment, such as when using
WARNING
@PropertySource, will not be taken into account.
Once you finish the migration, please make sure to remove this module from your
NOTE
project’s dependencies.
21
Spring Boot’s documentation is specific to that version, so any information that you find in here
will contain the most up-to-date changes that are in that version.
22
Chapter 6. Developing with Spring Boot
This section goes into more detail about how you should use Spring Boot. It covers topics such as
build systems, auto-configuration, and how to run your applications. We also cover some Spring
Boot best practices. Although there is nothing particularly special about Spring Boot (it is just
another library that you can consume), there are a few recommendations that, when followed,
make your development process a little easier.
If you are starting out with Spring Boot, you should probably read the Getting Started guide before
diving into this section.
Each release of Spring Boot provides a curated list of dependencies that it supports. In practice, you
do not need to provide a version for any of these dependencies in your build configuration, as
Spring Boot manages that for you. When you upgrade Spring Boot itself, these dependencies are
upgraded as well in a consistent way.
You can still specify a version and override Spring Boot’s recommendations if you
NOTE
need to do so.
The curated list contains all the Spring modules that you can use with Spring Boot as well as a
refined list of third party libraries. The list is available as a standard Bills of Materials (spring-boot-
dependencies) that can be used with both Maven and Gradle.
Each release of Spring Boot is associated with a base version of the Spring
WARNING
Framework. We highly recommend that you not specify its version.
6.1.2. Maven
To learn about using Spring Boot with Maven, see the documentation for Spring Boot’s Maven
plugin:
• API
6.1.3. Gradle
To learn about using Spring Boot with Gradle, see the documentation for Spring Boot’s Gradle
plugin:
23
• Reference (HTML and PDF)
• API
6.1.4. Ant
It is possible to build a Spring Boot project using Apache Ant+Ivy. The spring-boot-antlib “AntLib”
module is also available to help Ant create executable jars.
To declare dependencies, a typical ivy.xml file looks something like the following example:
<ivy-module version="2.0">
<info organisation="org.springframework.boot" module="spring-boot-sample-ant" />
<configurations>
<conf name="compile" description="everything needed to compile this module" />
<conf name="runtime" extends="compile" description="everything needed to run
this module" />
</configurations>
<dependencies>
<dependency org="org.springframework.boot" name="spring-boot-starter"
rev="${spring-boot.version}" conf="compile" />
</dependencies>
</ivy-module>
24
<project
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="myapp" default="build">
If you do not want to use the spring-boot-antlib module, see the Build an Executable
TIP
Archive from Ant without Using spring-boot-antlib “How-to” .
6.1.5. Starters
Starters are a set of convenient dependency descriptors that you can include in your application.
You get a one-stop shop for all the Spring and related technologies that you need without having to
hunt through sample code and copy-paste loads of dependency descriptors. For example, if you
want to get started using Spring and JPA for database access, include the spring-boot-starter-data-
jpa dependency in your project.
The starters contain a lot of the dependencies that you need to get a project up and running quickly
and with a consistent, supported set of managed transitive dependencies.
25
What is in a name
As explained in the “Creating Your Own Starter” section, third party starters should not start
with spring-boot, as it is reserved for official Spring Boot artifacts. Rather, a third-party
starter typically starts with the name of the project. For example, a third-party starter project
called thirdpartyproject would typically be named thirdpartyproject-spring-boot-starter.
The following application starters are provided by Spring Boot under the org.springframework.boot
group:
Name Description
26
Name Description
27
Name Description
In addition to the application starters, the following starters can be used to add production ready
features:
Name Description
Finally, Spring Boot also includes the following starters that can be used if you want to exclude or
swap specific technical facets:
Name Description
28
Name Description
To learn how to swap technical facets, please see the how-to documentation for swapping web
server and logging system.
For a list of additional community contributed starters, see the README file in the
TIP
spring-boot-starters module on GitHub.
When a class does not include a package declaration, it is considered to be in the “default package”.
The use of the “default package” is generally discouraged and should be avoided. It can cause
particular problems for Spring Boot applications that use the @ComponentScan,
@ConfigurationPropertiesScan, @EntityScan, or @SpringBootApplication annotations, since every class
from every jar is read.
We generally recommend that you locate your main application class in a root package above other
classes. The @SpringBootApplication annotation is often placed on your main class, and it implicitly
defines a base “search package” for certain items. For example, if you are writing a JPA application,
the package of the @SpringBootApplication annotated class is used to search for @Entity items. Using
a root package also allows component scan to apply only on your project.
29
com
+- example
+- myapplication
+- MyApplication.java
|
+- customer
| +- Customer.java
| +- CustomerController.java
| +- CustomerService.java
| +- CustomerRepository.java
|
+- order
+- Order.java
+- OrderController.java
+- OrderService.java
+- OrderRepository.java
The MyApplication.java file would declare the main method, along with the basic
@SpringBootApplication, as follows:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
Many Spring configuration examples have been published on the Internet that use
TIP XML configuration. If possible, always try to use the equivalent Java-based
configuration. Searching for Enable* annotations can be a good starting point.
You need not put all your @Configuration into a single class. The @Import annotation can be used to
import additional configuration classes. Alternatively, you can use @ComponentScan to automatically
pick up all Spring components, including @Configuration classes.
30
6.3.2. Importing XML Configuration
If you absolutely must use XML based configuration, we recommend that you still start with a
@Configuration class. You can then use an @ImportResource annotation to load XML configuration
files.
6.4. Auto-configuration
Spring Boot auto-configuration attempts to automatically configure your Spring application based
on the jar dependencies that you have added. For example, if HSQLDB is on your classpath, and you
have not manually configured any database connection beans, then Spring Boot auto-configures an
in-memory database.
Auto-configuration is non-invasive. At any point, you can start to define your own configuration to
replace specific parts of the auto-configuration. For example, if you add your own DataSource bean,
the default embedded database support backs away.
If you need to find out what auto-configuration is currently being applied, and why, start your
application with the --debug switch. Doing so enables debug logs for a selection of core loggers and
logs a conditions report to the console.
If you find that specific auto-configuration classes that you do not want are being applied, you can
use the exclude attribute of @SpringBootApplication to disable them, as shown in the following
example:
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {
If the class is not on the classpath, you can use the excludeName attribute of the annotation and
specify the fully qualified name instead. If you prefer to use @EnableAutoConfiguration rather than
@SpringBootApplication, exclude and excludeName are also available. Finally, you can also control the
31
list of auto-configuration classes to exclude by using the spring.autoconfigure.exclude property.
TIP You can define exclusions both at the annotation level and by using the property.
Even though auto-configuration classes are public, the only aspect of the class that
is considered public API is the name of the class which can be used for disabling the
NOTE auto-configuration. The actual contents of those classes, such as nested
configuration classes or bean methods are for internal use only and we do not
recommend using those directly.
If you structure your code as suggested above (locating your application class in a top package), you
can add @ComponentScan without any arguments or use the @SpringBootApplication annotation which
implicitly includes it. All of your application components (@Component, @Service, @Repository,
@Controller, and others) are automatically registered as Spring Beans.
The following example shows a @Service Bean that uses constructor injection to obtain a required
RiskAssessor bean:
import org.springframework.stereotype.Service;
@Service
public class MyAccountService implements AccountService {
// ...
If a bean has more than one constructor, you will need to mark the one you want Spring to use with
@Autowired:
32
import java.io.PrintStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyAccountService implements AccountService {
@Autowired
public MyAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
this.out = System.out;
}
// ...
Notice how using constructor injection lets the riskAssessor field be marked as final,
TIP
indicating that it cannot be subsequently changed.
• @ComponentScan: enable @Component scan on the package where the application is located (see the
best practices)
33
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
None of these features are mandatory and you may choose to replace this single
annotation by any of the features that it enables. For instance, you may not want to
use component scan or configuration properties scan in your application:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Import;
@SpringBootConfiguration(proxyBeanMethods = false)
@EnableAutoConfiguration
@Import({ SomeConfiguration.class, AnotherConfiguration.class })
NOTE
public class MyApplication {
In this example, MyApplication is just like any other Spring Boot application except
that @Component-annotated classes and @ConfigurationProperties-annotated classes
are not detected automatically and the user-defined beans are imported explicitly
(see @Import).
34
This section only covers jar-based packaging. If you choose to package your
NOTE
application as a war file, see your server and IDE documentation.
You can run a Spring Boot application from your IDE as a Java application. However, you first need
to import your project. Import steps vary depending on your IDE and build system. Most IDEs can
import Maven projects directly. For example, Eclipse users can select Import… → Existing Maven
Projects from the File menu.
If you cannot directly import your project into your IDE, you may be able to generate IDE metadata
by using a build plugin. Maven includes plugins for Eclipse and IDEA. Gradle offers plugins for
various IDEs.
If you accidentally run a web application twice, you see a “Port already in use” error.
TIP Spring Tools users can use the Relaunch button rather than the Run button to ensure
that any existing instance is closed.
If you use the Spring Boot Maven or Gradle plugins to create an executable jar, you can run your
application using java -jar, as shown in the following example:
It is also possible to run a packaged application with remote debugging support enabled. Doing so
lets you attach a debugger to your packaged application, as shown in the following example:
The Spring Boot Maven plugin includes a run goal that can be used to quickly compile and run your
application. Applications run in an exploded form, as they do in your IDE. The following example
shows a typical Maven command to run a Spring Boot application:
$ mvn spring-boot:run
You might also want to use the MAVEN_OPTS operating system environment variable, as shown in the
following example:
$ export MAVEN_OPTS=-Xmx1024m
35
6.7.4. Using the Gradle Plugin
The Spring Boot Gradle plugin also includes a bootRun task that can be used to run your application
in an exploded form. The bootRun task is added whenever you apply the org.springframework.boot
and java plugins and is shown in the following example:
$ gradle bootRun
You might also want to use the JAVA_OPTS operating system environment variable, as shown in the
following example:
$ export JAVA_OPTS=-Xmx1024m
Since Spring Boot applications are plain Java applications, JVM hot-swapping should work out of
the box. JVM hot swapping is somewhat limited with the bytecode that it can replace. For a more
complete solution, JRebel can be used.
The spring-boot-devtools module also includes support for quick application restarts. See the Hot
swapping “How-to” for details.
Maven
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Gradle
dependencies {
developmentOnly("org.springframework.boot:spring-boot-devtools")
}
36
Devtools might cause classloading issues, in particular in multi-module projects.
CAUTION
Diagnosing Classloading Issues explains how to diagnose and solve them.
Repackaged archives do not contain devtools by default. If you want to use a certain
remote devtools feature, you need to include it. When using the Maven plugin, set the
TIP
excludeDevtools property to false. When using the Gradle plugin, configure the task’s
classpath to include the developmentOnly configuration.
As described in the Restart vs Reload section, restart functionality is implemented by using two
classloaders. For most applications, this approach works well. However, it can sometimes cause
classloading issues, in particular in multi-module projects.
To diagnose whether the classloading issues are indeed caused by devtools and its two classloaders,
try disabling restart. If this solves your problems, customize the restart classloader to include your
entire project.
Several of the libraries supported by Spring Boot use caches to improve performance. For example,
template engines cache compiled templates to avoid repeatedly parsing template files. Also, Spring
MVC can add HTTP caching headers to responses when serving static resources.
Cache options are usually configured by settings in your application.properties file. For example,
Thymeleaf offers the spring.thymeleaf.cache property. Rather than needing to set these properties
manually, the spring-boot-devtools module automatically applies sensible development-time
configuration.
37
Because you need more information about web requests while developing Spring MVC and Spring
WebFlux applications, developer tools suggests you to enable DEBUG logging for the web logging
group. This will give you information about the incoming request, which handler is processing it,
the response outcome, and other details. If you wish to log all request details (including potentially
sensitive information), you can turn on the spring.mvc.log-request-details or spring.codec.log-
request-details configuration properties.
If you do not want property defaults to be applied you can set spring.devtools.add-
NOTE
properties to false in your application.properties.
For a complete list of the properties that are applied by the devtools, see
TIP
DevToolsPropertyDefaultsPostProcessor.
Applications that use spring-boot-devtools automatically restart whenever files on the classpath
change. This can be a useful feature when working in an IDE, as it gives a very fast feedback loop
for code changes. By default, any entry on the classpath that points to a directory is monitored for
changes. Note that certain resources, such as static assets and view templates, do not need to restart
the application.
Triggering a restart
As DevTools monitors classpath resources, the only way to trigger a restart is to update the
classpath. The way in which you cause the classpath to be updated depends on the IDE that
you are using:
• In Eclipse, saving a modified file causes the classpath to be updated and triggers a restart.
• In IntelliJ IDEA, building the project (Build +→+ Build Project) has the same effect.
• If using a build plugin, running mvn compile for Maven or gradle build for Gradle will
trigger a restart.
If you are restarting with Maven or Gradle using the build plugin you must leave
NOTE the forking set to enabled. If you disable forking, the isolated application classloader
used by devtools will not be created and restarts will not operate properly.
Automatic restart works very well when used with LiveReload. See the LiveReload
section for details. If you use JRebel, automatic restarts are disabled in favor of
TIP
dynamic class reloading. Other devtools features (such as LiveReload and property
overrides) can still be used.
38
DevTools needs to customize the ResourceLoader used by the ApplicationContext. If
NOTE your application provides one already, it is going to be wrapped. Direct override of
the getResource method on the ApplicationContext is not supported.
Restart vs Reload
The restart technology provided by Spring Boot works by using two classloaders. Classes that
do not change (for example, those from third-party jars) are loaded into a base classloader.
Classes that you are actively developing are loaded into a restart classloader. When the
application is restarted, the restart classloader is thrown away and a new one is created. This
approach means that application restarts are typically much faster than “cold starts”, since
the base classloader is already available and populated.
If you find that restarts are not quick enough for your applications or you encounter
classloading issues, you could consider reloading technologies such as JRebel from
ZeroTurnaround. These work by rewriting classes as they are loaded to make them more
amenable to reloading.
By default, each time your application restarts, a report showing the condition evaluation delta is
logged. The report shows the changes to your application’s auto-configuration as you make changes
such as adding or removing beans and setting configuration properties.
Properties
spring.devtools.restart.log-condition-evaluation-delta=false
Yaml
spring:
devtools:
restart:
log-condition-evaluation-delta: false
Excluding Resources
Certain resources do not necessarily need to trigger a restart when they are changed. For example,
Thymeleaf templates can be edited in-place. By default, changing resources in /META-INF/maven,
/META-INF/resources, /resources, /static, /public, or /templates does not trigger a restart but does
trigger a live reload. If you want to customize these exclusions, you can use the
spring.devtools.restart.exclude property. For example, to exclude only /static and /public you
39
would set the following property:
Properties
spring.devtools.restart.exclude=static/**,public/**
Yaml
spring:
devtools:
restart:
exclude: "static/**,public/**"
If you want to keep those defaults and add additional exclusions, use the
TIP
spring.devtools.restart.additional-exclude property instead.
You may want your application to be restarted or reloaded when you make changes to files that are
not on the classpath. To do so, use the spring.devtools.restart.additional-paths property to
configure additional paths to watch for changes. You can use the spring.devtools.restart.exclude
property described earlier to control whether changes beneath the additional paths trigger a full
restart or a live reload.
Disabling Restart
If you do not want to use the restart feature, you can disable it by using the
spring.devtools.restart.enabled property. In most cases, you can set this property in your
application.properties (doing so still initializes the restart classloader, but it does not watch for file
changes).
If you need to completely disable restart support (for example, because it does not work with a
specific library), you need to set the spring.devtools.restart.enabled System property to false
before calling SpringApplication.run(…), as shown in the following example:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
40
Using a Trigger File
If you work with an IDE that continuously compiles changed files, you might prefer to trigger
restarts only at specific times. To do so, you can use a “trigger file”, which is a special file that must
be modified when you want to actually trigger a restart check.
Any update to the file will trigger a check, but restart only actually occurs if
NOTE
Devtools has detected it has something to do.
To use a trigger file, set the spring.devtools.restart.trigger-file property to the name (excluding
any path) of your trigger file. The trigger file must appear somewhere on your classpath.
src
+- main
+- resources
+- .reloadtrigger
Properties
spring.devtools.restart.trigger-file=.reloadtrigger
Yaml
spring:
devtools:
restart:
trigger-file: ".reloadtrigger"
Some IDEs have features that save you from needing to update your trigger file manually. Spring
Tools for Eclipse and IntelliJ IDEA (Ultimate Edition) both have such support. With Spring Tools, you
can use the “reload” button from the console view (as long as your trigger-file is named
.reloadtrigger). For IntelliJ IDEA, you can follow the instructions in their documentation.
As described earlier in the Restart vs Reload section, restart functionality is implemented by using
two classloaders. If this causes issues, you might need to customize what gets loaded by which
classloader.
41
By default, any open project in your IDE is loaded with the “restart” classloader, and any regular
.jar file is loaded with the “base” classloader. The same is true if you use mvn spring-boot:run or
gradle bootRun: the project containing your @SpringBootApplication is loaded with the “restart”
classloader, and everything else with the “base” classloader.
You can instruct Spring Boot to load parts of your project with a different classloader by creating a
META-INF/spring-devtools.properties file. The spring-devtools.properties file can contain
properties prefixed with restart.exclude and restart.include. The include elements are items that
should be pulled up into the “restart” classloader, and the exclude elements are items that should be
pushed down into the “base” classloader. The value of the property is a regex pattern that is applied
to the classpath, as shown in the following example:
Properties
restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\\.]+\\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\\.]+\\.jar
Yaml
restart:
exclude:
companycommonlibs: "/mycorp-common-[\\w\\d-\\.]+\\.jar"
include:
projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
All property keys must be unique. As long as a property starts with restart.include.
NOTE
or restart.exclude. it is considered.
Known Limitations
Restart functionality does not work well with objects that are deserialized by using a standard
ObjectInputStream. If you need to deserialize data, you may need to use Spring’s
ConfigurableObjectInputStream in combination with
Thread.currentThread().getContextClassLoader().
Unfortunately, several third-party libraries deserialize without considering the context classloader.
If you find such a problem, you need to request a fix with the original authors.
6.8.4. LiveReload
The spring-boot-devtools module includes an embedded LiveReload server that can be used to
trigger a browser refresh when a resource is changed. LiveReload browser extensions are freely
available for Chrome, Firefox and Safari from livereload.com.
If you do not want to start the LiveReload server when your application runs, you can set the
42
spring.devtools.livereload.enabled property to false.
You can only run one LiveReload server at a time. Before starting your application,
NOTE ensure that no other LiveReload servers are running. If you start multiple
applications from your IDE, only the first has LiveReload support.
WARNING To trigger LiveReload when a file changes, Automatic Restart must be enabled.
You can configure global devtools settings by adding any of the following files to the
$HOME/.config/spring-boot directory:
1. spring-boot-devtools.properties
2. spring-boot-devtools.yaml
3. spring-boot-devtools.yml
Any properties added to these files apply to all Spring Boot applications on your machine that use
devtools. For example, to configure restart to always use a trigger file, you would add the following
property to your spring-boot-devtools file:
Properties
spring.devtools.restart.trigger-file=.reloadtrigger
Yaml
spring:
devtools:
restart:
trigger-file: ".reloadtrigger"
By default, $HOME is the user’s home directory. To customize this location, set the
SPRING_DEVTOOLS_HOME environment variable or the spring.devtools.home system property.
43
Profiles are not supported in devtools properties/yaml files.
FileSystemWatcher works by polling the class changes with a certain time interval, and then
waiting for a predefined quiet period to make sure there are no more changes. Since Spring Boot
relies entirely on the IDE to compile and copy files into the location from where Spring Boot can
read them, you might find that there are times when certain changes are not reflected when
devtools restarts the application. If you observe such problems constantly, try increasing the
spring.devtools.restart.poll-interval and spring.devtools.restart.quiet-period parameters to
the values that fit your development environment:
Properties
spring.devtools.restart.poll-interval=2s
spring.devtools.restart.quiet-period=1s
Yaml
spring:
devtools:
restart:
poll-interval: "2s"
quiet-period: "1s"
The monitored classpath directories are now polled every 2 seconds for changes, and a 1 second
quiet period is maintained to make sure there are no additional class changes.
The Spring Boot developer tools are not limited to local development. You can also use several
features when running applications remotely. Remote support is opt-in as enabling it can be a
security risk. It should only be enabled when running on a trusted network or when secured with
SSL. If neither of these options is available to you, you should not use DevTools' remote support.
You should never enable support on a production deployment.
To enable it, you need to make sure that devtools is included in the repackaged archive, as shown in
the following listing:
44
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>false</excludeDevtools>
</configuration>
</plugin>
</plugins>
</build>
Then you need to set the spring.devtools.remote.secret property. Like any important password or
secret, the value should be unique and strong such that it cannot be guessed or brute-forced.
Remote devtools support is provided in two parts: a server-side endpoint that accepts connections
and a client application that you run in your IDE. The server component is automatically enabled
when the spring.devtools.remote.secret property is set. The client component must be launched
manually.
The remote client application is designed to be run from within your IDE. You need to run
org.springframework.boot.devtools.RemoteSpringApplication with the same classpath as the remote
project that you connect to. The application’s single required argument is the remote URL to which
it connects.
For example, if you are using Eclipse or Spring Tools and you have a project named my-app that you
have deployed to Cloud Foundry, you would do the following:
• Add https://myapp.cfapps.io to the Program arguments (or whatever your remote URL is).
45
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: 3.0.0-SNAPSHOT
Because the remote client is using the same classpath as the real application it can
NOTE directly read application properties. This is how the spring.devtools.remote.secret
property is read and passed to the server for authentication.
If you need to use a proxy to access the remote application, configure the
TIP
spring.devtools.remote.proxy.host and spring.devtools.remote.proxy.port properties.
Remote Update
The remote client monitors your application classpath for changes in the same way as the local
restart. Any updated resource is pushed to the remote application and (if required) triggers a
restart. This can be helpful if you iterate on a feature that uses a cloud service that you do not have
locally. Generally, remote updates and restarts are much quicker than a full rebuild and deploy
cycle.
On a slower development environment, it may happen that the quiet period is not enough, and the
changes in the classes may be split into batches. The server is restarted after the first batch of class
changes is uploaded. The next batch can’t be sent to the application, since the server is restarting.
46
This is typically manifested by a warning in the RemoteSpringApplication logs about failing to upload
some of the classes, and a consequent retry. But it may also lead to application code inconsistency
and failure to restart after the first batch of changes is uploaded. If you observe such problems
constantly, try increasing the spring.devtools.restart.poll-interval and
spring.devtools.restart.quiet-period parameters to the values that fit your development
environment. See the Configuring File System Watcher section for configuring these properties.
Files are only monitored when the remote client is running. If you change a file
NOTE
before starting the remote client, it is not pushed to the remote server.
For additional “production ready” features, such as health, auditing, and metric REST or JMX end-
points, consider adding spring-boot-actuator. See Production-ready Features for details.
47
Chapter 7. Core Features
This section dives into the details of Spring Boot. Here you can learn about the key features that you
may want to use and customize. If you have not already done so, you might want to read the
"Getting Started" and "Developing with Spring Boot" sections, so that you have a good grounding of
the basics.
7.1. SpringApplication
The SpringApplication class provides a convenient way to bootstrap a Spring application that is
started from a main() method. In many situations, you can delegate to the static
SpringApplication.run method, as shown in the following example:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
When your application starts, you should see something similar to the following output:
48
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: v3.0.0-SNAPSHOT
By default, INFO logging messages are shown, including some relevant startup details, such as the
user that launched the application. If you need a log level other than INFO, you can set it, as
described in Log Levels. The application version is determined using the implementation version
from the main application class’s package. Startup information logging can be turned off by setting
spring.main.log-startup-info to false. This will also turn off logging of the application’s active
profiles.
49
7.1.1. Startup Failure
If your application fails to start, registered FailureAnalyzers get a chance to provide a dedicated
error message and a concrete action to fix the problem. For instance, if you start a web application
on port 8080 and that port is already in use, you should see something similar to the following
message:
***************************
APPLICATION FAILED TO START
***************************
Description:
Embedded servlet container failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that is listening on port 8080 or configure this
application to listen on another port.
Spring Boot provides numerous FailureAnalyzer implementations, and you can add
NOTE
your own.
If no failure analyzers are able to handle the exception, you can still display the full conditions
report to better understand what went wrong. To do so, you need to enable the debug property or
enable DEBUG logging for
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener.
For instance, if you are running your application by using java -jar, you can enable the debug
property as follows:
A downside of lazy initialization is that it can delay the discovery of a problem with the application.
If a misconfigured bean is initialized lazily, a failure will no longer occur during startup and the
problem will only become apparent when the bean is initialized. Care must also be taken to ensure
that the JVM has sufficient memory to accommodate all of the application’s beans and not just those
that are initialized during startup. For these reasons, lazy initialization is not enabled by default
and it is recommended that fine-tuning of the JVM’s heap size is done before enabling lazy
50
initialization.
Properties
spring.main.lazy-initialization=true
Yaml
spring:
main:
lazy-initialization: true
If you want to disable lazy initialization for certain beans while using lazy
TIP initialization for the rest of the application, you can explicitly set their lazy attribute to
false using the @Lazy(false) annotation.
The banner that is printed on start up can be changed by adding a banner.txt file to your classpath
or by setting the spring.banner.location property to the location of such a file. If the file has an
encoding other than UTF-8, you can set spring.banner.charset. In addition to a text file, you can also
add a banner.gif, banner.jpg, or banner.png image file to your classpath or set the
spring.banner.image.location property. Images are converted into an ASCII art representation and
printed above any text banner.
Inside your banner.txt file, you can use any of the following placeholders:
Variable Description
${application.version} The version number of your application, as
declared in MANIFEST.MF. For example,
Implementation-Version: 1.0 is printed as 1.0.
${application.formatted-version} The version number of your application, as
declared in MANIFEST.MF and formatted for
display (surrounded with brackets and prefixed
with v). For example (v1.0).
${spring-boot.version} The Spring Boot version that you are using. For
example 3.0.0-SNAPSHOT.
51
Variable Description
${spring-boot.formatted-version} The Spring Boot version that you are using,
formatted for display (surrounded with brackets
and prefixed with v). For example (v3.0.0-
SNAPSHOT).
${Ansi.NAME} (or ${AnsiColor.NAME}, Where NAME is the name of an ANSI escape code.
${AnsiBackground.NAME}, ${AnsiStyle.NAME}) See AnsiPropertySource for details.
${application.title} The title of your application, as declared in
MANIFEST.MF. For example Implementation-Title:
MyApp is printed as MyApp.
You can also use the spring.main.banner-mode property to determine if the banner has to be printed
on System.out (console), sent to the configured logger (log), or not produced at all (off).
The printed banner is registered as a singleton bean under the following name: springBootBanner.
This is why we recommend that you always launch unpacked jars using java
org.springframework.boot.loader.JarLauncher. This will initialize the application.*
banner variables before building the classpath and launching your app.
If the SpringApplication defaults are not to your taste, you can instead create a local instance and
customize it. For example, to turn off the banner, you could write:
52
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
For a complete list of the configuration options, see the SpringApplication Javadoc.
The SpringApplicationBuilder lets you chain together multiple method calls and includes parent and
child methods that let you create a hierarchy, as shown in the following example:
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
When deployed on platforms, applications can provide information about their availability to the
platform using infrastructure such as Kubernetes Probes. Spring Boot includes out-of-the box
53
support for the commonly used “liveness” and “readiness” availability states. If you are using
Spring Boot’s “actuator” support then these states are exposed as health endpoint groups.
In addition, you can also obtain availability states by injecting the ApplicationAvailability interface
into your own beans.
Liveness State
The “Liveness” state of an application tells whether its internal state allows it to work correctly, or
recover by itself if it is currently failing. A broken “Liveness” state means that the application is in a
state that it cannot recover from, and the infrastructure should restart the application.
In general, the "Liveness" state should not be based on external checks, such as
NOTE Health checks. If it did, a failing external system (a database, a Web API, an external
cache) would trigger massive restarts and cascading failures across the platform.
The internal state of Spring Boot applications is mostly represented by the Spring
ApplicationContext. If the application context has started successfully, Spring Boot assumes that the
application is in a valid state. An application is considered live as soon as the context has been
refreshed, see Spring Boot application lifecycle and related Application Events.
Readiness State
The “Readiness” state of an application tells whether the application is ready to handle traffic. A
failing “Readiness” state tells the platform that it should not route traffic to the application for now.
This typically happens during startup, while CommandLineRunner and ApplicationRunner components
are being processed, or at any time if the application decides that it is too busy for additional traffic.
An application is considered ready as soon as application and command-line runners have been
called, see Spring Boot application lifecycle and related Application Events.
Application components can retrieve the current availability state at any time, by injecting the
ApplicationAvailability interface and calling methods on it. More often, applications will want to
listen to state updates or update the state of the application.
For example, we can export the "Readiness" state of the application to a file so that a Kubernetes
"exec Probe" can look at this file:
54
import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.ReadinessState;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class MyReadinessStateExporter {
@EventListener
public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) {
switch (event.getState()) {
case ACCEPTING_TRAFFIC:
// create file /tmp/healthy
break;
case REFUSING_TRAFFIC:
// remove file /tmp/healthy
break;
}
}
We can also update the state of the application, when the application breaks and cannot recover:
55
import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.LivenessState;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
@Component
public class MyLocalCacheVerifier {
Spring Boot provides Kubernetes HTTP probes for "Liveness" and "Readiness" with Actuator Health
Endpoints. You can get more guidance about deploying Spring Boot applications on Kubernetes in
the dedicated section.
56
Some events are actually triggered before the ApplicationContext is created, so you
cannot register a listener on those as a @Bean. You can register them with the
SpringApplication.addListeners(…) method or the
SpringApplicationBuilder.listeners(…) method.
If you want those listeners to be registered automatically, regardless of the way the
application is created, you can add a META-INF/spring.factories file to your project
NOTE
and reference your listener(s) by using the
org.springframework.context.ApplicationListener key, as shown in the following
example:
org.springframework.context.ApplicationListener=com.example.project.MyLi
stener
Application events are sent in the following order, as your application runs:
1. An ApplicationStartingEvent is sent at the start of a run but before any processing, except for
the registration of listeners and initializers.
4. An ApplicationPreparedEvent is sent just before the refresh is started but after bean definitions
have been loaded.
5. An ApplicationStartedEvent is sent after the context has been refreshed but before any
application and command-line runners have been called.
7. An ApplicationReadyEvent is sent after any application and command-line runners have been
called.
The above list only includes SpringApplicationEvents that are tied to a SpringApplication. In
addition to these, the following events are also published after ApplicationPreparedEvent and before
ApplicationStartedEvent:
57
You often need not use application events, but it can be handy to know that they exist.
TIP
Internally, Spring Boot uses events to handle a variety of tasks.
Event listeners should not run potentially lengthy tasks as they execute in the same
NOTE
thread by default. Consider using application and command-line runners instead.
Application events are sent by using Spring Framework’s event publishing mechanism. Part of this
mechanism ensures that an event published to the listeners in a child context is also published to
the listeners in any ancestor contexts. As a result of this, if your application uses a hierarchy of
SpringApplication instances, a listener may receive multiple instances of the same type of
application event.
To allow your listener to distinguish between an event for its context and an event for a descendant
context, it should request that its application context is injected and then compare the injected
context with the context of the event. The context can be injected by implementing
ApplicationContextAware or, if the listener is a bean, by using @Autowired.
A SpringApplication attempts to create the right type of ApplicationContext on your behalf. The
algorithm used to determine a WebApplicationType is the following:
This means that if you are using Spring MVC and the new WebClient from Spring WebFlux in the
same application, Spring MVC will be used by default. You can override that easily by calling
setWebApplicationType(WebApplicationType).
It is also possible to take complete control of the ApplicationContext type that is used by calling
setApplicationContextClass(…).
If you need to access the application arguments that were passed to SpringApplication.run(…), you
can inject a org.springframework.boot.ApplicationArguments bean. The ApplicationArguments
interface provides access to both the raw String[] arguments as well as parsed option and non-
option arguments, as shown in the following example:
58
import java.util.List;
import org.springframework.boot.ApplicationArguments;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
If you need to run some specific code once the SpringApplication has started, you can implement
the ApplicationRunner or CommandLineRunner interfaces. Both interfaces work in the same way and
offer a single run method, which is called just before SpringApplication.run(…) completes.
This contract is well suited for tasks that should run after application startup but
NOTE
before it starts accepting traffic.
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) {
// Do something...
}
59
If several CommandLineRunner or ApplicationRunner beans are defined that must be called in a specific
order, you can additionally implement the org.springframework.core.Ordered interface or use the
org.springframework.core.annotation.Order annotation.
Each SpringApplication registers a shutdown hook with the JVM to ensure that the
ApplicationContext closes gracefully on exit. All the standard Spring lifecycle callbacks (such as the
DisposableBean interface or the @PreDestroy annotation) can be used.
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class MyApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return () -> 42;
}
Also, the ExitCodeGenerator interface may be implemented by exceptions. When such an exception
is encountered, Spring Boot returns the exit code provided by the implemented getExitCode()
method.
If you want to know on which HTTP port the application is running, get the property
TIP
with a key of local.server.port.
60
7.1.13. Application Startup tracking
During the application startup, the SpringApplication and the ApplicationContext perform many
tasks related to the application lifecycle, the beans lifecycle or even processing application events.
With ApplicationStartup, Spring Framework allows you to track the application startup sequence
with StartupStep objects. This data can be collected for profiling purposes, or just to have a better
understanding of an application startup process.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
@SpringBootApplication
public class MyApplication {
Spring Boot ships with the BufferingApplicationStartup variant; this implementation is meant for
buffering the startup steps and draining them into an external metrics system. Applications can ask
for the bean of type BufferingApplicationStartup in any component.
Spring Boot can also be configured to expose a startup endpoint that provides this information as a
JSON document.
61
Property values can be injected directly into your beans by using the @Value annotation, accessed
through Spring’s Environment abstraction, or be bound to structured objects through
@ConfigurationProperties.
Spring Boot uses a very particular PropertySource order that is designed to allow sensible
overriding of values. Properties are considered in the following order (with values from lower
items overriding earlier ones):
2. @PropertySource annotations on your @Configuration classes. Please note that such property
sources are not added to the Environment until the application context is being refreshed. This is
too late to configure certain properties such as logging.* and spring.main.* which are read
before refresh begins.
5. OS environment variables.
12. properties attribute on your tests. Available on @SpringBootTest and the test annotations for
testing a particular slice of your application.
14. Devtools global settings properties in the $HOME/.config/spring-boot directory when devtools is
active.
1. Application properties packaged inside your jar (application.properties and YAML variants).
It is recommended to stick with one format for your entire application. If you have
NOTE configuration files with both .properties and .yml format in the same location,
.properties takes precedence.
62
To provide a concrete example, suppose you develop a @Component that uses a name property, as
shown in the following example:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
On your application classpath (for example, inside your jar) you can have an
application.properties file that provides a sensible default property value for name. When running
in a new environment, an application.properties file can be provided outside of your jar that
overrides the name. For one-off testing, you can launch with a specific command line switch (for
example, java -jar app.jar --name="Spring").
The env and configprops endpoints can be useful in determining why a property has a
TIP particular value. You can use these two endpoints to diagnose unexpected property
values. See the "Production ready features" section for details.
By default, SpringApplication converts any command line option arguments (that is, arguments
starting with --, such as --server.port=9000) to a property and adds them to the Spring Environment.
As mentioned previously, command line properties always take precedence over file-based
property sources.
If you do not want command line properties to be added to the Environment, you can disable them
by using SpringApplication.setAddCommandLineProperties(false).
Environment variables and system properties often have restrictions that mean some property
names cannot be used. To help with this, Spring Boot allows you to encode a block of properties into
a single JSON structure.
For example, the SPRING_APPLICATION_JSON property can be supplied on the command line in a UN*X
shell as an environment variable:
63
$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar
In the preceding example, you end up with my.name=test in the Spring Environment.
If you are deploying to a classic Application Server, you could also use a JNDI variable named
java:comp/env/spring.application.json.
Although null values from the JSON will be added to the resulting property source,
the PropertySourcesPropertyResolver treats null properties as missing values. This
NOTE
means that the JSON cannot override properties from lower order property sources
with a null value.
Spring Boot will automatically find and load application.properties and application.yaml files from
the following locations when your application starts:
The list is ordered by precedence (with values from lower items overriding earlier ones).
Documents from the loaded files are added as PropertySources to the Spring Environment.
If you do not like application as the configuration file name, you can switch to another file name by
specifying a spring.config.name environment property. For example, to look for
myproject.properties and myproject.yaml files you can run your application as follows:
64
You can also refer to an explicit location by using the spring.config.location environment property.
This properties accepts a comma-separated list of one or more locations to check.
Use the prefix optional: if the locations are optional and you do not mind if they do
TIP
not exist.
If spring.config.location contains directories (as opposed to files), they should end in /. At runtime
they will be appended with the names generated from spring.config.name before being loaded. Files
specified in spring.config.location are imported directly.
Both directory and file location values are also expanded to check for profile-
specific files. For example, if you have a spring.config.location of
NOTE
classpath:myconfig.properties, you will also find appropriate classpath:myconfig-
<profile>.properties files are loaded.
In most situations, each spring.config.location item you add will reference a single file or
directory. Locations are processed in the order that they are defined and later ones can override
the values of earlier ones.
If you have a complex location setup, and you use profile-specific configuration files, you may need
to provide further hints so that Spring Boot knows how they should be grouped. A location group is
a collection of locations that are all considered at the same level. For example, you might want to
group all classpath locations, then all external locations. Items within a location group should be
separated with ;. See the example in the “Profile Specific Files” section for more details.
Locations configured by using spring.config.location replace the default locations. For example, if
spring.config.location is configured with the value optional:classpath:/custom-
config/,optional:file:./custom-config/, the complete set of locations considered is:
1. optional:classpath:custom-config/
2. optional:file:./custom-config/
If you prefer to add additional locations, rather than replacing them, you can use
spring.config.additional-location. Properties loaded from additional locations can override those
in the default locations. For example, if spring.config.additional-location is configured with the
value optional:classpath:/custom-config/,optional:file:./custom-config/, the complete set of
65
locations considered is:
1. optional:classpath:/;optional:classpath:/config/
2. optional:file:./;optional:file:./config/;optional:file:./config/*/
3. optional:classpath:custom-config/
4. optional:file:./custom-config/
This search ordering lets you specify default values in one configuration file and then selectively
override those values in another. You can provide default values for your application in
application.properties (or whatever other basename you choose with spring.config.name) in one of
the default locations. These default values can then be overridden at runtime with a different file
located in one of the custom locations.
If you use environment variables rather than system properties, most operating
systems disallow period-separated key names, but you can use underscores instead
NOTE
(for example, SPRING_CONFIG_NAME instead of spring.config.name). See Binding from
Environment Variables for details.
Optional Locations
By default, when a specified config data location does not exist, Spring Boot will throw a
ConfigDataLocationNotFoundException and your application will not start.
If you want to specify a location, but you do not mind if it does not always exist, you can use the
optional: prefix. You can use this prefix with the spring.config.location and
spring.config.additional-location properties, as well as with spring.config.import declarations.
If you want to ignore all ConfigDataLocationNotFoundExceptions and always continue to start your
application, you can use the spring.config.on-not-found property. Set the value to ignore using
SpringApplication.setDefaultProperties(…) or with a system/environment variable.
Wildcard Locations
If a config file location includes the * character for the last path segment, it is considered a wildcard
location. Wildcards are expanded when the config is loaded so that immediate subdirectories are
also checked. Wildcard locations are particularly useful in an environment such as Kubernetes
when there are multiple sources of config properties.
For example, if you have some Redis configuration and some MySQL configuration, you might want
to keep those two pieces of configuration separate, while requiring that both those are present in
an application.properties file. This might result in two separate application.properties files
66
mounted at different locations such as /config/redis/application.properties and
/config/mysql/application.properties. In such a case, having a wildcard location of config/*/, will
result in both files being processed.
By default, Spring Boot includes config/*/ in the default search locations. It means that all
subdirectories of the /config directory outside of your jar will be searched.
You can use wildcard locations yourself with the spring.config.location and
spring.config.additional-location properties.
A wildcard location must contain only one * and end with */ for search locations
NOTE that are directories or */<filename> for search locations that are files. Locations with
wildcards are sorted alphabetically based on the absolute path of the file names.
Wildcard locations only work with external directories. You cannot use a wildcard in a
TIP
classpath: location.
As well as application property files, Spring Boot will also attempt to load profile-specific files using
the naming convention application-{profile}. For example, if your application activates a profile
named prod and uses YAML files, then both application.yml and application-prod.yml will be
considered.
Profile-specific properties are loaded from the same locations as standard application.properties,
with profile-specific files always overriding the non-specific ones. If several profiles are specified, a
last-wins strategy applies. For example, if profiles prod,live are specified by the
spring.profiles.active property, values in application-prod.properties can be overridden by those
in application-live.properties.
67
The last-wins strategy applies at the location group level. A spring.config.location
of classpath:/cfg/,classpath:/ext/ will not have the same override rules as
classpath:/cfg/;classpath:/ext/.
For example, continuing our prod,live example above, we might have the following
files:
/cfg
application-live.properties
/ext
application-live.properties
application-prod.properties
1. /cfg/application-live.properties
2. /ext/application-prod.properties
3. /ext/application-live.properties
1. /ext/application-prod.properties
2. /cfg/application-live.properties
3. /ext/application-live.properties
The Environment has a set of default profiles (by default, [default]) that are used if no active profiles
are set. In other words, if no profiles are explicitly activated, then properties from application-
default are considered.
Properties files are only ever loaded once. If you have already directly imported a
NOTE
profile specific property files then it will not be imported a second time.
Application properties may import further config data from other locations using the
spring.config.import property. Imports are processed as they are discovered, and are treated as
additional documents inserted immediately below the one that declares the import.
For example, you might have the following in your classpath application.properties file:
Properties
spring.application.name=myapp
spring.config.import=optional:file:./dev.properties
68
Yaml
spring:
application:
name: "myapp"
config:
import: "optional:file:./dev.properties"
This will trigger the import of a dev.properties file in current directory (if such a file exists). Values
from the imported dev.properties will take precedence over the file that triggered the import. In
the above example, the dev.properties could redefine spring.application.name to a different value.
An import will only be imported once no matter how many times it is declared. The order an
import is defined inside a single document within the properties/yaml file does not matter. For
instance, the two examples below produce the same result:
Properties
spring.config.import=my.properties
my.property=value
Yaml
spring:
config:
import: "my.properties"
my:
property: "value"
Properties
my.property=value
spring.config.import=my.properties
Yaml
my:
property: "value"
spring:
config:
import: "my.properties"
In both of the above examples, the values from the my.properties file will take precedence over the
file that triggered its import.
Several locations can be specified under a single spring.config.import key. Locations will be
processed in the order that they are defined, with later imports taking precedence.
69
When appropriate, Profile-specific variants are also considered for import. The
NOTE example above would import both my.properties as well as any my-
<profile>.properties variants.
Spring Boot includes pluggable API that allows various different location addresses to
be supported. By default you can import Java Properties, YAML and “configuration
trees”.
Third-party jars can offer support for additional technologies (there is no requirement
TIP
for files to be local). For example, you can imagine config data being from external
stores such as Consul, Apache ZooKeeper or Netflix Archaius.
If you want to support your own locations, see the ConfigDataLocationResolver and
ConfigDataLoader classes in the org.springframework.boot.context.config package.
Some cloud platforms cannot add a file extension to volume mounted files. To import these
extensionless files, you need to give Spring Boot a hint so that it knows how to load them. You can
do this by putting an extension hint in square brackets.
For example, suppose you have a /etc/config/myconfig file that you wish to import as yaml. You can
import it from your application.properties using the following:
Properties
spring.config.import=file:/etc/config/myconfig[.yaml]
Yaml
spring:
config:
import: "file:/etc/config/myconfig[.yaml]"
When running applications on a cloud platform (such as Kubernetes) you often need to read config
values that the platform supplies. It is not uncommon to use environment variables for such
purposes, but this can have drawbacks, especially if the value is supposed to be kept secret.
As an alternative to environment variables, many cloud platforms now allow you to map
configuration into mounted data volumes. For example, Kubernetes can volume mount both
ConfigMaps and Secrets.
There are two common volume mount patterns that can be used:
2. Multiple files are written to a directory tree, with the filename becoming the ‘key’ and the
70
contents becoming the ‘value’.
For the first case, you can import the YAML or Properties file directly using spring.config.import as
described above. For the second case, you need to use the configtree: prefix so that Spring Boot
knows it needs to expose all the files as properties.
As an example, let’s imagine that Kubernetes has mounted the following volume:
etc/
config/
myapp/
username
password
The contents of the username file would be a config value, and the contents of password would be a
secret.
To import these properties, you can add the following to your application.properties or
application.yaml file:
Properties
spring.config.import=optional:configtree:/etc/config/
Yaml
spring:
config:
import: "optional:configtree:/etc/config/"
You can then access or inject myapp.username and myapp.password properties from the Environment in
the usual way.
Filenames with dot notation are also correctly mapped. For example, in the above
NOTE example, a file named myapp.username in /etc/config would result in a
myapp.username property in the Environment.
Configuration tree values can be bound to both string String and byte[] types
TIP
depending on the contents expected.
If you have multiple config trees to import from the same parent folder you can use a wildcard
shortcut. Any configtree: location that ends with /*/ will import all immediate children as config
trees.
71
etc/
config/
dbconfig/
db/
username
password
mqconfig/
mq/
username
password
Properties
spring.config.import=optional:configtree:/etc/config/*/
Yaml
spring:
config:
import: "optional:configtree:/etc/config/*/"
Directories loaded using a wildcard are sorted alphabetically. If you need a different
NOTE
order, then you should list each location as a separate import
Configuration trees can also be used for Docker secrets. When a Docker swarm service is granted
access to a secret, the secret gets mounted into the container. For example, if a secret named
db.password is mounted at location /run/secrets/, you can make db.password available to the Spring
environment using the following:
Properties
spring.config.import=optional:configtree:/run/secrets/
Yaml
spring:
config:
import: "optional:configtree:/run/secrets/"
Property Placeholders
The values in application.properties and application.yml are filtered through the existing
Environment when they are used, so you can refer back to previously defined values (for example,
72
from System properties). The standard ${name} property-placeholder syntax can be used anywhere
within a value.
For example, the following file will set app.description to “MyApp is a Spring Boot application”:
Properties
app.name=MyApp
app.description=${app.name} is a Spring Boot application
Yaml
app:
name: "MyApp"
description: "${app.name} is a Spring Boot application"
You can also use this technique to create “short” variants of existing Spring Boot
TIP
properties. See the Use ‘Short’ Command Line Arguments how-to for details.
Spring Boot allows you to split a single physical file into multiple logical documents which are each
added independently. Documents are processed in order, from top to bottom. Later documents can
override the properties defined in earlier ones.
For application.yml files, the standard YAML multi-document syntax is used. Three consecutive
hyphens represent the end of one document, and the start of the next.
spring:
application:
name: "MyApp"
---
spring:
application:
name: "MyCloudApp"
config:
activate:
on-cloud-platform: "kubernetes"
For application.properties files a special #--- comment is used to mark the document splits:
spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes
73
Property file separators must not have any leading whitespace and must have
NOTE exactly three hyphen characters. The lines immediately before and after the
separator must not be comments.
Multi-document property files are often used in conjunction with activation properties
TIP
such as spring.config.activate.on-profile. See the next section for details.
Activation Properties
It is sometimes useful to only activate a given set of properties when certain conditions are met. For
example, you might have properties that are only relevant when a specific profile is active.
Property Note
on-profile A profile expression that must match for the document to be active.
on-cloud-platform The CloudPlatform that must be detected for the document to be active.
For example, the following specifies that the second document is only active when running on
Kubernetes, and only when either the “prod” or “staging” profiles are active:
Properties
myprop=always-set
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.config.activate.on-profile=prod | staging
myotherprop=sometimes-set
Yaml
myprop:
"always-set"
---
spring:
config:
activate:
on-cloud-platform: "kubernetes"
on-profile: "prod | staging"
myotherprop: "sometimes-set"
74
7.2.4. Encrypting Properties
Spring Boot does not provide any built in support for encrypting property values, however, it does
provide the hook points necessary to modify values contained in the Spring Environment. The
EnvironmentPostProcessor interface allows you to manipulate the Environment before the application
starts. See Customize the Environment or ApplicationContext Before It Starts for details.
If you need a secure way to store credentials and passwords, the Spring Cloud Vault project
provides support for storing externalized configuration in HashiCorp Vault.
YAML is a superset of JSON and, as such, is a convenient format for specifying hierarchical
configuration data. The SpringApplication class automatically supports YAML as an alternative to
properties whenever you have the SnakeYAML library on your classpath.
YAML documents need to be converted from their hierarchical format to a flat structure that can be
used with the Spring Environment. For example, consider the following YAML document:
environments:
dev:
url: "https://dev.example.com"
name: "Developer Setup"
prod:
url: "https://another.example.com"
name: "My Cool App"
In order to access these properties from the Environment, they would be flattened as follows:
environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App
Likewise, YAML lists also need to be flattened. They are represented as property keys with [index]
dereferencers. For example, consider the following YAML:
my:
servers:
- "dev.example.com"
- "another.example.com"
75
The preceding example would be transformed into these properties:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
Properties that use the [index] notation can be bound to Java List or Set objects using
TIP Spring Boot’s Binder class. For more details see the “Type-safe Configuration
Properties” section below.
Spring Framework provides two convenient classes that can be used to load YAML documents. The
YamlPropertiesFactoryBean loads YAML as Properties and the YamlMapFactoryBean loads YAML as a
Map.
You can also use the YamlPropertySourceLoader class if you want to load YAML as a Spring
PropertySource.
The RandomValuePropertySource is useful for injecting random values (for example, into secrets or
test cases). It can produce integers, longs, uuids, or strings, as shown in the following example:
Properties
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number-less-than-ten=${random.int(10)}
my.number-in-range=${random.int[1024,65536]}
Yaml
my:
secret: "${random.value}"
number: "${random.int}"
bignumber: "${random.long}"
uuid: "${random.uuid}"
number-less-than-ten: "${random.int(10)}"
number-in-range: "${random.int[1024,65536]}"
The random.int* syntax is OPEN value (,max) CLOSE where the OPEN,CLOSE are any character and
76
value,max are integers. If max is provided, then value is the minimum value and max is the maximum
value (exclusive).
Spring Boot supports setting a prefix for environment properties. This is useful if the system
environment is shared by multiple Spring Boot applications with different configuration
requirements. The prefix for system environment properties can be set directly on
SpringApplication.
For example, if you set the prefix to input, a property such as remote.timeout will also be resolved as
input.remote.timeout in the system environment.
TIP See also the differences between @Value and type-safe configuration properties.
It is possible to bind a bean declaring standard JavaBean properties as shown in the following
example:
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my.service")
public class MyProperties {
77
}
}
78
The preceding POJO defines the following properties:
• my.service.security.password.
Such arrangement relies on a default empty constructor and getters and setters are
usually mandatory, since binding is through standard Java Beans property
descriptors, just like in Spring MVC. A setter may be omitted in the following cases:
• Maps, as long as they are initialized, need a getter but not necessarily a setter,
since they can be mutated by the binder.
• Collections and arrays can be accessed either through an index (typically with
YAML) or by using a single comma-separated value (properties). In the latter
case, a setter is mandatory. We recommend to always add a setter for such types.
If you initialize a collection, make sure it is not immutable (as in the preceding
NOTE example).
• If nested POJO properties are initialized (like the Security field in the preceding
example), a setter is not required. If you want the binder to create the instance
on the fly by using its default constructor, you need a setter.
Some people use Project Lombok to add getters and setters automatically. Make sure
that Lombok does not generate any particular constructor for such a type, as it is
used automatically by the container to instantiate the object.
Finally, only standard Java Bean properties are considered and binding on static
properties is not supported.
Constructor binding
The example in the previous section can be rewritten in an immutable fashion as shown in the
following example:
import java.net.InetAddress;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
79
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
@ConstructorBinding
@ConfigurationProperties("my.service")
public class MyProperties {
80
}
}
In this setup, the @ConstructorBinding annotation is used to indicate that constructor binding should
be used. This means that the binder will expect to find a constructor with the parameters that you
wish to have bound. If you are using Java 16 or later, constructor binding can be used with records.
In this case, unless your record has multiple constructors, there is no need to use
@ConstructorBinding.
Nested members of a @ConstructorBinding class (such as Security in the example above) will also be
bound through their constructor.
Default values can be specified using @DefaultValue and the same conversion service will be applied
to coerce the String value to the target type of a missing property. By default, if no properties are
bound to Security, the MyProperties instance will contain a null value for security. If you wish you
return a non-null instance of Security even when no properties are bound to it, you can use an
empty @DefaultValue annotation to do so:
If you have more than one constructor for your class you can also use
TIP
@ConstructorBinding directly on the constructor that should be bound.
81
The use of java.util.Optional with @ConfigurationProperties is not recommended
as it is primarily intended for use as a return type. As such, it is not well-suited to
NOTE configuration property injection. For consistency with properties of other types, if
you do declare an Optional property and it has no value, null rather than an empty
Optional will be bound.
Spring Boot provides infrastructure to bind @ConfigurationProperties types and register them as
beans. You can either enable configuration properties on a class-by-class basis or enable
configuration property scanning that works in a similar manner to component scanning.
Sometimes, classes annotated with @ConfigurationProperties might not be suitable for scanning, for
example, if you’re developing your own auto-configuration or you want to enable them
conditionally. In these cases, specify the list of types to process using the
@EnableConfigurationProperties annotation. This can be done on any @Configuration class, as shown
in the following example:
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties.class)
public class MyConfiguration {
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
public class MyApplication {
82
When the @ConfigurationProperties bean is registered using configuration property
scanning or through @EnableConfigurationProperties, the bean has a conventional
name: <prefix>-<fqn>, where <prefix> is the environment key prefix specified in the
@ConfigurationProperties annotation and <fqn> is the fully qualified name of the
NOTE bean. If the annotation does not provide any prefix, only the fully qualified name of
the bean is used.
We recommend that @ConfigurationProperties only deal with the environment and, in particular,
does not inject other beans from the context. For corner cases, setter injection can be used or any of
the *Aware interfaces provided by the framework (such as EnvironmentAware if you need access to the
Environment). If you still want to inject other beans using the constructor, the configuration
properties bean must be annotated with @Component and use JavaBean-based property binding.
This style of configuration works particularly well with the SpringApplication external YAML
configuration, as shown in the following example:
my:
service:
remote-address: 192.168.1.1
security:
username: "admin"
roles:
- "USER"
- "ADMIN"
To work with @ConfigurationProperties beans, you can inject them in the same way as any other
bean, as shown in the following example:
83
import org.springframework.stereotype.Service;
@Service
public class MyService {
// ...
Using @ConfigurationProperties also lets you generate metadata files that can be used
TIP
by IDEs to offer auto-completion for your own keys. See the appendix for details.
Third-party Configuration
As well as using @ConfigurationProperties to annotate a class, you can also use it on public @Bean
methods. Doing so can be particularly useful when you want to bind properties to third-party
components that are outside of your control.
To configure a bean from the Environment properties, add @ConfigurationProperties to its bean
registration, as shown in the following example:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class ThirdPartyConfiguration {
@Bean
@ConfigurationProperties(prefix = "another")
public AnotherComponent anotherComponent() {
return new AnotherComponent();
}
84
Any JavaBean property defined with the another prefix is mapped onto that AnotherComponent bean
in manner similar to the preceding SomeProperties example.
Relaxed Binding
Spring Boot uses some relaxed rules for binding Environment properties to @ConfigurationProperties
beans, so there does not need to be an exact match between the Environment property name and the
bean property name. Common examples where this is useful include dash-separated environment
properties (for example, context-path binds to contextPath), and capitalized environment properties
(for example, PORT binds to port).
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.main-project.person")
public class MyPersonProperties {
With the preceding code, the following properties names can all be used:
Property Note
my.main- Kebab case, which is recommended for use in .properties and .yml files.
project.person.fir
st-name
my.main- Standard camel case syntax.
project.person.fir
stName
my.main- Underscore notation, which is an alternative format for use in .properties and
project.person.fir .yml files.
st_name
MY_MAINPROJECT_PER Upper case format, which is recommended when using system environment
SON_FIRSTNAME variables.
The prefix value for the annotation must be in kebab case (lowercase and separated
NOTE
by -, such as my.main-project.person).
85
Table 7. relaxed binding rules per property source
Properties Files Camel case, kebab case, or underscore Standard list syntax using [ ] or
notation comma-separated values
YAML Files Camel case, kebab case, or underscore Standard YAML list syntax or comma-
notation separated values
System properties Camel case, kebab case, or underscore Standard list syntax using [ ] or
notation comma-separated values
We recommend that, when possible, properties are stored in lower-case kebab format,
TIP
such as my.person.first-name=Rod.
Binding Maps
When binding to Map properties you may need to use a special bracket notation so that the original
key value is preserved. If the key is not surrounded by [], any characters that are not alpha-
numeric, - or . are removed.
Properties
my.map.[/key1]=value1
my.map.[/key2]=value2
my.map./key3=value3
Yaml
my:
map:
"[/key1]": "value1"
"[/key2]": "value2"
"/key3": "value3"
For YAML files, the brackets need to be surrounded by quotes for the keys to be
NOTE
parsed properly.
The properties above will bind to a Map with /key1, /key2 and key3 as the keys in the map. The slash
has been removed from key3 because it was not surrounded by square brackets.
You may also occasionally need to use the bracket notation if your key contains a . and you are
binding to non-scalar value. For example, binding a.b=c to Map<String, Object> will return a Map
with the entry {"a"={"b"="c"}} whereas [a.b]=c will return a Map with the entry {"a.b"="c"}.
86
Binding from Environment Variables
Most operating systems impose strict rules around the names that can be used for environment
variables. For example, Linux shell variables can contain only letters (a to z or A to Z), numbers (0 to
9) or the underscore character (_). By convention, Unix shell variables will also have their names in
UPPERCASE.
Spring Boot’s relaxed binding rules are, as much as possible, designed to be compatible with these
naming restrictions.
To convert a property name in the canonical-form to an environment variable name you can follow
these rules:
• Convert to uppercase.
Environment variables can also be used when binding to object lists. To bind to a List, the element
number should be surrounded with underscores in the variable name.
For example, the configuration property my.service[0].other would use an environment variable
named MY_SERVICE_0_OTHER.
When lists are configured in more than one place, overriding works by replacing the entire list.
For example, assume a MyPojo object with name and description attributes that are null by default.
The following example exposes a list of MyPojo objects from MyProperties:
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my")
public class MyProperties {
87
Consider the following configuration:
Properties
my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
Yaml
my:
list:
- name: "my name"
description: "my description"
---
spring:
config:
activate:
on-profile: "dev"
my:
list:
- name: "my another name"
If the dev profile is not active, MyProperties.list contains one MyPojo entry, as previously defined. If
the dev profile is enabled, however, the list still contains only one entry (with a name of my another
name and a description of null). This configuration does not add a second MyPojo instance to the list,
and it does not merge the items.
When a List is specified in multiple profiles, the one with the highest priority (and only that one) is
used. Consider the following example:
Properties
my.list[0].name=my name
my.list[0].description=my description
my.list[1].name=another name
my.list[1].description=another description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
88
Yaml
my:
list:
- name: "my name"
description: "my description"
- name: "another name"
description: "another description"
---
spring:
config:
activate:
on-profile: "dev"
my:
list:
- name: "my another name"
In the preceding example, if the dev profile is active, MyProperties.list contains one MyPojo entry
(with a name of my another name and a description of null). For YAML, both comma-separated lists
and YAML lists can be used for completely overriding the contents of the list.
For Map properties, you can bind with property values drawn from multiple sources. However, for
the same property in multiple sources, the one with the highest priority is used. The following
example exposes a Map<String, MyPojo> from MyProperties:
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my")
public class MyProperties {
89
Properties
my.map.key1.name=my name 1
my.map.key1.description=my description 1
#---
spring.config.activate.on-profile=dev
my.map.key1.name=dev name 1
my.map.key2.name=dev name 2
my.map.key2.description=dev description 2
Yaml
my:
map:
key1:
name: "my name 1"
description: "my description 1"
---
spring:
config:
activate:
on-profile: "dev"
my:
map:
key1:
name: "dev name 1"
key2:
name: "dev name 2"
description: "dev description 2"
If the dev profile is not active, MyProperties.map contains one entry with key key1 (with a name of my
name 1 and a description of my description 1). If the dev profile is enabled, however, map contains
two entries with keys key1 (with a name of dev name 1 and a description of my description 1) and
key2 (with a name of dev name 2 and a description of dev description 2).
The preceding merging rules apply to properties from all property sources, and not
NOTE
just files.
Properties Conversion
Spring Boot attempts to coerce the external application properties to the right type when it binds to
the @ConfigurationProperties beans. If you need custom type conversion, you can provide a
ConversionService bean (with a bean named conversionService) or custom property editors (through
a CustomEditorConfigurer bean) or custom Converters (with bean definitions annotated as
@ConfigurationPropertiesBinding).
90
As this bean is requested very early during the application lifecycle, make sure to
limit the dependencies that your ConversionService is using. Typically, any
dependency that you require may not be fully initialized at creation time. You may
NOTE
want to rename your custom ConversionService if it is not required for
configuration keys coercion and only rely on custom converters qualified with
@ConfigurationPropertiesBinding.
Converting Durations
Spring Boot has dedicated support for expressing durations. If you expose a java.time.Duration
property, the following formats in application properties are available:
• A regular long representation (using milliseconds as the default unit unless a @DurationUnit has
been specified)
• A more readable format where the value and the unit are coupled (10s means 10 seconds)
91
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DurationUnit;
@ConfigurationProperties("my")
public class MyProperties {
@DurationUnit(ChronoUnit.SECONDS)
private Duration sessionTimeout = Duration.ofSeconds(30);
To specify a session timeout of 30 seconds, 30, PT30S and 30s are all equivalent. A read timeout of
500ms can be specified in any of the following form: 500, PT0.5S and 500ms.
You can also use any of the supported units. These are:
• ns for nanoseconds
• us for microseconds
• ms for milliseconds
• s for seconds
• m for minutes
• h for hours
• d for days
The default unit is milliseconds and can be overridden using @DurationUnit as illustrated in the
sample above.
92
If you prefer to use constructor binding, the same properties can be exposed, as shown in the
following example:
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.convert.DurationUnit;
@ConfigurationProperties("my")
@ConstructorBinding
public class MyProperties {
If you are upgrading a Long property, make sure to define the unit (using
TIP @DurationUnit) if it is not milliseconds. Doing so gives a transparent upgrade path
while supporting a much richer format.
Converting periods
In addition to durations, Spring Boot can also work with java.time.Period type. The following
formats can be used in application properties:
• An regular int representation (using days as the default unit unless a @PeriodUnit has been
specified)
93
• A simpler format where the value and the unit pairs are coupled (1y3d means 1 year and 3 days)
• y for years
• m for months
• w for weeks
• d for days
Spring Framework has a DataSize value type that expresses a size in bytes. If you expose a DataSize
property, the following formats in application properties are available:
• A regular long representation (using bytes as the default unit unless a @DataSizeUnit has been
specified)
• A more readable format where the value and the unit are coupled (10MB means 10 megabytes)
94
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;
@ConfigurationProperties("my")
public class MyProperties {
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize bufferSize = DataSize.ofMegabytes(2);
To specify a buffer size of 10 megabytes, 10 and 10MB are equivalent. A size threshold of 256 bytes
can be specified as 256 or 256B.
You can also use any of the supported units. These are:
• B for bytes
• KB for kilobytes
• MB for megabytes
• GB for gigabytes
• TB for terabytes
The default unit is bytes and can be overridden using @DataSizeUnit as illustrated in the sample
above.
If you prefer to use constructor binding, the same properties can be exposed, as shown in the
following example:
95
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;
@ConfigurationProperties("my")
@ConstructorBinding
public class MyProperties {
If you are upgrading a Long property, make sure to define the unit (using
TIP @DataSizeUnit) if it is not bytes. Doing so gives a transparent upgrade path while
supporting a much richer format.
@ConfigurationProperties Validation
Spring Boot attempts to validate @ConfigurationProperties classes whenever they are annotated
with Spring’s @Validated annotation. You can use JSR-303 javax.validation constraint annotations
directly on your configuration class. To do so, ensure that a compliant JSR-303 implementation is on
your classpath and then add constraint annotations to your fields, as shown in the following
example:
96
import java.net.InetAddress;
import jakarta.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
@ConfigurationProperties("my.service")
@Validated
public class MyProperties {
@NotNull
private InetAddress remoteAddress;
You can also trigger validation by annotating the @Bean method that creates the
TIP
configuration properties with @Validated.
To ensure that validation is always triggered for nested properties, even when no properties are
found, the associated field must be annotated with @Valid. The following example builds on the
preceding MyProperties example:
97
import java.net.InetAddress;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
@ConfigurationProperties("my.service")
@Validated
public class MyProperties {
@NotNull
private InetAddress remoteAddress;
@Valid
private final Security security = new Security();
@NotEmpty
private String username;
}
You can also add a custom Spring Validator by creating a bean definition called
configurationPropertiesValidator. The @Bean method should be declared static. The configuration
98
properties validator is created very early in the application’s lifecycle, and declaring the @Bean
method as static lets the bean be created without having to instantiate the @Configuration class.
Doing so avoids any problems that may be caused by early instantiation.
The @Value annotation is a core container feature, and it does not provide the same features as type-
safe configuration properties. The following table summarizes the features that are supported by
@ConfigurationProperties and @Value:
If you do want to use @Value, we recommend that you refer to property names using
their canonical form (kebab-case using only lowercase letters). This will allow
Spring Boot to use the same logic as it does when relaxed binding
@ConfigurationProperties. For example, @Value("{demo.item-price}") will pick up
NOTE
demo.item-price and demo.itemPrice forms from the application.properties file, as
well as DEMO_ITEMPRICE from the system environment. If you used
@Value("{demo.itemPrice}") instead, demo.item-price and DEMO_ITEMPRICE would not
be considered.
If you define a set of configuration keys for your own components, we recommend you group them
in a POJO annotated with @ConfigurationProperties. Doing so will provide you with structured,
type-safe object that you can inject into your own beans.
SpEL expressions from application property files are not processed at time of parsing these files and
populating the environment. However, it is possible to write a SpEL expression in @Value. If the
value of a property from an application property file is a SpEL expression, it will be evaluated when
consumed through @Value.
7.3. Profiles
Spring Profiles provide a way to segregate parts of your application configuration and make it be
available only in certain environments. Any @Component, @Configuration or @ConfigurationProperties
can be marked with @Profile to limit when it is loaded, as shown in the following example:
99
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration(proxyBeanMethods = false)
@Profile("production")
public class ProductionConfiguration {
// ...
You can use a spring.profiles.active Environment property to specify which profiles are active. You
can specify the property in any of the ways described earlier in this chapter. For example, you
could include it in your application.properties, as shown in the following example:
Properties
spring.profiles.active=dev,hsqldb
Yaml
spring:
profiles:
active: "dev,hsqldb"
You could also specify it on the command line by using the following switch:
--spring.profiles.active=dev,hsqldb.
If no profile is active, a default profile is enabled. The name of the default profile is default and it
can be tuned using the spring.profiles.default Environment property, as shown in the following
example:
Properties
spring.profiles.default=none
100
Yaml
spring:
profiles:
default: "none"
The spring.profiles.active property follows the same ordering rules as other properties: The
highest PropertySource wins. This means that you can specify active profiles in
application.properties and then replace them by using the command line switch.
Sometimes, it is useful to have properties that add to the active profiles rather than replace them.
The SpringApplication entry point has a Java API for setting additional profiles (that is, on top of
those activated by the spring.profiles.active property). See the setAdditionalProfiles() method in
SpringApplication. Profile groups, which are described in the next section can also be used to add
active profiles if a given profile is active.
Occasionally the profiles that you define and use in your application are too fine-grained and
become cumbersome to use. For example, you might have proddb and prodmq profiles that you use to
enable database and messaging features independently.
To help with this, Spring Boot lets you define profile groups. A profile group allows you to define a
logical name for a related group of profiles.
For example, we can create a production group that consists of our proddb and prodmq profiles.
Properties
spring.profiles.group.production[0]=proddb
spring.profiles.group.production[1]=prodmq
Yaml
spring:
profiles:
group:
production:
- "proddb"
- "prodmq"
101
7.3.3. Programmatically Setting Profiles
7.4. Logging
Spring Boot uses Commons Logging for all internal logging but leaves the underlying log
implementation open. Default configurations are provided for Java Util Logging, Log4J2, and
Logback. In each case, loggers are pre-configured to use console output with optional file output
also available.
By default, if you use the “Starters”, Logback is used for logging. Appropriate Logback routing is
also included to ensure that dependent libraries that use Java Util Logging, Commons Logging,
Log4J, or SLF4J all work correctly.
There are a lot of logging frameworks available for Java. Do not worry if the above list
TIP seems confusing. Generally, you do not need to change your logging dependencies and
the Spring Boot defaults work just fine.
When you deploy your application to a servlet container or application server, logging
performed with the Java Util Logging API is not routed into your application’s logs.
TIP
This prevents logging performed by the container or other applications that have been
deployed to it from appearing in your application’s logs.
The default log output from Spring Boot resembles the following example:
102
2019-03-05 10:57:51.112 INFO 45469 --- [ main]
org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache
Tomcat/7.0.52
2019-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1]
o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded
WebApplicationContext
2019-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1]
o.s.web.context.ContextLoader : Root WebApplicationContext: initialization
completed in 1358 ms
2019-03-05 10:57:51.698 INFO 45469 --- [ost-startStop-1]
o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2019-03-05 10:57:51.702 INFO 45469 --- [ost-startStop-1]
o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter'
to: [/*]
• Process ID.
• Thread name: Enclosed in square brackets (may be truncated for console output).
• Logger name: This is usually the source class name (often abbreviated).
The default log configuration echoes messages to the console as they are written. By default, ERROR
-level, WARN-level, and INFO-level messages are logged. You can also enable a “debug” mode by
starting your application with a --debug flag.
When the debug mode is enabled, a selection of core loggers (embedded container, Hibernate, and
Spring Boot) are configured to output more information. Enabling the debug mode does not
configure your application to log all messages with DEBUG level.
Alternatively, you can enable a “trace” mode by starting your application with a --trace flag (or
trace=true in your application.properties). Doing so enables trace logging for a selection of core
loggers (embedded container, Hibernate schema generation, and the whole Spring portfolio).
103
Color-coded Output
If your terminal supports ANSI, color output is used to aid readability. You can set
spring.output.ansi.enabled to a supported value to override the auto-detection.
Color coding is configured by using the %clr conversion word. In its simplest form, the converter
colors the output according to the log level, as shown in the following example:
%clr(%5p)
Level Color
FATAL Red
ERROR Red
WARN Yellow
INFO Green
DEBUG Green
TRACE Green
Alternatively, you can specify the color or style that should be used by providing it as an option to
the conversion. For example, to make the text yellow, use the following setting:
%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}
• blue
• cyan
• faint
• green
• magenta
• red
• yellow
By default, Spring Boot logs only to the console and does not write log files. If you want to write log
files in addition to the console output, you need to set a logging.file.name or logging.file.path
property (for example, in your application.properties).
The following table shows how the logging.* properties can be used together:
104
Table 8. Logging properties
Specific file (none) my.log Writes to the specified log file. Names can be an exact
location or relative to the current directory.
(none) Specific /var/log Writes spring.log to the specified directory. Names can
directory be an exact location or relative to the current directory.
Log files rotate when they reach 10 MB and, as with console output, ERROR-level, WARN-level, and INFO
-level messages are logged by default.
If you are using the Logback, it is possible to fine-tune log rotation settings using your
application.properties or application.yaml file. For all other logging system, you will need to
configure rotation settings directly yourself (for example, if you use Log4J2 then you could add a
log4j2.xml or log4j2-spring.xml file).
Name Description
logging.logback.rollingpolicy.file-name- The filename pattern used to create log archives.
pattern
logging.logback.rollingpolicy.clean-history- If log archive cleanup should occur when the
on-start application starts.
logging.logback.rollingpolicy.max-file-size The maximum size of log file before it is
archived.
logging.logback.rollingpolicy.total-size-cap The maximum amount of size log archives can
take before being deleted.
logging.logback.rollingpolicy.max-history The maximum number of archive log files to
keep (defaults to 7).
All the supported logging systems can have the logger levels set in the Spring Environment (for
example, in application.properties) by using logging.level.<logger-name>=<level> where level is
one of TRACE, DEBUG, INFO, WARN, ERROR, FATAL, or OFF. The root logger can be configured by
using logging.level.root.
105
Properties
logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
Yaml
logging:
level:
root: "warn"
org.springframework.web: "debug"
org.hibernate: "error"
It is also possible to set logging levels using environment variables. For example,
LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG will set org.springframework.web to DEBUG.
The above approach will only work for package level logging. Since relaxed binding
always converts environment variables to lowercase, it is not possible to configure
NOTE
logging for an individual class in this way. If you need to configure logging for a
class, you can use the SPRING_APPLICATION_JSON variable.
It is often useful to be able to group related loggers together so that they can all be configured at the
same time. For example, you might commonly change the logging levels for all Tomcat related
loggers, but you can not easily remember top level packages.
To help with this, Spring Boot allows you to define logging groups in your Spring Environment. For
example, here is how you could define a “tomcat” group by adding it to your
application.properties:
Properties
logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
Yaml
logging:
group:
tomcat: "org.apache.catalina,org.apache.coyote,org.apache.tomcat"
Once defined, you can change the level for all the loggers in the group with a single line:
Properties
logging.level.tomcat=trace
106
Yaml
logging:
level:
tomcat: "trace"
Spring Boot includes the following pre-defined logging groups that can be used out-of-the-box:
Name Loggers
In order to release logging resources when your application terminates, a shutdown hook that will
trigger log system cleanup when the JVM exits is provided. This shutdown hook is registered
automatically unless your application is deployed as a war file. If your application has complex
context hierarchies the shutdown hook may not meet your needs. If it does not, disable the
shutdown hook and investigate the options provided directly by the underlying logging system. For
example, Logback offers context selectors which allow each Logger to be created in its own context.
You can use the logging.register-shutdown-hook property to disable the shutdown hook. Setting it to
false will disable the registration. You can set the property in your application.properties or
application.yaml file:
Properties
logging.register-shutdown-hook=false
Yaml
logging:
register-shutdown-hook: false
The various logging systems can be activated by including the appropriate libraries on the
classpath and can be further customized by providing a suitable configuration file in the root of the
classpath or in a location specified by the following Spring Environment property: logging.config.
You can force Spring Boot to use a particular logging system by using the
org.springframework.boot.logging.LoggingSystem system property. The value should be the fully
qualified class name of a LoggingSystem implementation. You can also disable Spring Boot’s logging
configuration entirely by using a value of none.
107
Since logging is initialized before the ApplicationContext is created, it is not possible
NOTE to control logging from @PropertySources in Spring @Configuration files. The only
way to change the logging system or disable it entirely is through System properties.
When possible, we recommend that you use the -spring variants for your logging
configuration (for example, logback-spring.xml rather than logback.xml). If you use
NOTE
standard configuration locations, Spring cannot completely control log
initialization.
There are known classloading issues with Java Util Logging that cause
WARNING problems when running from an 'executable jar'. We recommend that you
avoid it when running from an 'executable jar' if at all possible.
To help with the customization, some other properties are transferred from the Spring Environment
to System properties, as described in the following table:
108
Spring Environment System Property Comments
logging.pattern.level LOG_LEVEL_PATTERN The format to use when
rendering the log level (default
%5p).
PID PID The current process ID
(discovered if possible and
when not already defined as an
OS environment variable).
All the supported logging systems can consult System properties when parsing their configuration
files. See the default configurations in spring-boot.jar for examples:
• Logback
• Log4j 2
If you want to use a placeholder in a logging property, you should use Spring Boot’s
syntax and not the syntax of the underlying framework. Notably, if you use Logback,
TIP
you should use : as the delimiter between a property name and its default value and
not use :-.
109
You can add MDC and other ad-hoc content to log lines by overriding only the
LOG_LEVEL_PATTERN (or logging.pattern.level with Logback). For example, if you use
logging.pattern.level=user:%X{user} %5p, then the default log format contains an MDC
entry for "user", if it exists, as shown in the following example.
TIP
Spring Boot includes a number of extensions to Logback that can help with advanced configuration.
You can use these extensions in your logback-spring.xml configuration file.
Because the standard logback.xml configuration file is loaded too early, you cannot
NOTE use extensions in it. You need to either use logback-spring.xml or define a
logging.config property.
Profile-specific Configuration
The <springProfile> tag lets you optionally include or exclude sections of configuration based on
the active Spring profiles. Profile sections are supported anywhere within the <configuration>
element. Use the name attribute to specify which profile accepts the configuration. The
<springProfile> tag can contain a profile name (for example staging) or a profile expression. A
profile expression allows for more complicated profile logic to be expressed, for example
production & (eu-central | eu-west). Check the reference guide for more details. The following
listing shows three sample profiles:
110
<springProfile name="staging">
<!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>
<springProfile name="!production">
<!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>
Environment Properties
The <springProperty> tag lets you expose properties from the Spring Environment for use within
Logback. Doing so can be useful if you want to access values from your application.properties file
in your Logback configuration. The tag works in a similar way to Logback’s standard <property> tag.
However, rather than specifying a direct value, you specify the source of the property (from the
Environment). If you need to store the property somewhere other than in local scope, you can use
the scope attribute. If you need a fallback value (in case the property is not set in the Environment),
you can use the defaultValue attribute. The following example shows how to expose properties for
use within Logback:
7.5. Internationalization
Spring Boot supports localized messages so that your application can cater to users of different
language preferences. By default, Spring Boot looks for the presence of a messages resource bundle
at the root of the classpath.
The auto-configuration applies when the default properties file for the configured
resource bundle is available (messages.properties by default). If your resource
NOTE bundle contains only language-specific properties files, you are required to add the
default. If no properties file is found that matches any of the configured base
names, there will be no auto-configured MessageSource.
111
The basename of the resource bundle as well as several other attributes can be configured using
the spring.messages namespace, as shown in the following example:
Properties
spring.messages.basename=messages,config.i18n.messages
spring.messages.fallback-to-system-locale=false
Yaml
spring:
messages:
basename: "messages,config.i18n.messages"
fallback-to-system-locale: false
7.6. JSON
Spring Boot provides integration with three JSON mapping libraries:
• Gson
• Jackson
• JSON-B
7.6.1. Jackson
7.6.2. Gson
Auto-configuration for Gson is provided. When Gson is on the classpath a Gson bean is automatically
configured. Several spring.gson.* configuration properties are provided for customizing the
configuration. To take more control, one or more GsonBuilderCustomizer beans can be used.
7.6.3. JSON-B
Auto-configuration for JSON-B is provided. When the JSON-B API and an implementation are on the
classpath a Jsonb bean will be automatically configured. The preferred JSON-B implementation is
Eclipse Yasson for which dependency management is provided.
112
7.7. Task Execution and Scheduling
In the absence of an Executor bean in the context, Spring Boot auto-configures a
ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous
task execution (@EnableAsync) and Spring MVC asynchronous request processing.
If you have defined a custom Executor in the context, regular task execution (that is
@EnableAsync) will use it transparently but the Spring MVC support will not be
configured as it requires an AsyncTaskExecutor implementation (named
applicationTaskExecutor). Depending on your target arrangement, you could change
TIP your Executor into a ThreadPoolTaskExecutor or define both a ThreadPoolTaskExecutor
and an AsyncConfigurer wrapping your custom Executor.
The thread pool uses 8 core threads that can grow and shrink according to the load. Those default
settings can be fine-tuned using the spring.task.execution namespace, as shown in the following
example:
Properties
spring.task.execution.pool.max-size=16
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.keep-alive=10s
Yaml
spring:
task:
execution:
pool:
max-size: 16
queue-capacity: 100
keep-alive: "10s"
This changes the thread pool to use a bounded queue so that when the queue is full (100 tasks), the
thread pool increases to maximum 16 threads. Shrinking of the pool is more aggressive as threads
are reclaimed when they are idle for 10 seconds (rather than 60 seconds by default).
113
Properties
spring.task.scheduling.thread-name-prefix=scheduling-
spring.task.scheduling.pool.size=2
Yaml
spring:
task:
scheduling:
thread-name-prefix: "scheduling-"
pool:
size: 2
Both a TaskExecutorBuilder bean and a TaskSchedulerBuilder bean are made available in the context
if a custom executor or scheduler needs to be created.
7.8. Testing
Spring Boot provides a number of utilities and annotations to help when testing your application.
Test support is provided by two modules: spring-boot-test contains core items, and spring-boot-
test-autoconfigure supports auto-configuration for tests.
Most developers use the spring-boot-starter-test “Starter”, which imports both Spring Boot test
modules as well as JUnit Jupiter, AssertJ, Hamcrest, and a number of other useful libraries.
If you have tests that use JUnit 4, JUnit 5’s vintage engine can be used to run them. To
use the vintage engine, add a dependency on junit-vintage-engine, as shown in the
following example:
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
TIP <scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
The spring-boot-starter-test “Starter” (in the test scope) contains the following provided libraries:
114
• JUnit 5: The de-facto standard for unit testing Java applications.
• Spring Test & Spring Boot Test: Utilities and integration test support for Spring Boot
applications.
We generally find these common libraries to be useful when writing tests. If these libraries do not
suit your needs, you can add additional test dependencies of your own.
One of the major advantages of dependency injection is that it should make your code easier to unit
test. You can instantiate objects by using the new operator without even involving Spring. You can
also use mock objects instead of real dependencies.
Often, you need to move beyond unit testing and start integration testing (with a Spring
ApplicationContext). It is useful to be able to perform integration testing without requiring
deployment of your application or needing to connect to other infrastructure.
The Spring Framework includes a dedicated test module for such integration testing. You can
declare a dependency directly to org.springframework:spring-test or use the spring-boot-starter-
test “Starter” to pull it in transitively.
If you have not used the spring-test module before, you should start by reading the relevant
section of the Spring Framework reference documentation.
A Spring Boot application is a Spring ApplicationContext, so nothing very special has to be done to
test it beyond what you would normally do with a vanilla Spring context.
External properties, logging, and other features of Spring Boot are installed in the
NOTE
context by default only if you use SpringApplication to create it.
Spring Boot provides a @SpringBootTest annotation, which can be used as an alternative to the
standard spring-test @ContextConfiguration annotation when you need Spring Boot features. The
annotation works by creating the ApplicationContext used in your tests through SpringApplication.
In addition to @SpringBootTest a number of other annotations are also provided for testing more
specific slices of an application.
115
If you are using JUnit 4, do not forget to also add @RunWith(SpringRunner.class) to your
test, otherwise the annotations will be ignored. If you are using JUnit 5, there is no
TIP
need to add the equivalent @ExtendWith(SpringExtension.class) as @SpringBootTest and
the other @…Test annotations are already annotated with it.
By default, @SpringBootTest will not start a server. You can use the webEnvironment attribute of
@SpringBootTest to further refine how your tests run:
• NONE: Loads an ApplicationContext by using SpringApplication but does not provide any web
environment (mock or otherwise).
If your test is @Transactional, it rolls back the transaction at the end of each test
method by default. However, as using this arrangement with either RANDOM_PORT or
NOTE DEFINED_PORT implicitly provides a real servlet environment, the HTTP client and
server run in separate threads and, thus, in separate transactions. Any transaction
initiated on the server does not roll back in this case.
If Spring MVC is available, a regular MVC-based application context is configured. If you have only
Spring WebFlux, we will detect that and configure a WebFlux-based application context instead.
If both are present, Spring MVC takes precedence. If you want to test a reactive web application in
this scenario, you must set the spring.main.web-application-type property:
116
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(properties = "spring.main.web-application-type=reactive")
class MyWebFluxTests {
// ...
If you are familiar with the Spring Test Framework, you may be used to using
@ContextConfiguration(classes=…) in order to specify which Spring @Configuration to load.
Alternatively, you might have often used nested @Configuration classes within your test.
When testing Spring Boot applications, this is often not required. Spring Boot’s @*Test annotations
search for your primary configuration automatically whenever you do not explicitly define one.
The search algorithm works up from the package that contains the test until it finds a class
annotated with @SpringBootApplication or @SpringBootConfiguration. As long as you structured your
code in a sensible way, your main configuration is usually found.
If you use a test annotation to test a more specific slice of your application, you
should avoid adding configuration settings that are specific to a particular area on
the main method’s application class.
If you want to customize the primary configuration, you can use a nested @TestConfiguration class.
Unlike a nested @Configuration class, which would be used instead of your application’s primary
configuration, a nested @TestConfiguration class is used in addition to your application’s primary
configuration.
If your application uses component scanning (for example, if you use @SpringBootApplication or
@ComponentScan), you may find top-level configuration classes that you created only for specific tests
accidentally get picked up everywhere.
As we have seen earlier, @TestConfiguration can be used on an inner class of a test to customize the
117
primary configuration. When placed on a top-level class, @TestConfiguration indicates that classes
in src/test/java should not be picked up by scanning. You can then import that class explicitly
where it is required, as shown in the following example:
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
@SpringBootTest
@Import(MyTestsConfiguration.class)
class MyTests {
@Test
void exampleTest() {
// ...
}
If you directly use @ComponentScan (that is, not through @SpringBootApplication) you
NOTE
need to register the TypeExcludeFilter with it. See the Javadoc for details.
If your application expects arguments, you can have @SpringBootTest inject them using the args
attribute.
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(args = "--app.test=one")
class MyApplicationArgumentTests {
@Test
void applicationArgumentsPopulated(@Autowired ApplicationArguments args) {
assertThat(args.getOptionNames()).containsOnly("app.test");
assertThat(args.getOptionValues("app.test")).containsOnly("one");
}
118
Testing with a mock environment
By default, @SpringBootTest does not start the server but instead sets up a mock environment for
testing web endpoints.
With Spring MVC, we can query our web endpoints using MockMvc or WebTestClient, as shown in the
following example:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;
@SpringBootTest
@AutoConfigureMockMvc
class MyMockMvcTests {
@Test
void testWithMockMvc(@Autowired MockMvc mvc) throws Exception {
mvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("Hello
World"));
}
// If Spring WebFlux is on the classpath, you can drive MVC tests with a
WebTestClient
@Test
void testWithWebTestClient(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
If you want to focus only on the web layer and not start a complete
TIP
ApplicationContext, consider using @WebMvcTest instead.
119
With Spring WebFlux endpoints, you can use WebTestClient as shown in the following example:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;
@SpringBootTest
@AutoConfigureWebTestClient
class MyMockWebTestClientTests {
@Test
void exampleTest(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
Testing within a mocked environment is usually faster than running with a full servlet
container. However, since mocking occurs at the Spring MVC layer, code that relies on
lower-level servlet container behavior cannot be directly tested with MockMvc.
TIP For example, Spring Boot’s error handling is based on the “error page” support
provided by the servlet container. This means that, whilst you can test your MVC layer
throws and handles exceptions as expected, you cannot directly test that a specific
custom error page is rendered. If you need to test these lower-level concerns, you can
start a fully running server as described in the next section.
If you need to start a full running server, we recommend that you use random ports. If you use
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT), an available port is picked at random
each time your test runs.
The @LocalServerPort annotation can be used to inject the actual port used into your test. For
convenience, tests that need to make REST calls to the started server can additionally @Autowire a
WebTestClient, which resolves relative links to the running server and comes with a dedicated API
for verifying responses, as shown in the following example:
120
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.web.reactive.server.WebTestClient;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortWebTestClientTests {
@Test
void exampleTest(@Autowired WebTestClient webClient) {
webClient
.get().uri("/")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
TIP WebTestClient can be used against both live servers and mock environments.
This setup requires spring-webflux on the classpath. If you can not or will not add webflux, Spring
Boot also provides a TestRestTemplate facility:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortTestRestTemplateTests {
@Test
void exampleTest(@Autowired TestRestTemplate restTemplate) {
String body = restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World");
}
121
Customizing WebTestClient
Using JMX
As the test context framework caches context, JMX is disabled by default to prevent identical
components to register on the same domain. If such test needs access to an MBeanServer, consider
marking it dirty as well:
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
class MyJmxTests {
@Autowired
private MBeanServer mBeanServer;
@Test
void exampleTest() throws MalformedObjectNameException {
assertThat(this.mBeanServer.getDomains()).contains("java.lang");
// ...
}
Using Metrics
Regardless of your classpath, meter registries, except the in-memory backed, are not auto-
configured when using @SpringBootTest.
If you need to export metrics to a different backend as part of an integration test, annotate it with
@AutoConfigureMetrics.
122
Mocking and Spying Beans
When running tests, it is sometimes necessary to mock certain components within your application
context. For example, you may have a facade over some remote service that is unavailable during
development. Mocking can also be useful when you want to simulate failures that might be hard to
trigger in a real environment.
Spring Boot includes a @MockBean annotation that can be used to define a Mockito mock for a bean
inside your ApplicationContext. You can use the annotation to add new beans or replace a single
existing bean definition. The annotation can be used directly on test classes, on fields within your
test, or on @Configuration classes and fields. When used on a field, the instance of the created mock
is also injected. Mock beans are automatically reset after each test method.
If your test uses one of Spring Boot’s test annotations (such as @SpringBootTest), this
feature is automatically enabled. To use this feature with a different arrangement,
listeners must be explicitly added, as shown in the following example:
import
org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener;
import
org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListen
er;
import org.springframework.test.context.ContextConfiguration;
NOTE
import org.springframework.test.context.TestExecutionListeners;
@ContextConfiguration(classes = MyConfig.class)
@TestExecutionListeners({ MockitoTestExecutionListener.class,
ResetMocksTestExecutionListener.class })
class MyTests {
// ...
The following example replaces an existing RemoteService bean with a mock implementation:
123
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
@SpringBootTest
class MyTests {
@Autowired
private Reverser reverser;
@MockBean
private RemoteService remoteService;
@Test
void exampleTest() {
given(this.remoteService.getValue()).willReturn("spring");
String reverse = this.reverser.getReverseValue(); // Calls injected
RemoteService
assertThat(reverse).isEqualTo("gnirps");
}
@MockBean cannot be used to mock the behavior of a bean that is exercised during
application context refresh. By the time the test is executed, the application context
NOTE
refresh has completed and it is too late to configure the mocked behavior. We
recommend using a @Bean method to create and configure the mock in this situation.
Additionally, you can use @SpyBean to wrap any existing bean with a Mockito spy. See the Javadoc for
full details.
CGLib proxies, such as those created for scoped beans, declare the proxied methods
as final. This stops Mockito from functioning correctly as it cannot mock or spy on
final methods in its default configuration. If you want to mock or spy on such a
NOTE
bean, configure Mockito to use its inline mock maker by adding
org.mockito:mockito-inline to your application’s test dependencies. This allows
Mockito to mock and spy on final methods.
While Spring’s test framework caches application contexts between tests and reuses
NOTE a context for tests sharing the same configuration, the use of @MockBean or @SpyBean
influences the cache key, which will most likely increase the number of contexts.
124
If you are using @SpyBean to spy on a bean with @Cacheable methods that refer to
parameters by name, your application must be compiled with -parameters. This
TIP
ensures that the parameter names are available to the caching infrastructure once the
bean has been spied upon.
When you are using @SpyBean to spy on a bean that is proxied by Spring, you may need
TIP to remove Spring’s proxy in some situations, for example when setting expectations
using given or when. Use AopTestUtils.getTargetObject(yourProxiedSpy) to do so.
Auto-configured Tests
Spring Boot’s auto-configuration system works well for applications but can sometimes be a little
too much for tests. It often helps to load only the parts of the configuration that are required to test
a “slice” of your application. For example, you might want to test that Spring MVC controllers are
mapping URLs correctly, and you do not want to involve database calls in those tests, or you might
want to test JPA entities, and you are not interested in the web layer when those tests run.
Each slice restricts component scan to appropriate components and loads a very
restricted set of auto-configuration classes. If you need to exclude one of them, most
NOTE
@…Test annotations provide an excludeAutoConfiguration attribute. Alternatively,
you can use @ImportAutoConfiguration#exclude.
Including multiple “slices” by using several @…Test annotations in one test is not
NOTE supported. If you need multiple “slices”, pick one of the @…Test annotations and
include the @AutoConfigure… annotations of the other “slices” by hand.
To test that object JSON serialization and deserialization is working as expected, you can use the
@JsonTest annotation. @JsonTest auto-configures the available supported JSON mapper, which can
be one of the following libraries:
• Gson
• Jsonb
125
A list of the auto-configurations that are enabled by @JsonTest can be found in the
TIP
appendix.
If you need to configure elements of the auto-configuration, you can use the
@AutoConfigureJsonTesters annotation.
Spring Boot includes AssertJ-based helpers that work with the JSONAssert and JsonPath libraries to
check that JSON appears as expected. The JacksonTester, GsonTester, JsonbTester, and
BasicJsonTester classes can be used for Jackson, Gson, Jsonb, and Strings respectively. Any helper
fields on the test class can be @Autowired when using @JsonTest. The following example shows a test
class for Jackson:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.JacksonTester;
@JsonTest
class MyJsonTests {
@Autowired
private JacksonTester<VehicleDetails> json;
@Test
void serialize() throws Exception {
VehicleDetails details = new VehicleDetails("Honda", "Civic");
// Assert against a `.json` file in the same package as the test
assertThat(this.json.write(details)).isEqualToJson("expected.json");
// Or use JSON path based assertions
assertThat(this.json.write(details)).hasJsonPathStringValue("@.make");
assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo
("Honda");
}
@Test
void deserialize() throws Exception {
String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}";
assertThat(this.json.parse(content)).isEqualTo(new VehicleDetails("Ford",
"Focus"));
assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford");
}
126
JSON helper classes can also be used directly in standard unit tests. To do so, call the
NOTE
initFields method of the helper in your @Before method if you do not use @JsonTest.
If you use Spring Boot’s AssertJ-based helpers to assert on a number value at a given JSON path, you
might not be able to use isEqualTo depending on the type. Instead, you can use AssertJ’s satisfies to
assert that the value matches the given condition. For instance, the following example asserts that
the actual number is a float value close to 0.15 within an offset of 0.01.
@Test
void someTest() throws Exception {
SomeObject value = new SomeObject(0.152f);
assertThat(this.json.write(value)).extractingJsonPathNumberValue("@.test.numberValue")
.satisfies((number) -> assertThat(number.floatValue()).isCloseTo(0.15f,
within(0.01f)));
}
To test whether Spring MVC controllers are working as expected, use the @WebMvcTest annotation.
@WebMvcTest auto-configures the Spring MVC infrastructure and limits scanned beans to @Controller,
@ControllerAdvice, @JsonComponent, Converter, GenericConverter, Filter, HandlerInterceptor,
WebMvcConfigurer, WebMvcRegistrations, and HandlerMethodArgumentResolver. Regular @Component and
@ConfigurationProperties beans are not scanned when the @WebMvcTest annotation is used.
@EnableConfigurationProperties can be used to include @ConfigurationProperties beans.
A list of the auto-configuration settings that are enabled by @WebMvcTest can be found
TIP
in the appendix.
If you need to register extra components, such as the Jackson Module, you can import
TIP
additional configuration classes by using @Import on your test.
Often, @WebMvcTest is limited to a single controller and is used in combination with @MockBean to
provide mock implementations for required collaborators.
@WebMvcTest also auto-configures MockMvc. Mock MVC offers a powerful way to quickly test MVC
controllers without needing to start a full HTTP server.
127
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
@WebMvcTest(UserVehicleController.class)
class MyControllerTests {
@Autowired
private MockMvc mvc;
@MockBean
private UserVehicleService userVehicleService;
@Test
void testExample() throws Exception {
given(this.userVehicleService.getVehicleDetails("sboot"))
.willReturn(new VehicleDetails("Honda", "Civic"));
this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().string("Honda Civic"));
}
If you need to configure elements of the auto-configuration (for example, when servlet
TIP filters should be applied) you can use attributes in the @AutoConfigureMockMvc
annotation.
If you use HtmlUnit and Selenium, auto-configuration also provides an HtmlUnit WebClient bean
and/or a Selenium WebDriver bean. The following example uses HtmlUnit:
128
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
@WebMvcTest(UserVehicleController.class)
class MyHtmlUnitTests {
@Autowired
private WebClient webClient;
@MockBean
private UserVehicleService userVehicleService;
@Test
void testExample() throws Exception {
given(this.userVehicleService.getVehicleDetails("sboot")).willReturn(new
VehicleDetails("Honda", "Civic"));
HtmlPage page = this.webClient.getPage("/sboot/vehicle.html");
assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic");
}
By default, Spring Boot puts WebDriver beans in a special “scope” to ensure that the
NOTE driver exits after each test and that a new instance is injected. If you do not want
this behavior, you can add @Scope("singleton") to your WebDriver @Bean definition.
The webDriver scope created by Spring Boot will replace any user defined scope
WARNING of the same name. If you define your own webDriver scope you may find it stops
working when you use @WebMvcTest.
If you have Spring Security on the classpath, @WebMvcTest will also scan WebSecurityConfigurer
beans. Instead of disabling security completely for such tests, you can use Spring Security’s test
support. More details on how to use Spring Security’s MockMvc support can be found in this Testing
With Spring Security how-to section.
Sometimes writing Spring MVC tests is not enough; Spring Boot can help you run full
TIP
end-to-end tests with an actual server.
129
Auto-configured Spring WebFlux Tests
To test that Spring WebFlux controllers are working as expected, you can use the @WebFluxTest
annotation. @WebFluxTest auto-configures the Spring WebFlux infrastructure and limits scanned
beans to @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, WebFilter, and
WebFluxConfigurer. Regular @Component and @ConfigurationProperties beans are not scanned when
the @WebFluxTest annotation is used. @EnableConfigurationProperties can be used to include
@ConfigurationProperties beans.
A list of the auto-configurations that are enabled by @WebFluxTest can be found in the
TIP
appendix.
If you need to register extra components, such as Jackson Module, you can import
TIP
additional configuration classes using @Import on your test.
Often, @WebFluxTest is limited to a single controller and used in combination with the @MockBean
annotation to provide mock implementations for required collaborators.
@WebFluxTest also auto-configures WebTestClient, which offers a powerful way to quickly test
WebFlux controllers without needing to start a full HTTP server.
130
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;
@WebFluxTest(UserVehicleController.class)
class MyControllerTests {
@Autowired
private WebTestClient webClient;
@MockBean
private UserVehicleService userVehicleService;
@Test
void testExample() throws Exception {
given(this.userVehicleService.getVehicleDetails("sboot"))
.willReturn(new VehicleDetails("Honda", "Civic"));
this.webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN).exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("Honda Civic");
}
Sometimes writing Spring WebFlux tests is not enough; Spring Boot can help you run
TIP
full end-to-end tests with an actual server.
131
Auto-configured Data Cassandra Tests
The following example shows a typical setup for using Cassandra tests in Spring Boot:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest;
@DataCassandraTest
class MyDataCassandraTests {
@Autowired
private SomeRepository repository;
You can use the @DataJpaTest annotation to test JPA applications. By default, it scans for @Entity
classes and configures Spring Data JPA repositories. If an embedded database is available on the
classpath, it configures one as well. SQL queries are logged by default by setting the
spring.jpa.show-sql property to true. This can be disabled using the showSql() attribute of the
annotation.
Regular @Component and @ConfigurationProperties beans are not scanned when the @DataJpaTest
annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties
beans.
A list of the auto-configuration settings that are enabled by @DataJpaTest can be found
TIP
in the appendix.
By default, data JPA tests are transactional and roll back at the end of each test. See the relevant
section in the Spring Framework Reference Documentation for more details. If that is not what you
want, you can disable transaction management for a test or for the whole class as follows:
132
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyNonTransactionalTests {
// ...
Data JPA tests may also inject a TestEntityManager bean, which provides an alternative to the
standard JPA EntityManager that is specifically designed for tests.
A JdbcTemplate is also available if you need that. The following example shows the @DataJpaTest
annotation in use:
133
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
@DataJpaTest
class MyRepositoryTests {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository repository;
@Test
void testExample() throws Exception {
this.entityManager.persist(new User("sboot", "1234"));
User user = this.repository.findByUsername("sboot");
assertThat(user.getUsername()).isEqualTo("sboot");
assertThat(user.getEmployeeNumber()).isEqualTo("1234");
}
In-memory embedded databases generally work well for tests, since they are fast and do not
require any installation. If, however, you prefer to run tests against a real database you can use the
@AutoConfigureTestDatabase annotation, as shown in the following example:
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import
org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
class MyRepositoryTests {
// ...
@JdbcTest is similar to @DataJpaTest but is for tests that only require a DataSource and do not use
Spring Data JDBC. By default, it configures an in-memory embedded database and a JdbcTemplate.
134
Regular @Component and @ConfigurationProperties beans are not scanned when the @JdbcTest
annotation is used. @EnableConfigurationProperties can be used to include @ConfigurationProperties
beans.
A list of the auto-configurations that are enabled by @JdbcTest can be found in the
TIP
appendix.
By default, JDBC tests are transactional and roll back at the end of each test. See the relevant section
in the Spring Framework Reference Documentation for more details. If that is not what you want,
you can disable transaction management for a test or for the whole class, as follows:
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyTransactionalTests {
If you prefer your test to run against a real database, you can use the @AutoConfigureTestDatabase
annotation in the same way as for DataJpaTest. (See "Auto-configured Data JPA Tests".)
@DataJdbcTest is similar to @JdbcTest but is for tests that use Spring Data JDBC repositories. By
default, it configures an in-memory embedded database, a JdbcTemplate, and Spring Data JDBC
repositories. Only AbstractJdbcConfiguration sub-classes are scanned when the @DataJdbcTest
annotation is used, regular @Component and @ConfigurationProperties beans are not scanned.
@EnableConfigurationProperties can be used to include @ConfigurationProperties beans.
A list of the auto-configurations that are enabled by @DataJdbcTest can be found in the
TIP
appendix.
By default, Data JDBC tests are transactional and roll back at the end of each test. See the relevant
section in the Spring Framework Reference Documentation for more details. If that is not what you
want, you can disable transaction management for a test or for the whole test class as shown in the
JDBC example.
If you prefer your test to run against a real database, you can use the @AutoConfigureTestDatabase
annotation in the same way as for DataJpaTest. (See "Auto-configured Data JPA Tests".)
You can use @JooqTest in a similar fashion as @JdbcTest but for jOOQ-related tests. As jOOQ relies
heavily on a Java-based schema that corresponds with the database schema, the existing DataSource
is used. If you want to replace it with an in-memory database, you can use
135
@AutoConfigureTestDatabase to override those settings. (For more about using jOOQ with Spring
Boot, see "Using jOOQ", earlier in this chapter.) Regular @Component and @ConfigurationProperties
beans are not scanned when the @JooqTest annotation is used. @EnableConfigurationProperties can
be used to include @ConfigurationProperties beans.
A list of the auto-configurations that are enabled by @JooqTest can be found in the
TIP
appendix.
@JooqTest configures a DSLContext. The following example shows the @JooqTest annotation in use:
import org.jooq.DSLContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jooq.JooqTest;
@JooqTest
class MyJooqTests {
@Autowired
private DSLContext dslContext;
// ...
JOOQ tests are transactional and roll back at the end of each test by default. If that is not what you
want, you can disable transaction management for a test or for the whole test class as shown in the
JDBC example.
You can use @DataMongoTest to test MongoDB applications. By default, it configures an in-memory
embedded MongoDB (if available), configures a MongoTemplate, scans for @Document classes, and
configures Spring Data MongoDB repositories. Regular @Component and @ConfigurationProperties
beans are not scanned when the @DataMongoTest annotation is used. @EnableConfigurationProperties
can be used to include @ConfigurationProperties beans. (For more about using MongoDB with
Spring Boot, see "MongoDB", earlier in this chapter.)
136
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;
@DataMongoTest
class MyDataMongoDbTests {
@Autowired
private MongoTemplate mongoTemplate;
// ...
In-memory embedded MongoDB generally works well for tests, since it is fast and does not require
any developer installation. If, however, you prefer to run tests against a real MongoDB server, you
should exclude the embedded MongoDB auto-configuration, as shown in the following example:
import
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
class MyDataMongoDbTests {
// ...
You can use @DataNeo4jTest to test Neo4j applications. By default, it scans for @Node classes, and
configures Spring Data Neo4j repositories. Regular @Component and @ConfigurationProperties beans
are not scanned when the @DataNeo4jTest annotation is used. @EnableConfigurationProperties can be
used to include @ConfigurationProperties beans. (For more about using Neo4J with Spring Boot, see
"Neo4j", earlier in this chapter.)
The following example shows a typical setup for using Neo4J tests in Spring Boot:
137
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;
@DataNeo4jTest
class MyDataNeo4jTests {
@Autowired
private SomeRepository repository;
// ...
By default, Data Neo4j tests are transactional and roll back at the end of each test. See the relevant
section in the Spring Framework Reference Documentation for more details. If that is not what you
want, you can disable transaction management for a test or for the whole class, as follows:
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@DataNeo4jTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyDataNeo4jTests {
Transactional tests are not supported with reactive access. If you are using this
NOTE
style, you must configure @DataNeo4jTest tests as described above.
You can use @DataRedisTest to test Redis applications. By default, it scans for @RedisHash classes and
configures Spring Data Redis repositories. Regular @Component and @ConfigurationProperties beans
are not scanned when the @DataRedisTest annotation is used. @EnableConfigurationProperties can be
used to include @ConfigurationProperties beans. (For more about using Redis with Spring Boot, see
"Redis", earlier in this chapter.)
138
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest;
@DataRedisTest
class MyDataRedisTests {
@Autowired
private SomeRepository repository;
// ...
You can use @DataLdapTest to test LDAP applications. By default, it configures an in-memory
embedded LDAP (if available), configures an LdapTemplate, scans for @Entry classes, and configures
Spring Data LDAP repositories. Regular @Component and @ConfigurationProperties beans are not
scanned when the @DataLdapTest annotation is used. @EnableConfigurationProperties can be used to
include @ConfigurationProperties beans. (For more about using LDAP with Spring Boot, see "LDAP",
earlier in this chapter.)
A list of the auto-configuration settings that are enabled by @DataLdapTest can be found
TIP
in the appendix.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;
import org.springframework.ldap.core.LdapTemplate;
@DataLdapTest
class MyDataLdapTests {
@Autowired
private LdapTemplate ldapTemplate;
// ...
In-memory embedded LDAP generally works well for tests, since it is fast and does not require any
developer installation. If, however, you prefer to run tests against a real LDAP server, you should
exclude the embedded LDAP auto-configuration, as shown in the following example:
139
import
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;
@DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class)
class MyDataLdapTests {
// ...
You can use the @RestClientTest annotation to test REST clients. By default, it auto-configures
Jackson, GSON, and Jsonb support, configures a RestTemplateBuilder, and adds support for
MockRestServiceServer. Regular @Component and @ConfigurationProperties beans are not scanned
when the @RestClientTest annotation is used. @EnableConfigurationProperties can be used to
include @ConfigurationProperties beans.
The specific beans that you want to test should be specified by using the value or components
attribute of @RestClientTest, as shown in the following example:
140
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;
@RestClientTest(RemoteVehicleDetailsService.class)
class MyRestClientTests {
@Autowired
private RemoteVehicleDetailsService service;
@Autowired
private MockRestServiceServer server;
@Test
void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() throws Exception {
this.server.expect(requestTo("/greet/details")).andRespond(withSuccess("hello",
MediaType.TEXT_PLAIN));
String greeting = this.service.callRestService();
assertThat(greeting).isEqualTo("hello");
}
You can use the @AutoConfigureRestDocs annotation to use Spring REST Docs in your tests with Mock
MVC, REST Assured, or WebTestClient. It removes the need for the JUnit extension in Spring REST
Docs.
@AutoConfigureRestDocs customizes the MockMvc bean to use Spring REST Docs when testing servlet-
based web applications. You can inject it by using @Autowired and use it in your tests as you
normally would when using Mock MVC and Spring REST Docs, as shown in the following example:
141
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
@WebMvcTest(UserController.class)
@AutoConfigureRestDocs
class MyUserDocumentationTests {
@Autowired
private MockMvc mvc;
@Test
void listUsers() throws Exception {
this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andDo(document("list-users"));
}
If you require more control over Spring REST Docs configuration than offered by the attributes of
@AutoConfigureRestDocs, you can use a RestDocsMockMvcConfigurationCustomizer bean, as shown in
the following example:
142
import
org.springframework.boot.test.autoconfigure.restdocs.RestDocsMockMvcConfigurationCusto
mizer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer;
import org.springframework.restdocs.templates.TemplateFormats;
@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsMockMvcConfigurationCustomizer
{
@Override
public void customize(MockMvcRestDocumentationConfigurer configurer) {
configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
}
If you want to make use of Spring REST Docs support for a parameterized output directory, you can
create a RestDocumentationResultHandler bean. The auto-configuration calls alwaysDo with this result
handler, thereby causing each MockMvc call to automatically generate the default snippets. The
following example shows a RestDocumentationResultHandler being defined:
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
@TestConfiguration(proxyBeanMethods = false)
public class MyResultHandlerConfiguration {
@Bean
public RestDocumentationResultHandler restDocumentation() {
return MockMvcRestDocumentation.document("{method-name}");
}
@AutoConfigureRestDocs can also be used with WebTestClient when testing reactive web applications.
You can inject it by using @Autowired and use it in your tests as you normally would when using
@WebFluxTest and Spring REST Docs, as shown in the following example:
143
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.test.web.reactive.server.WebTestClient;
import static
org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
@WebFluxTest
@AutoConfigureRestDocs
class MyUsersDocumentationTests {
@Autowired
private WebTestClient webTestClient;
@Test
void listUsers() {
this.webTestClient
.get().uri("/")
.exchange()
.expectStatus()
.isOk()
.expectBody()
.consumeWith(document("list-users"));
}
If you require more control over Spring REST Docs configuration than offered by the attributes of
@AutoConfigureRestDocs, you can use a RestDocsWebTestClientConfigurationCustomizer bean, as
shown in the following example:
144
import
org.springframework.boot.test.autoconfigure.restdocs.RestDocsWebTestClientConfiguratio
nCustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import
org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;
@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements
RestDocsWebTestClientConfigurationCustomizer {
@Override
public void customize(WebTestClientRestDocumentationConfigurer configurer) {
configurer.snippets().withEncoding("UTF-8");
}
If you want to make use of Spring REST Docs support for a parameterized output directory, you can
use a WebTestClientBuilderCustomizer to configure a consumer for every entity exchange result. The
following example shows such a WebTestClientBuilderCustomizer being defined:
import org.springframework.boot.test.context.TestConfiguration;
import
org.springframework.boot.test.web.reactive.server.WebTestClientBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import static
org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
@TestConfiguration(proxyBeanMethods = false)
public class MyWebTestClientBuilderCustomizerConfiguration {
@Bean
public WebTestClientBuilderCustomizer restDocumentation() {
return (builder) -> builder.entityExchangeResultConsumer(document("{method-
name}"));
}
145
import io.restassured.specification.RequestSpecification;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestDocs
class MyUserDocumentationTests {
@Test
void listUsers(@Autowired RequestSpecification documentationSpec, @LocalServerPort
int port) {
given(documentationSpec)
.filter(document("list-users"))
.when()
.port(port)
.get("/")
.then().assertThat()
.statusCode(is(200));
}
If you require more control over Spring REST Docs configuration than offered by the attributes of
@AutoConfigureRestDocs, a RestDocsRestAssuredConfigurationCustomizer bean can be used, as shown
in the following example:
146
import
org.springframework.boot.test.autoconfigure.restdocs.RestDocsRestAssuredConfigurationC
ustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import
org.springframework.restdocs.restassured.RestAssuredRestDocumentationConfigurer;
import org.springframework.restdocs.templates.TemplateFormats;
@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements
RestDocsRestAssuredConfigurationCustomizer {
@Override
public void customize(RestAssuredRestDocumentationConfigurer configurer) {
configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
}
You can use @WebServiceClientTest to test applications that call web services using the Spring Web
Services project. By default, it configures a mock WebServiceServer bean and automatically
customizes your WebServiceTemplateBuilder. (For more about using Web Services with Spring Boot,
see "Web Services", earlier in this chapter.)
147
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.boot.test.autoconfigure.webservices.client.WebServiceClientTest;
import org.springframework.ws.test.client.MockWebServiceServer;
import org.springframework.xml.transform.StringSource;
@WebServiceClientTest(SomeWebService.class)
class MyWebServiceClientTests {
@Autowired
private MockWebServiceServer server;
@Autowired
private SomeWebService someWebService;
@Test
void mockServerCall() {
this.server
.expect(payload(new StringSource("<request/>")))
.andRespond(withPayload(new
StringSource("<response><status>200</status></response>")));
assertThat(this.someWebService.test())
.extracting(Response::getStatus)
.isEqualTo(200);
}
You can use @WebServiceServerTest to test applications that implement web services using the
Spring Web Services project. By default, it configures a MockWebServiceClient bean that can be used
to call your web service endpoints. (For more about using Web Services with Spring Boot, see "Web
Services", earlier in this chapter.)
148
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.boot.test.autoconfigure.webservices.server.WebServiceServerTest;
import org.springframework.ws.test.server.MockWebServiceClient;
import org.springframework.ws.test.server.RequestCreators;
import org.springframework.ws.test.server.ResponseMatchers;
import org.springframework.xml.transform.StringSource;
@WebServiceServerTest(ExampleEndpoint.class)
class MyWebServiceServerTests {
@Autowired
private MockWebServiceClient client;
@Test
void mockServerCall() {
this.client
.sendRequest(RequestCreators.withPayload(new
StringSource("<ExampleRequest/>")))
.andExpect(ResponseMatchers.payload(new
StringSource("<ExampleResponse>42</ExampleResponse>")));
}
Each slice provides one or more @AutoConfigure… annotations that namely defines the auto-
configurations that should be included as part of a slice. Additional auto-configurations can be
added on a test-by-test basis by creating a custom @AutoConfigure… annotation or by adding
@ImportAutoConfiguration to the test as shown in the following example:
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration;
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
@JdbcTest
@ImportAutoConfiguration(IntegrationAutoConfiguration.class)
class MyJdbcTests {
Make sure to not use the regular @Import annotation to import auto-configurations
NOTE
as they are handled in a specific way by Spring Boot.
149
Alternatively, additional auto-configurations can be added for any use of a slice annotation by
registering them in META-INF/spring.factories as shown in the following example:
org.springframework.boot.test.autoconfigure.jdbc.JdbcTest=com.example.IntegrationAutoC
onfiguration
If you structure your code in a sensible way, your @SpringBootApplication class is used by default as
the configuration of your tests.
It then becomes important not to litter the application’s main class with configuration settings that
are specific to a particular area of its functionality.
Assume that you are using Spring Batch and you rely on the auto-configuration for it. You could
define your @SpringBootApplication as follows:
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableBatchProcessing
public class MyApplication {
// ...
Because this class is the source configuration for the test, any slice test actually tries to start Spring
Batch, which is definitely not what you want to do. A recommended approach is to move that area-
specific configuration to a separate @Configuration class at the same level as your application, as
shown in the following example:
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableBatchProcessing
public class MyBatchConfiguration {
// ...
150
Depending on the complexity of your application, you may either have a single
@Configuration class for your customizations or one class per domain area. The
NOTE
latter approach lets you enable it in one of your tests, if necessary, with the @Import
annotation.
Test slices exclude @Configuration classes from scanning. For example, for a @WebMvcTest, the
following configuration will not include the given WebMvcConfigurer bean in the application context
loaded by the test slice:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration(proxyBeanMethods = false)
public class MyWebConfiguration {
@Bean
public WebMvcConfigurer testConfigurer() {
return new WebMvcConfigurer() {
// ...
};
}
The configuration below will, however, cause the custom WebMvcConfigurer to be loaded by the test
slice.
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {
// ...
Another source of confusion is classpath scanning. Assume that, while you structured your code in
a sensible way, you need to scan an additional package. Your application may resemble the
following code:
151
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan({ "com.example.app", "com.example.another" })
public class MyApplication {
// ...
Doing so effectively overrides the default component scan directive with the side effect of scanning
those two packages regardless of the slice that you chose. For instance, a @DataJpaTest seems to
suddenly scan components and user configurations of your application. Again, moving the custom
directive to a separate class is a good way to fix this issue.
If this is not an option for you, you can create a @SpringBootConfiguration somewhere
TIP in the hierarchy of your test so that it is used instead. Alternatively, you can specify a
source for your test, which disables the behavior of finding a default one.
Spock 2.x can be used to test a Spring Boot application. To do so, add a dependency on Spock’s
spock-spring module to your application’s build. spock-spring integrates Spring’s test framework
into Spock. See the documentation for Spock’s Spring module for further details.
A few test utility classes that are generally useful when testing your application are packaged as
part of spring-boot.
ConfigDataApplicationContextInitializer
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;
// ...
152
Using ConfigDataApplicationContextInitializer alone does not provide support for
@Value("${…}") injection. Its only job is to ensure that application.properties files
NOTE are loaded into Spring’s Environment. For @Value support, you need to either
additionally configure a PropertySourcesPlaceholderConfigurer or use
@SpringBootTest, which auto-configures one for you.
TestPropertyValues
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.mock.env.MockEnvironment;
class MyEnvironmentTests {
@Test
void testPropertySources() {
MockEnvironment environment = new MockEnvironment();
TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment);
assertThat(environment.getProperty("name")).isEqualTo("Boot");
}
OutputCapture
OutputCapture is a JUnit Extension that you can use to capture System.out and System.err output. To
use add @ExtendWith(OutputCaptureExtension.class) and inject CapturedOutput as an argument to
your test class constructor or test method as follows:
153
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
@ExtendWith(OutputCaptureExtension.class)
class MyOutputCaptureTests {
@Test
void testName(CapturedOutput output) {
System.out.println("Hello World!");
assertThat(output).contains("World");
}
TestRestTemplate
Spring Framework 5.0 provides a new WebTestClient that works for WebFlux
TIP integration tests and both WebFlux and MVC end-to-end testing. It provides a fluent
API for assertions, unlike TestRestTemplate.
It is recommended, but not mandatory, to use the Apache HTTP Client (version 4.3.2 or better). If
you have that on your classpath, the TestRestTemplate responds by configuring the client
appropriately. If you do use Apache’s HTTP client, some additional test-friendly features are
enabled:
• Redirects are not followed (so you can assert the response location).
TestRestTemplate can be instantiated directly in your integration tests, as shown in the following
example:
154
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
class MyTests {
@Test
void testRequest() throws Exception {
ResponseEntity<String> headers =
this.template.getForEntity("https://myhost.example.com/example", String.class);
assertThat(headers.getHeaders().getLocation()).hasHost("other.example.com");
}
155
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MySpringBootTests {
@Autowired
private TestRestTemplate template;
@Test
void testRequest() {
HttpHeaders headers = this.template.getForEntity("/example",
String.class).getHeaders();
assertThat(headers.getLocation()).hasHost("other.example.com");
}
@TestConfiguration(proxyBeanMethods = false)
static class RestTemplateBuilderConfiguration {
@Bean
RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1))
.setReadTimeout(Duration.ofSeconds(1));
}
}
156
build your own auto-configuration and then we move on to the typical steps required to create a
custom starter.
TIP A demo project is available to showcase how you can create a starter step-by-step.
You can browse the source code of spring-boot-autoconfigure to see the @Configuration classes that
Spring provides (see the META-INF/spring.factories file).
Spring Boot checks for the presence of a META-INF/spring.factories file within your published jar.
The file should list your configuration classes under the EnableAutoConfiguration key, as shown in
the following example:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
Auto-configurations must be loaded that way only. Make sure that they are defined
in a specific package space and that they are never the target of component
NOTE
scanning. Furthermore, auto-configuration classes should not enable component
scanning to find additional components. Specific @Imports should be used instead.
If you want to order certain auto-configurations that should not have any direct knowledge of each
other, you can also use @AutoConfigureOrder. That annotation has the same semantic as the regular
@Order annotation but provides a dedicated order for auto-configuration classes.
As with standard @Configuration classes, the order in which auto-configuration classes are applied
only affects the order in which their beans are defined. The order in which those beans are
subsequently created is unaffected and is determined by each bean’s dependencies and any
@DependsOn relationships.
You almost always want to include one or more @Conditional annotations on your auto-
157
configuration class. The @ConditionalOnMissingBean annotation is one common example that is used
to allow developers to override auto-configuration if they are not happy with your defaults.
Spring Boot includes a number of @Conditional annotations that you can reuse in your own code by
annotating @Configuration classes or individual @Bean methods. These annotations include:
• Class Conditions
• Bean Conditions
• Property Conditions
• Resource Conditions
Class Conditions
This mechanism does not apply the same way to @Bean methods where typically the return type is
the target of the condition: before the condition on the method applies, the JVM will have loaded
the class and potentially processed method references which will fail if the class is not present.
To handle this scenario, a separate @Configuration class can be used to isolate the condition, as
shown in the following example:
158
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
// Some conditions ...
public class MyAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(SomeService.class)
public static class SomeServiceConfiguration {
@Bean
@ConditionalOnMissingBean
public SomeService someService() {
return new SomeService();
}
}
Bean Conditions
When placed on a @Bean method, the target type defaults to the return type of the method, as shown
in the following example:
159
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SomeService someService() {
return new SomeService();
}
In the preceding example, the someService bean is going to be created if no bean of type SomeService
is already contained in the ApplicationContext.
You need to be very careful about the order in which bean definitions are added, as
these conditions are evaluated based on what has been processed so far. For this
TIP reason, we recommend using only @ConditionalOnBean and @ConditionalOnMissingBean
annotations on auto-configuration classes (since these are guaranteed to load after
any user-defined bean definitions have been added).
When declaring a @Bean method, provide as much type information as possible in the
method’s return type. For example, if your bean’s concrete class implements an
interface the bean method’s return type should be the concrete class and not the
TIP
interface. Providing as much type information as possible in @Bean methods is
particularly important when using bean conditions as their evaluation can only rely
upon to type information that is available in the method signature.
Property Conditions
Resource Conditions
The @ConditionalOnResource annotation lets configuration be included only when a specific resource
160
is present. Resources can be specified by using the usual Spring conventions, as shown in the
following example: file:/home/user/test.dat.
An auto-configuration can be affected by many factors: user configuration (@Bean definition and
Environment customization), condition evaluation (presence of a particular library), and others.
Concretely, each test should create a well defined ApplicationContext that represents a combination
of those customizations. ApplicationContextRunner provides a great way to achieve that.
ApplicationContextRunner is usually defined as a field of the test class to gather the base, common
configuration. The following example makes sure that MyServiceAutoConfiguration is always
invoked:
Each test can use the runner to represent a particular use case. For instance, the sample below
invokes a user configuration (UserConfiguration) and checks that the auto-configuration backs off
properly. Invoking run provides a callback context that can be used with AssertJ.
161
@Test
void defaultServiceBacksOff() {
this.contextRunner.withUserConfiguration(UserConfiguration.class).run((context) ->
{
assertThat(context).hasSingleBean(MyService.class);
assertThat(context).getBean("myCustomService").isSameAs(context.getBean(MyService.clas
s));
});
}
@Configuration(proxyBeanMethods = false)
static class UserConfiguration {
@Bean
MyService myCustomService() {
return new MyService("mine");
}
It is also possible to easily customize the Environment, as shown in the following example:
@Test
void serviceNameCanBeConfigured() {
this.contextRunner.withPropertyValues("user.name=test123").run((context) -> {
assertThat(context).hasSingleBean(MyService.class);
assertThat(context.getBean(MyService.class).getName()).isEqualTo("test123");
});
}
The runner can also be used to display the ConditionEvaluationReport. The report can be printed at
INFO or DEBUG level. The following example shows how to use the
ConditionEvaluationReportLoggingListener to print the report in auto-configuration tests.
162
import org.junit.jupiter.api.Test;
import
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListene
r;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
class MyConditionEvaluationReportingTests {
@Test
void autoConfigTest() {
new ApplicationContextRunner()
.withInitializer(new
ConditionEvaluationReportLoggingListener(LogLevel.INFO))
.run((context) -> {
// Test something...
});
}
If you need to test an auto-configuration that only operates in a servlet or reactive web application
context, use the WebApplicationContextRunner or ReactiveWebApplicationContextRunner respectively.
It is also possible to test what happens when a particular class and/or package is not present at
runtime. Spring Boot ships with a FilteredClassLoader that can easily be used by the runner. In the
following example, we assert that if MyService is not present, the auto-configuration is properly
disabled:
@Test
void serviceIsIgnoredIfLibraryIsNotPresent() {
this.contextRunner.withClassLoader(new FilteredClassLoader(MyService.class))
.run((context) -> assertThat(context).doesNotHaveBean("myService"));
}
A typical Spring Boot starter contains code to auto-configure and customize the infrastructure of a
given technology, let’s call that "acme". To make it easily extensible, a number of configuration keys
in a dedicated namespace can be exposed to the environment. Finally, a single "starter" dependency
is provided to help users get started as easily as possible.
163
• The autoconfigure module that contains the auto-configuration code for "acme".
• The starter module that provides a dependency to the autoconfigure module as well as "acme"
and any additional dependencies that are typically useful. In a nutshell, adding the starter
should provide everything needed to start using that library.
This separation in two modules is in no way necessary. If "acme" has several flavors, options or
optional features, then it is better to separate the auto-configuration as you can clearly express the
fact some features are optional. Besides, you have the ability to craft a starter that provides an
opinion about those optional dependencies. At the same time, others can rely only on the
autoconfigure module and craft their own starter with different opinions.
If the auto-configuration is relatively straightforward and does not have optional feature, merging
the two modules in the starter is definitely an option.
Naming
You should make sure to provide a proper namespace for your starter. Do not start your module
names with spring-boot, even if you use a different Maven groupId. We may offer official support
for the thing you auto-configure in the future.
As a rule of thumb, you should name a combined module after the starter. For example, assume
that you are creating a starter for "acme" and that you name the auto-configure module acme-
spring-boot and the starter acme-spring-boot-starter. If you only have one module that combines
the two, name it acme-spring-boot-starter.
Configuration keys
If your starter provides configuration keys, use a unique namespace for them. In particular, do not
include your keys in the namespaces that Spring Boot uses (such as server, management, spring, and
so on). If you use the same namespace, we may modify these namespaces in the future in ways that
break your modules. As a rule of thumb, prefix all your keys with a namespace that you own (for
example acme).
Make sure that configuration keys are documented by adding field javadoc for each property, as
shown in the following example:
164
import java.time.Duration;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("acme")
public class AcmeProperties {
/**
* Whether to check the location of acme resources.
*/
private boolean checkLocation = true;
/**
* Timeout for establishing a connection to the acme server.
*/
private Duration loginTimeout = Duration.ofSeconds(3);
You should only use plain text with @ConfigurationProperties field Javadoc, since
NOTE
they are not processed before being added to the JSON.
Here are some rules we follow internally to make sure descriptions are consistent:
• Use java.time.Duration rather than long and describe the default unit if it differs from
milliseconds, such as "If a duration suffix is not specified, seconds will be used".
• Do not provide the default value in the description unless it has to be determined at runtime.
165
Make sure to trigger meta-data generation so that IDE assistance is available for your keys as well.
You may want to review the generated metadata (META-INF/spring-configuration-metadata.json) to
make sure your keys are properly documented. Using your own starter in a compatible IDE is also a
good idea to validate that quality of the metadata.
The autoconfigure module contains everything that is necessary to get started with the library. It
may also contain configuration key definitions (such as @ConfigurationProperties) and any callback
interface that can be used to further customize how the components are initialized.
You should mark the dependencies to the library as optional so that you can include
TIP the autoconfigure module in your projects more easily. If you do it that way, the library
is not provided and, by default, Spring Boot backs off.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
If you have defined auto-configurations directly in your application, make sure to configure the
spring-boot-maven-plugin to prevent the repackage goal from adding the dependency into the fat jar:
166
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-
processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
With Gradle 4.5 and earlier, the dependency should be declared in the compileOnly configuration, as
shown in the following example:
dependencies {
compileOnly "org.springframework.boot:spring-boot-autoconfigure-processor"
}
With Gradle 4.6 and later, the dependency should be declared in the annotationProcessor
configuration, as shown in the following example:
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-autoconfigure-processor"
}
Starter Module
The starter is really an empty jar. Its only purpose is to provide the necessary dependencies to work
with the library. You can think of it as an opinionated view of what is required to get started.
Do not make assumptions about the project in which your starter is added. If the library you are
auto-configuring typically requires other starters, mention them as well. Providing a proper set of
default dependencies may be hard if the number of optional dependencies is high, as you should
avoid including dependencies that are unnecessary for a typical usage of the library. In other
words, you should not include optional dependencies.
167
Either way, your starter must reference the core Spring Boot starter (spring-boot-
starter) directly or indirectly (there is no need to add it if your starter relies on
NOTE
another starter). If a project is created with only your custom starter, Spring Boot’s
core features will be honoured by the presence of the core starter.
Spring Boot provides Kotlin support by leveraging the support in other Spring projects such as
Spring Framework, Spring Data, and Reactor. See the Spring Framework Kotlin support
documentation for more information.
The easiest way to start with Spring Boot and Kotlin is to follow this comprehensive tutorial. You
can create new Kotlin projects by using start.spring.io. Feel free to join the #spring channel of Kotlin
Slack or ask a question with the spring and kotlin tags on Stack Overflow if you need support.
7.10.1. Requirements
Spring Boot requires at least Kotlin 1.3.x and manages a suitable Kotlin version through
dependency management. To use Kotlin, org.jetbrains.kotlin:kotlin-stdlib and
org.jetbrains.kotlin:kotlin-reflect must be present on the classpath. The kotlin-stdlib variants
kotlin-stdlib-jdk7 and kotlin-stdlib-jdk8 can also be used.
Since Kotlin classes are final by default, you are likely to want to configure kotlin-spring plugin in
order to automatically open Spring-annotated classes so that they can be proxied.
Jackson’s Kotlin module is required for serializing / deserializing JSON data in Kotlin. It is
automatically registered when found on the classpath. A warning message is logged if Jackson and
Kotlin are present but the Jackson Kotlin module is not.
These dependencies and plugins are provided by default if one bootstraps a Kotlin
TIP
project on start.spring.io.
7.10.2. Null-safety
One of Kotlin’s key features is null-safety. It deals with null values at compile time rather than
deferring the problem to runtime and encountering a NullPointerException. This helps to eliminate
a common source of bugs without paying the cost of wrappers like Optional. Kotlin also allows using
functional constructs with nullable values as described in this comprehensive guide to null-safety
in Kotlin.
Although Java does not allow one to express null-safety in its type system, Spring Framework,
Spring Data, and Reactor now provide null-safety of their API through tooling-friendly annotations.
By default, types from Java APIs used in Kotlin are recognized as platform types for which null-
checks are relaxed. Kotlin’s support for JSR 305 annotations combined with nullability annotations
provide null-safety for the related Spring API in Kotlin.
168
The JSR 305 checks can be configured by adding the -Xjsr305 compiler flag with the following
options: -Xjsr305={strict|warn|ignore}. The default behavior is the same as -Xjsr305=warn. The
strict value is required to have null-safety taken in account in Kotlin types inferred from Spring
API but should be used with the knowledge that Spring API nullability declaration could evolve
even between minor releases and more checks may be added in the future).
Generic type arguments, varargs and array elements nullability are not yet
WARNING supported. See SPR-15942 for up-to-date information. Also be aware that
Spring Boot’s own API is not yet annotated.
runApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class MyApplication
runApplication<MyApplication>(*args) {
setBannerMode(OFF)
}
Extensions
Kotlin extensions provide the ability to extend existing classes with additional functionality. The
Spring Boot Kotlin API makes use of these extensions to add new Kotlin specific conveniences to
existing APIs.
In order to avoid mixing different versions of Kotlin dependencies on the classpath, Spring Boot
169
imports the Kotlin BOM.
With Maven, the Kotlin version can be customized by setting the kotlin.version property and
plugin management is provided for kotlin-maven-plugin. With Gradle, the Spring Boot plugin
automatically aligns the kotlin.version with the version of the Kotlin plugin.
Spring Boot also manages the version of Coroutines dependencies by importing the Kotlin
Coroutines BOM. The version can be customized by setting the kotlin-coroutines.version property.
7.10.5. @ConfigurationProperties
@ConstructorBinding
@ConfigurationProperties("example.kotlin")
data class KotlinExampleProperties(
val name: String,
val description: String,
val myService: MyService) {
To generate your own metadata using the annotation processor, kapt should be
configured with the spring-boot-configuration-processor dependency. Note that some
TIP
features (such as detecting the default value or deprecated items) are not working due
to limitations in the model kapt provides.
7.10.6. Testing
While it is possible to use JUnit 4 to test Kotlin code, JUnit 5 is provided by default and is
recommended. JUnit 5 enables a test class to be instantiated once and reused for all of the class’s
tests. This makes it possible to use @BeforeAll and @AfterAll annotations on non-static methods,
which is a good fit for Kotlin.
To mock Kotlin classes, MockK is recommended. If you need the Mockk equivalent of the Mockito
specific @MockBean and @SpyBean annotations, you can use SpringMockK which provides similar
@MockkBean and @SpykBean annotations.
170
7.10.7. Resources
Further reading
• Kotlin blog
• Awesome Kotlin
Examples
• spring-kotlin-fullstack: WebFlux Kotlin fullstack example with Kotlin2js for frontend instead of
JavaScript or TypeScript
• spring-kotlin-deepdive: a step by step migration for Boot 1.0 + Java to Boot 2.0 + Kotlin
If you are comfortable with Spring Boot’s core features, you can continue on and read about
production-ready features.
171
Chapter 8. Web
Spring Boot is well suited for web application development. You can create a self-contained HTTP
server by using embedded Tomcat, Jetty, Undertow, or Netty. Most web applications use the spring-
boot-starter-web module to get up and running quickly. You can also choose to build reactive web
applications by using the spring-boot-starter-webflux module.
If you have not yet developed a Spring Boot web application, you can follow the "Hello World!"
example in the Getting started section.
The Spring Web MVC framework (often referred to as “Spring MVC”) is a rich “model view
controller” web framework. Spring MVC lets you create special @Controller or @RestController
beans to handle incoming HTTP requests. Methods in your controller are mapped to HTTP by using
@RequestMapping annotations.
The following code shows a typical @RestController that serves JSON data:
172
import java.util.List;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/users")
public class MyRestController {
@GetMapping("/{user}")
public User getUser(@PathVariable Long userId) {
return this.userRepository.findById(userId).get();
}
@GetMapping("/{user}/customers")
public List<Customer> getUserCustomers(@PathVariable Long userId) {
return
this.userRepository.findById(userId).map(this.customerRepository::findByUser).get();
}
@DeleteMapping("/{user}")
public void deleteUser(@PathVariable Long userId) {
this.userRepository.deleteById(userId);
}
Spring MVC is part of the core Spring Framework, and detailed information is available in the
reference documentation. There are also several guides that cover Spring MVC available at
spring.io/guides.
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
173
• Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
• Support for serving static resources, including support for WebJars (covered later in this
document).
If you want to keep those Spring Boot MVC customizations and make more MVC customizations
(interceptors, formatters, view controllers, and other features), you can add your own
@Configuration class of type WebMvcConfigurer but without @EnableWebMvc.
If you want to take complete control of Spring MVC, you can add your own @Configuration
annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated
DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.
Spring MVC uses a different ConversionService to the one used to convert values
from your application.properties or application.yaml file. It means that Period,
Duration and DataSize converters are not available and that @DurationUnit and
@DataSizeUnit annotations will be ignored.
NOTE
If you want to customize the ConversionService used by Spring MVC, you can
provide a WebMvcConfigurer bean with an addFormatters method. From this method
you can register any converter that you like, or you can delegate to the static
methods available on ApplicationConversionService.
HttpMessageConverters
Spring MVC uses the HttpMessageConverter interface to convert HTTP requests and responses.
Sensible defaults are included out of the box. For example, objects can be automatically converted
to JSON (by using the Jackson library) or XML (by using the Jackson XML extension, if available, or
by using JAXB if the Jackson XML extension is not available). By default, strings are encoded in UTF-
8.
If you need to add or customize converters, you can use Spring Boot’s HttpMessageConverters class,
as shown in the following listing:
174
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
@Configuration(proxyBeanMethods = false)
public class MyHttpMessageConvertersConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = new AdditionalHttpMessageConverter();
HttpMessageConverter<?> another = new AnotherHttpMessageConverter();
return new HttpMessageConverters(additional, another);
}
Any HttpMessageConverter bean that is present in the context is added to the list of converters. You
can also override default converters in the same way.
If you use Jackson to serialize and deserialize JSON data, you might want to write your own
JsonSerializer and JsonDeserializer classes. Custom serializers are usually registered with Jackson
through a module, but Spring Boot provides an alternative @JsonComponent annotation that makes it
easier to directly register Spring Beans.
175
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.boot.jackson.JsonComponent;
@JsonComponent
public class MyJsonComponent {
@Override
public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider
serializers) throws IOException {
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
}
}
@Override
public MyObject deserialize(JsonParser jsonParser, DeserializationContext
ctxt)
throws IOException, JsonProcessingException {
ObjectCodec codec = jsonParser.getCodec();
JsonNode tree = codec.readTree(jsonParser);
String name = tree.get("name").textValue();
int age = tree.get("age").intValue();
return new MyObject(name, age);
}
}
All @JsonComponent beans in the ApplicationContext are automatically registered with Jackson.
Because @JsonComponent is meta-annotated with @Component, the usual component-scanning rules
apply.
Spring Boot also provides JsonObjectSerializer and JsonObjectDeserializer base classes that
176
provide useful alternatives to the standard Jackson versions when serializing objects. See
JsonObjectSerializer and JsonObjectDeserializer in the Javadoc for details.
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.boot.jackson.JsonObjectDeserializer;
import org.springframework.boot.jackson.JsonObjectSerializer;
@JsonComponent
public class MyJsonComponent {
@Override
protected void serializeObject(MyObject value, JsonGenerator jgen,
SerializerProvider provider)
throws IOException {
jgen.writeStringField("name", value.getName());
jgen.writeNumberField("age", value.getAge());
}
}
@Override
protected MyObject deserializeObject(JsonParser jsonParser,
DeserializationContext context, ObjectCodec codec,
JsonNode tree) throws IOException {
String name = nullSafeValue(tree.get("name"), String.class);
int age = nullSafeValue(tree.get("age"), Integer.class);
return new MyObject(name, age);
}
}
177
MessageCodesResolver
Spring MVC has a strategy for generating error codes for rendering error messages from binding
errors: MessageCodesResolver. If you set the spring.mvc.message-codes-resolver-format property
PREFIX_ERROR_CODE or POSTFIX_ERROR_CODE, Spring Boot creates one for you (see the enumeration in
DefaultMessageCodesResolver.Format).
Static Content
By default, Spring Boot serves static content from a directory called /static (or /public or
/resources or /META-INF/resources) in the classpath or from the root of the ServletContext. It uses
the ResourceHttpRequestHandler from Spring MVC so that you can modify that behavior by adding
your own WebMvcConfigurer and overriding the addResourceHandlers method.
In a stand-alone web application, the default servlet from the container is also enabled and acts as
a fallback, serving content from the root of the ServletContext if Spring decides not to handle it.
Most of the time, this does not happen (unless you modify the default MVC configuration), because
Spring can always handle requests through the DispatcherServlet.
By default, resources are mapped on /**, but you can tune that with the spring.mvc.static-path-
pattern property. For instance, relocating all resources to /resources/** can be achieved as follows:
Properties
spring.mvc.static-path-pattern=/resources/**
Yaml
spring:
mvc:
static-path-pattern: "/resources/**"
You can also customize the static resource locations by using the spring.web.resources.static-
locations property (replacing the default values with a list of directory locations). The root servlet
context path, "/", is automatically added as a location as well.
In addition to the “standard” static resource locations mentioned earlier, a special case is made for
Webjars content. Any resources with a path in /webjars/** are served from jar files if they are
packaged in the Webjars format.
Spring Boot also supports the advanced resource handling features provided by Spring MVC,
allowing use cases such as cache-busting static resources or using version agnostic URLs for
Webjars.
To use version agnostic URLs for Webjars, add the webjars-locator-core dependency. Then declare
178
your Webjar. Using jQuery as an example, adding "/webjars/jquery/jquery.min.js" results in
"/webjars/jquery/x.y.z/jquery.min.js" where x.y.z is the Webjar version.
To use cache busting, the following configuration configures a cache busting solution for all static
resources, effectively adding a content hash, such as <link href="/css/spring-
2a2d595e6ed9a0b24f027f2b63b134d6.css"/>, in URLs:
Properties
spring.web.resources.chain.strategy.content.enabled=true
spring.web.resources.chain.strategy.content.paths=/**
Yaml
spring:
web:
resources:
chain:
strategy:
content:
enabled: true
paths: "/**"
When loading resources dynamically with, for example, a JavaScript module loader, renaming files
is not an option. That is why other strategies are also supported and can be combined. A "fixed"
strategy adds a static version string in the URL without changing the file name, as shown in the
following example:
Properties
spring.web.resources.chain.strategy.content.enabled=true
spring.web.resources.chain.strategy.content.paths=/**
spring.web.resources.chain.strategy.fixed.enabled=true
spring.web.resources.chain.strategy.fixed.paths=/js/lib/
spring.web.resources.chain.strategy.fixed.version=v12
179
Yaml
spring:
web:
resources:
chain:
strategy:
content:
enabled: true
paths: "/**"
fixed:
enabled: true
paths: "/js/lib/"
version: "v12"
With this configuration, JavaScript modules located under "/js/lib/" use a fixed versioning
strategy ("/v12/js/lib/mymodule.js"), while other resources still use the content one (<link
href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>).
This feature has been thoroughly described in a dedicated blog post and in Spring
TIP
Framework’s reference documentation.
Welcome Page
Spring Boot supports both static and templated welcome pages. It first looks for an index.html file in
the configured static content locations. If one is not found, it then looks for an index template. If
either is found, it is automatically used as the welcome page of the application.
Spring MVC can map incoming HTTP requests to handlers by looking at the request path and
matching it to the mappings defined in your application (for example, @GetMapping annotations on
Controller methods).
Spring Boot chooses to disable suffix pattern matching by default, which means that requests like
"GET /projects/spring-boot.json" will not be matched to @GetMapping("/projects/spring-boot")
mappings. This is considered as a best practice for Spring MVC applications. This feature was
mainly useful in the past for HTTP clients which did not send proper "Accept" request headers; we
needed to make sure to send the correct Content Type to the client. Nowadays, Content Negotiation
is much more reliable.
There are other ways to deal with HTTP clients that do not consistently send proper "Accept"
request headers. Instead of using suffix matching, we can use a query parameter to ensure that
requests like "GET /projects/spring-boot?format=json" will be mapped to
@GetMapping("/projects/spring-boot"):
180
Properties
spring.mvc.contentnegotiation.favor-parameter=true
Yaml
spring:
mvc:
contentnegotiation:
favor-parameter: true
Properties
spring.mvc.contentnegotiation.favor-parameter=true
spring.mvc.contentnegotiation.parameter-name=myparam
Yaml
spring:
mvc:
contentnegotiation:
favor-parameter: true
parameter-name: "myparam"
Most standard media types are supported out-of-the-box, but you can also define new ones:
Properties
spring.mvc.contentnegotiation.media-types.markdown=text/markdown
Yaml
spring:
mvc:
contentnegotiation:
media-types:
markdown: "text/markdown"
Suffix pattern matching is deprecated and will be removed in a future release. If you understand
the caveats and would still like your application to use suffix pattern matching, the following
configuration is required:
181
Properties
spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-suffix-pattern=true
Yaml
spring:
mvc:
contentnegotiation:
favor-path-extension: true
pathmatch:
use-suffix-pattern: true
Alternatively, rather than open all suffix patterns, it is more secure to only support registered suffix
patterns:
Properties
spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-registered-suffix-pattern=true
Yaml
spring:
mvc:
contentnegotiation:
favor-path-extension: true
pathmatch:
use-registered-suffix-pattern: true
As of Spring Framework 5.3, Spring MVC supports several implementation strategies for matching
request paths to Controller handlers. It was previously only supporting the AntPathMatcher strategy,
but it now also offers PathPatternParser. Spring Boot now provides a configuration property to
choose and opt in the new strategy:
Properties
spring.mvc.pathmatch.matching-strategy=path-pattern-parser
Yaml
spring:
mvc:
pathmatch:
matching-strategy: "path-pattern-parser"
182
For more details on why you should consider this new implementation, see the dedicated blog post.
ConfigurableWebBindingInitializer
Spring MVC uses a WebBindingInitializer to initialize a WebDataBinder for a particular request. If you
create your own ConfigurableWebBindingInitializer @Bean, Spring Boot automatically configures
Spring MVC to use it.
Template Engines
As well as REST web services, you can also use Spring MVC to serve dynamic HTML content. Spring
MVC supports a variety of templating technologies, including Thymeleaf, FreeMarker, and JSPs.
Also, many other templating engines include their own Spring MVC integrations.
Spring Boot includes auto-configuration support for the following templating engines:
• FreeMarker
• Groovy
• Thymeleaf
• Mustache
If possible, JSPs should be avoided. There are several known limitations when using
TIP
them with embedded servlet containers.
When you use one of these templating engines with the default configuration, your templates are
picked up automatically from src/main/resources/templates.
Depending on how you run your application, your IDE may order the classpath
differently. Running your application in the IDE from its main method results in a
different ordering than when you run your application by using Maven or Gradle or
TIP
from its packaged jar. This can cause Spring Boot to fail to find the expected template.
If you have this problem, you can reorder the classpath in the IDE to place the
module’s classes and resources first.
Error Handling
By default, Spring Boot provides an /error mapping that handles all errors in a sensible way, and it
is registered as a “global” error page in the servlet container. For machine clients, it produces a
JSON response with details of the error, the HTTP status, and the exception message. For browser
clients, there is a “whitelabel” error view that renders the same data in HTML format (to customize
it, add a View that resolves to error).
183
There are a number of server.error properties that can be set if you want to customize the default
error handling behavior. See the “Server Properties” section of the Appendix.
To replace the default behavior completely, you can implement ErrorController and register a bean
definition of that type or add a bean of type ErrorAttributes to use the existing mechanism but
replace the contents.
You can also define a class annotated with @ControllerAdvice to customize the JSON document to
return for a particular controller and/or exception type, as shown in the following example:
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import
org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@ControllerAdvice(basePackageClasses = SomeController.class)
public class MyControllerAdvice extends ResponseEntityExceptionHandler {
@ResponseBody
@ExceptionHandler(MyException.class)
public ResponseEntity<?> handleControllerException(HttpServletRequest request,
Throwable ex) {
HttpStatus status = getStatus(request);
return new ResponseEntity<>(new MyErrorBody(status.value(), ex.getMessage()),
status);
}
In the preceding example, if YourException is thrown by a controller defined in the same package as
184
SomeController, a JSON representation of the CustomErrorType POJO is used instead of the
ErrorAttributes representation.
In some cases, errors handled at the controller level are not recorded by the metrics infrastructure.
Applications can ensure that such exceptions are recorded with the request metrics by setting the
handled exception as a request attribute:
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
@Controller
public class MyController {
@ExceptionHandler(CustomException.class)
String handleCustomException(HttpServletRequest request, CustomException ex) {
request.setAttribute(ErrorAttributes.ERROR_ATTRIBUTE, ex);
return "errorView";
}
If you want to display a custom HTML error page for a given status code, you can add a file to an
/error directory. Error pages can either be static HTML (that is, added under any of the static
resource directories) or be built by using templates. The name of the file should be the exact status
code or a series mask.
For example, to map 404 to a static HTML file, your directory structure would be as follows:
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>
To map all 5xx errors by using a FreeMarker template, your directory structure would be as follows:
185
src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.ftlh
+- <other templates>
For more complex mappings, you can also add beans that implement the ErrorViewResolver
interface, as shown in the following example:
import java.util.Map;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.ModelAndView;
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus
status, Map<String, Object> model) {
// Use the request or status to optionally return a ModelAndView
if (status == HttpStatus.INSUFFICIENT_STORAGE) {
// We could add custom model values here
new ModelAndView("myview");
}
return null;
}
You can also use regular Spring MVC features such as @ExceptionHandler methods and
@ControllerAdvice. The ErrorController then picks up any unhandled exceptions.
For applications that do not use Spring MVC, you can use the ErrorPageRegistrar interface to
directly register ErrorPages. This abstraction works directly with the underlying embedded servlet
container and works even if you do not have a Spring MVC DispatcherServlet.
186
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
@Configuration(proxyBeanMethods = false)
public class MyErrorPagesConfiguration {
@Bean
public ErrorPageRegistrar errorPageRegistrar() {
return this::registerErrorPages;
}
If you register an ErrorPage with a path that ends up being handled by a Filter (as is
common with some non-Spring web frameworks, like Jersey and Wicket), then the
NOTE
Filter has to be explicitly registered as an ERROR dispatcher, as shown in the
following example:
import java.util.EnumSet;
import jakarta.servlet.DispatcherType;
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> myFilter() {
FilterRegistrationBean<MyFilter> registration = new
FilterRegistrationBean<>(new MyFilter());
// ...
registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
return registration;
}
187
Note that the default FilterRegistrationBean does not include the ERROR dispatcher type.
When deployed to a servlet container, Spring Boot uses its error page filter to forward a request
with an error status to the appropriate error page. This is necessary as the servlet specification does
not provide an API for registering error pages. Depending on the container that you are deploying
your war file to and the technologies that your application uses, some additional configuration may
be required.
The error page filter can only forward the request to the correct error page if the response has not
already been committed. By default, WebSphere Application Server 8.0 and later commits the
response upon successful completion of a servlet’s service method. You should disable this behavior
by setting com.ibm.ws.webcontainer.invokeFlushAfterService to false.
If you are using Spring Security and want to access the principal in an error page, you must
configure Spring Security’s filter to be invoked on error dispatches. To do so, set the
spring.security.filter.dispatcher-types property to async, error, forward, request.
CORS Support
Cross-origin resource sharing (CORS) is a W3C specification implemented by most browsers that
lets you specify in a flexible way what kind of cross-domain requests are authorized, instead of
using some less secure and less powerful approaches such as IFRAME or JSONP.
As of version 4.2, Spring MVC supports CORS. Using controller method CORS configuration with
@CrossOrigin annotations in your Spring Boot application does not require any specific
configuration. Global CORS configuration can be defined by registering a WebMvcConfigurer bean
with a customized addCorsMappings(CorsRegistry) method, as shown in the following example:
188
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration(proxyBeanMethods = false)
public class MyCorsConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
For servlet application, Spring Boot includes support for embedded Tomcat, Jetty, and Undertow
servers. Most developers use the appropriate “Starter” to obtain a fully configured instance. By
default, the embedded server listens for HTTP requests on port 8080.
When using an embedded servlet container, you can register servlets, filters, and all the listeners
(such as HttpSessionListener) from the servlet spec, either by using Spring beans or by scanning for
servlet components.
Any Servlet, Filter, or servlet *Listener instance that is a Spring bean is registered with the
embedded container. This can be particularly convenient if you want to refer to a value from your
application.properties during configuration.
By default, if the context contains only a single Servlet, it is mapped to /. In the case of multiple
servlet beans, the bean name is used as a path prefix. Filters map to /*.
If convention-based mapping is not flexible enough, you can use the ServletRegistrationBean,
FilterRegistrationBean, and ServletListenerRegistrationBean classes for complete control.
It is usually safe to leave filter beans unordered. If a specific order is required, you should annotate
the Filter with @Order or make it implement Ordered. You cannot configure the order of a Filter by
annotating its bean method with @Order. If you cannot change the Filter class to add @Order or
189
implement Ordered, you must define a FilterRegistrationBean for the Filter and set the registration
bean’s order using the setOrder(int) method. Avoid configuring a filter that reads the request body
at Ordered.HIGHEST_PRECEDENCE, since it might go against the character encoding configuration of
your application. If a servlet filter wraps the request, it should be configured with an order that is
less than or equal to OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER.
To see the order of every Filter in your application, enable debug level logging for the
TIP web logging group (logging.level.web=debug). Details of the registered filters, including
their order and URL patterns, will then be logged at startup.
Take care when registering Filter beans since they are initialized very early in
WARNING the application lifecycle. If you need to register a Filter that interacts with
other beans, consider using a DelegatingFilterProxyRegistrationBean instead.
If you need to perform servlet context initialization in a Spring Boot application, you should
register a bean that implements the
org.springframework.boot.web.servlet.ServletContextInitializer interface. The single onStartup
method provides access to the ServletContext and, if necessary, can easily be used as an adapter to
an existing WebApplicationInitializer.
When using an embedded container, automatic registration of classes annotated with @WebServlet,
@WebFilter, and @WebListener can be enabled by using @ServletComponentScan.
The ServletWebServerApplicationContext
Under the hood, Spring Boot uses a different type of ApplicationContext for embedded servlet
container support. The ServletWebServerApplicationContext is a special type of
WebApplicationContext that bootstraps itself by searching for a single ServletWebServerFactory bean.
Usually a TomcatServletWebServerFactory, JettyServletWebServerFactory, or
UndertowServletWebServerFactory has been auto-configured.
190
Customizing Embedded Servlet Containers
Common servlet container settings can be configured by using Spring Environment properties.
Usually, you would define the properties in your application.properties or application.yaml file.
• Network settings: Listen port for incoming HTTP requests (server.port), interface address to
bind to server.address, and so on.
• SSL
• HTTP compression
Spring Boot tries as much as possible to expose common settings, but this is not always possible. For
those cases, dedicated namespaces offer server-specific customizations (see server.tomcat and
server.undertow). For instance, access logs can be configured with specific features of the embedded
servlet container.
SameSite Cookies
The SameSite cookie attribute can be used by web browsers to control if and how cookies are
submitted in cross-site requests. The attribute is particularly relevant for modern web browsers
which have started to change the default value that is used when the attribute is missing.
If you want to change the SameSite attribute of your session cookie, you can use the
server.servlet.session.cookie.same-site property. This property is supported by auto-configured
Tomcat, Jetty and Undertow servers. It is also used to configure Spring Session servlet based
SessionRepository beans.
For example, if you want your session cookie to have a SameSite attribute of None, you can add the
following to your application.properties or application.yaml file:
Properties
server.servlet.session.cookie.same-site=none
191
Yaml
server:
servlet:
session:
cookie:
same-site: "none"
If you want to change the SameSite attribute on other cookies added to your HttpServletResponse,
you can use a CookieSameSiteSupplier. The CookieSameSiteSupplier is passed a Cookie and may
return a SameSite value, or null.
There are a number of convenience factory and filter methods that you can use to quickly match
specific cookies. For example, adding the following bean will automatically apply a SameSite of Lax
for all cookies with a name that matches the regular expression myapp.*.
import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MySameSiteConfiguration {
@Bean
public CookieSameSiteSupplier applicationCookieSameSiteSupplier() {
return CookieSameSiteSupplier.ofLax().whenHasNameMatching("myapp.*");
}
Programmatic Customization
If you need to programmatically configure your embedded servlet container, you can register a
Spring bean that implements the WebServerFactoryCustomizer interface. WebServerFactoryCustomizer
provides access to the ConfigurableServletWebServerFactory, which includes numerous
customization setter methods. The following example shows programmatically setting the port:
192
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import
org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;
@Component
public class MyWebServerFactoryCustomizer implements
WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory server) {
server.setPort(9000);
}
import java.time.Duration;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
@Component
public class MyTomcatWebServerFactoryCustomizer implements
WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory server) {
server.addConnectorCustomizers((connector) ->
connector.setAsyncTimeout(Duration.ofSeconds(20).toMillis()));
}
For more advanced use cases that require you to extend from ServletWebServerFactory, you can
expose a bean of such type yourself.
Setters are provided for many configuration options. Several protected method “hooks” are also
provided should you need to do something more exotic. See the source code documentation for
details.
193
Auto-configured customizers are still applied on your custom factory, so use that
NOTE
option carefully.
JSP Limitations
When running a Spring Boot application that uses an embedded servlet container (and is packaged
as an executable archive), there are some limitations in the JSP support.
• With Jetty and Tomcat, it should work if you use war packaging. An executable war will work
when launched with java -jar, and will also be deployable to any standard container. JSPs are
not supported when using an executable jar.
• Creating a custom error.jsp page does not override the default view for error handling. Custom
error pages should be used instead.
Spring WebFlux is the new reactive web framework introduced in Spring Framework 5.0. Unlike
Spring MVC, it does not require the servlet API, is fully asynchronous and non-blocking, and
implements the Reactive Streams specification through the Reactor project.
Spring WebFlux comes in two flavors: functional and annotation-based. The annotation-based one
is quite close to the Spring MVC model, as shown in the following example:
194
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/users")
public class MyRestController {
@GetMapping("/{user}")
public Mono<User> getUser(@PathVariable Long userId) {
return this.userRepository.findById(userId);
}
@GetMapping("/{user}/customers")
public Flux<Customer> getUserCustomers(@PathVariable Long userId) {
return
this.userRepository.findById(userId).flatMapMany(this.customerRepository::findByUser);
}
@DeleteMapping("/{user}")
public void deleteUser(@PathVariable Long userId) {
this.userRepository.deleteById(userId);
}
“WebFlux.fn”, the functional variant, separates the routing configuration from the actual handling
of the requests, as shown in the following example:
195
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicate;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import static
org.springframework.web.reactive.function.server.RequestPredicates.DELETE;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static
org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {
@Bean
public RouterFunction<ServerResponse> monoRouterFunction(MyUserHandler
userHandler) {
return route(
GET("/{user}").and(ACCEPT_JSON), userHandler::getUser).andRoute(
GET("/{user}/customers").and(ACCEPT_JSON),
userHandler::getUserCustomers).andRoute(
DELETE("/{user}").and(ACCEPT_JSON), userHandler::deleteUser);
}
196
import reactor.core.publisher.Mono;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
@Component
public class MyUserHandler {
WebFlux is part of the Spring Framework and detailed information is available in its reference
documentation.
You can define as many RouterFunction beans as you like to modularize the definition
TIP
of the router. Beans can be ordered if you need to apply a precedence.
“WebFlux.fn”, the functional variant, separates the routing configuration from the actual handling
of the requests, as shown in the following example:
197
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicate;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import static
org.springframework.web.reactive.function.server.RequestPredicates.DELETE;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static
org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {
@Bean
public RouterFunction<ServerResponse> monoRouterFunction(MyUserHandler
userHandler) {
return route(
GET("/{user}").and(ACCEPT_JSON), userHandler::getUser).andRoute(
GET("/{user}/customers").and(ACCEPT_JSON),
userHandler::getUserCustomers).andRoute(
DELETE("/{user}").and(ACCEPT_JSON), userHandler::deleteUser);
}
198
import reactor.core.publisher.Mono;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
@Component
public class MyUserHandler {
WebFlux is part of the Spring Framework and detailed information is available in its reference
documentation.
You can define as many RouterFunction beans as you like to modularize the definition
TIP
of the router. Beans can be ordered if you need to apply a precedence.
Spring Boot provides auto-configuration for Spring WebFlux that works well with most
applications.
• Support for serving static resources, including support for WebJars (described later in this
199
document).
If you want to keep Spring Boot WebFlux features and you want to add additional WebFlux
configuration, you can add your own @Configuration class of type WebFluxConfigurer but without
@EnableWebFlux.
If you want to take complete control of Spring WebFlux, you can add your own @Configuration
annotated with @EnableWebFlux.
Spring WebFlux uses the HttpMessageReader and HttpMessageWriter interfaces to convert HTTP
requests and responses. They are configured with CodecConfigurer to have sensible defaults by
looking at the libraries available in your classpath.
Spring Boot provides dedicated configuration properties for codecs, spring.codec.*. It also applies
further customization by using CodecCustomizer instances. For example, spring.jackson.*
configuration keys are applied to the Jackson codec.
If you need to add or customize codecs, you can create a custom CodecCustomizer component, as
shown in the following example:
import org.springframework.boot.web.codec.CodecCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.ServerSentEventHttpMessageReader;
@Configuration(proxyBeanMethods = false)
public class MyCodecsConfiguration {
@Bean
public CodecCustomizer myCodecCustomizer() {
return (configurer) -> {
configurer.registerDefaults(false);
configurer.customCodecs().register(new
ServerSentEventHttpMessageReader());
// ...
};
}
You can also leverage Boot’s custom JSON serializers and deserializers.
Static Content
By default, Spring Boot serves static content from a directory called /static (or /public or
/resources or /META-INF/resources) in the classpath. It uses the ResourceWebHandler from Spring
WebFlux so that you can modify that behavior by adding your own WebFluxConfigurer and
overriding the addResourceHandlers method.
200
By default, resources are mapped on /**, but you can tune that by setting the
spring.webflux.static-path-pattern property. For instance, relocating all resources to /resources/**
can be achieved as follows:
Properties
spring.webflux.static-path-pattern=/resources/**
Yaml
spring:
webflux:
static-path-pattern: "/resources/**"
You can also customize the static resource locations by using spring.web.resources.static-
locations. Doing so replaces the default values with a list of directory locations. If you do so, the
default welcome page detection switches to your custom locations. So, if there is an index.html in
any of your locations on startup, it is the home page of the application.
In addition to the “standard” static resource locations listed earlier, a special case is made for
Webjars content. Any resources with a path in /webjars/** are served from jar files if they are
packaged in the Webjars format.
Spring WebFlux applications do not strictly depend on the servlet API, so they cannot
TIP
be deployed as war files and do not use the src/main/webapp directory.
Welcome Page
Spring Boot supports both static and templated welcome pages. It first looks for an index.html file in
the configured static content locations. If one is not found, it then looks for an index template. If
either is found, it is automatically used as the welcome page of the application.
Template Engines
As well as REST web services, you can also use Spring WebFlux to serve dynamic HTML content.
Spring WebFlux supports a variety of templating technologies, including Thymeleaf, FreeMarker,
and Mustache.
Spring Boot includes auto-configuration support for the following templating engines:
• FreeMarker
• Thymeleaf
• Mustache
When you use one of these templating engines with the default configuration, your templates are
picked up automatically from src/main/resources/templates.
201
Error Handling
Spring Boot provides a WebExceptionHandler that handles all errors in a sensible way. Its position in
the processing order is immediately before the handlers provided by WebFlux, which are
considered last. For machine clients, it produces a JSON response with details of the error, the HTTP
status, and the exception message. For browser clients, there is a “whitelabel” error handler that
renders the same data in HTML format. You can also provide your own HTML templates to display
errors (see the next section).
The first step to customizing this feature often involves using the existing mechanism but replacing
or augmenting the error contents. For that, you can add a bean of type ErrorAttributes.
To change the error handling behavior, you can implement ErrorWebExceptionHandler and register a
bean definition of that type. Because a ErrorWebExceptionHandler is quite low-level, Spring Boot also
provides a convenient AbstractErrorWebExceptionHandler to let you handle errors in a WebFlux
functional way, as shown in the following example:
202
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.web.WebProperties.Resources;
import
org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHan
dler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.function.server.ServerResponse.BodyBuilder;
@Component
public class MyErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes
errorAttributes) {
return RouterFunctions.route(this::acceptsXml, this::handleErrorAsXml);
}
For a more complete picture, you can also subclass DefaultErrorWebExceptionHandler directly and
override specific methods.
In some cases, errors handled at the controller or handler function level are not recorded by the
metrics infrastructure. Applications can ensure that such exceptions are recorded with the request
203
metrics by setting the handled exception as a request attribute:
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.reactive.result.view.Rendering;
import org.springframework.web.server.ServerWebExchange;
@Controller
public class MyExceptionHandlingController {
@GetMapping("/profile")
public Rendering userProfile() {
// ...
throw new IllegalStateException();
}
@ExceptionHandler(IllegalStateException.class)
public Rendering handleIllegalState(ServerWebExchange exchange,
IllegalStateException exc) {
exchange.getAttributes().putIfAbsent(ErrorAttributes.ERROR_ATTRIBUTE, exc);
return Rendering.view("errorView").modelAttribute("message",
exc.getMessage()).build();
}
If you want to display a custom HTML error page for a given status code, you can add a file to an
/error directory. Error pages can either be static HTML (that is, added under any of the static
resource directories) or built with templates. The name of the file should be the exact status code or
a series mask.
For example, to map 404 to a static HTML file, your directory structure would be as follows:
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>
To map all 5xx errors by using a Mustache template, your directory structure would be as follows:
204
src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.mustache
+- <other templates>
Web Filters
Spring WebFlux provides a WebFilter interface that can be implemented to filter HTTP request-
response exchanges. WebFilter beans found in the application context will be automatically used to
filter each exchange.
Where the order of the filters is important they can implement Ordered or be annotated with @Order.
Spring Boot auto-configuration may configure web filters for you. When it does so, the orders
shown in the following table will be used:
HttpTraceWebFilter Ordered.LOWEST_PRECEDENCE - 10
Spring Boot includes support for the following embedded reactive web servers: Reactor Netty,
Tomcat, Jetty, and Undertow. Most developers use the appropriate “Starter” to obtain a fully
configured instance. By default, the embedded server listens for HTTP requests on port 8080.
When auto-configuring a Reactor Netty or Jetty server, Spring Boot will create specific beans that
will provide HTTP resources to the server instance: ReactorResourceFactory or JettyResourceFactory.
By default, those resources will be also shared with the Reactor Netty and Jetty clients for optimal
performances, given:
• the client instance is built using the WebClient.Builder bean auto-configured by Spring Boot
Developers can override the resource configuration for Jetty and Reactor Netty by providing a
custom ReactorResourceFactory or JettyResourceFactory bean - this will be applied to both clients
and servers.
You can learn more about the resource configuration on the client side in the WebClient Runtime
205
section.
To enable graceful shutdown, configure the server.shutdown property, as shown in the following
example:
Properties
server.shutdown=graceful
Yaml
server:
shutdown: "graceful"
Properties
spring.lifecycle.timeout-per-shutdown-phase=20s
Yaml
spring:
lifecycle:
timeout-per-shutdown-phase: "20s"
Using graceful shutdown with your IDE may not work properly if it does not
IMPORTANT send a proper SIGTERM signal. See the documentation of your IDE for more
details.
206
8.4. Spring Security
If Spring Security is on the classpath, then web applications are secured by default. Spring Boot
relies on Spring Security’s content-negotiation strategy to determine whether to use httpBasic or
formLogin. To add method-level security to a web application, you can also add
@EnableGlobalMethodSecurity with your desired settings. Additional information can be found in the
Spring Security Reference Guide.
The default UserDetailsService has a single user. The user name is user, and the password is
random and is printed at INFO level when the application starts, as shown in the following
example:
You can change the username and password by providing a spring.security.user.name and
spring.security.user.password.
• Form-based login or HTTP Basic security (depending on the Accept header in the request) for the
entire application (including actuator endpoints if actuator is on the classpath).
To also switch off the UserDetailsService configuration, you can add a bean of type
UserDetailsService, AuthenticationProvider, or AuthenticationManager.
207
override access rules for actuator endpoints and static resources. EndpointRequest can be used to
create a RequestMatcher that is based on the management.endpoints.web.base-path property.
PathRequest can be used to create a RequestMatcher for resources in commonly used locations.
Similar to Spring MVC applications, you can secure your WebFlux applications by adding the
spring-boot-starter-security dependency. The default security configuration is implemented in
ReactiveSecurityAutoConfiguration and UserDetailsServiceAutoConfiguration.
ReactiveSecurityAutoConfiguration imports WebFluxSecurityConfiguration for web security and
UserDetailsServiceAutoConfiguration configures authentication, which is also relevant in non-web
applications. To switch off the default web application security configuration completely, you can
add a bean of type WebFilterChainProxy (doing so does not disable the UserDetailsService
configuration or Actuator’s security).
To also switch off the UserDetailsService configuration, you can add a bean of type
ReactiveUserDetailsService or ReactiveAuthenticationManager.
Access rules and the use of multiple Spring Security components such as OAuth 2 Client and
Resource Server can be configured by adding a custom SecurityWebFilterChain bean. Spring Boot
provides convenience methods that can be used to override access rules for actuator endpoints and
static resources. EndpointRequest can be used to create a ServerWebExchangeMatcher that is based on
the management.endpoints.web.base-path property.
For example, you can customize your security configuration by adding something like:
208
import org.springframework.boot.autoconfigure.security.reactive.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration(proxyBeanMethods = false)
public class MyWebFluxSecurityConfiguration {
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange((spec) -> {
spec.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
spec.pathMatchers("/foo", "/bar").authenticated();
});
http.formLogin();
return http.build();
}
8.4.3. OAuth2
Client
If you have spring-security-oauth2-client on your classpath, you can take advantage of some auto-
configuration to set up an OAuth2/Open ID Connect clients. This configuration makes use of the
properties under OAuth2ClientProperties. The same properties are applicable to both servlet and
reactive applications.
You can register multiple OAuth2 clients and providers under the spring.security.oauth2.client
prefix, as shown in the following example:
209
Properties
spring.security.oauth2.client.registration.my-client-1.client-id=abcd
spring.security.oauth2.client.registration.my-client-1.client-secret=password
spring.security.oauth2.client.registration.my-client-1.client-name=Client for user
scope
spring.security.oauth2.client.registration.my-client-1.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-1.scope=user
spring.security.oauth2.client.registration.my-client-1.redirect-uri=https://my-
redirect-uri.com
spring.security.oauth2.client.registration.my-client-1.client-authentication-
method=basic
spring.security.oauth2.client.registration.my-client-1.authorization-grant-
type=authorization-code
spring.security.oauth2.client.registration.my-client-2.client-id=abcd
spring.security.oauth2.client.registration.my-client-2.client-secret=password
spring.security.oauth2.client.registration.my-client-2.client-name=Client for email
scope
spring.security.oauth2.client.registration.my-client-2.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-2.scope=email
spring.security.oauth2.client.registration.my-client-2.redirect-uri=https://my-
redirect-uri.com
spring.security.oauth2.client.registration.my-client-2.client-authentication-
method=basic
spring.security.oauth2.client.registration.my-client-2.authorization-grant-
type=authorization_code
spring.security.oauth2.client.provider.my-oauth-provider.authorization-uri=https://my-
auth-server/oauth/authorize
spring.security.oauth2.client.provider.my-oauth-provider.token-uri=https://my-auth-
server/oauth/token
spring.security.oauth2.client.provider.my-oauth-provider.user-info-uri=https://my-
auth-server/userinfo
spring.security.oauth2.client.provider.my-oauth-provider.user-info-authentication-
method=header
spring.security.oauth2.client.provider.my-oauth-provider.jwk-set-uri=https://my-auth-
server/token_keys
spring.security.oauth2.client.provider.my-oauth-provider.user-name-attribute=name
210
Yaml
spring:
security:
oauth2:
client:
registration:
my-client-1:
client-id: "abcd"
client-secret: "password"
client-name: "Client for user scope"
provider: "my-oauth-provider"
scope: "user"
redirect-uri: "https://my-redirect-uri.com"
client-authentication-method: "basic"
authorization-grant-type: "authorization-code"
my-client-2:
client-id: "abcd"
client-secret: "password"
client-name: "Client for email scope"
provider: "my-oauth-provider"
scope: "email"
redirect-uri: "https://my-redirect-uri.com"
client-authentication-method: "basic"
authorization-grant-type: "authorization_code"
provider:
my-oauth-provider:
authorization-uri: "https://my-auth-server/oauth/authorize"
token-uri: "https://my-auth-server/oauth/token"
user-info-uri: "https://my-auth-server/userinfo"
user-info-authentication-method: "header"
jwk-set-uri: "https://my-auth-server/token_keys"
user-name-attribute: "name"
For OpenID Connect providers that support OpenID Connect discovery, the configuration can be
further simplified. The provider needs to be configured with an issuer-uri which is the URI that the
it asserts as its Issuer Identifier. For example, if the issuer-uri provided is "https://example.com",
then an OpenID Provider Configuration Request will be made to "https://example.com/.well-
known/openid-configuration". The result is expected to be an OpenID Provider Configuration
Response. The following example shows how an OpenID Connect Provider can be configured with
the issuer-uri:
Properties
spring.security.oauth2.client.provider.oidc-provider.issuer-uri=https://dev-
123456.oktapreview.com/oauth2/default/
211
Yaml
spring:
security:
oauth2:
client:
provider:
oidc-provider:
issuer-uri: "https://dev-123456.oktapreview.com/oauth2/default/"
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration(proxyBeanMethods = false)
public class MyOAuthClientConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception
{
http.authorizeRequests().anyRequest().authenticated();
http.oauth2Login().redirectionEndpoint().baseUri("custom-callback");
return http.build();
}
For common OAuth2 and OpenID providers, including Google, Github, Facebook, and Okta, we
provide a set of provider defaults (google, github, facebook, and okta, respectively).
If you do not need to customize these providers, you can set the provider attribute to the one for
which you need to infer defaults. Also, if the key for the client registration matches a default
supported provider, Spring Boot infers that as well.
212
In other words, the two configurations in the following example use the Google provider:
Properties
spring.security.oauth2.client.registration.my-client.client-id=abcd
spring.security.oauth2.client.registration.my-client.client-secret=password
spring.security.oauth2.client.registration.my-client.provider=google
spring.security.oauth2.client.registration.google.client-id=abcd
spring.security.oauth2.client.registration.google.client-secret=password
Yaml
spring:
security:
oauth2:
client:
registration:
my-client:
client-id: "abcd"
client-secret: "password"
provider: "google"
google:
client-id: "abcd"
client-secret: "password"
Resource Server
Properties
spring.security.oauth2.resourceserver.jwt.jwk-set-
uri=https://example.com/oauth2/default/v1/keys
Yaml
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: "https://example.com/oauth2/default/v1/keys"
213
Properties
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-
123456.oktapreview.com/oauth2/default/
Yaml
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: "https://dev-123456.oktapreview.com/oauth2/default/"
If the authorization server does not support a JWK Set URI, you can configure the
resource server with the Public Key used for verifying the signature of the JWT. This
NOTE can be done using the spring.security.oauth2.resourceserver.jwt.public-key-
location property, where the value needs to point to a file containing the public key
in the PEM-encoded x509 format.
The same properties are applicable for both servlet and reactive applications.
Alternatively, you can define your own JwtDecoder bean for servlet applications or a
ReactiveJwtDecoder for reactive applications.
In cases where opaque tokens are used instead of JWTs, you can configure the following properties
to validate tokens through introspection:
Properties
spring.security.oauth2.resourceserver.opaquetoken.introspection-
uri=https://example.com/check-token
spring.security.oauth2.resourceserver.opaquetoken.client-id=my-client-id
spring.security.oauth2.resourceserver.opaquetoken.client-secret=my-client-secret
Yaml
spring:
security:
oauth2:
resourceserver:
opaquetoken:
introspection-uri: "https://example.com/check-token"
client-id: "my-client-id"
client-secret: "my-client-secret"
Again, the same properties are applicable for both servlet and reactive applications.
214
Alternatively, you can define your own OpaqueTokenIntrospector bean for servlet applications or a
ReactiveOpaqueTokenIntrospector for reactive applications.
Authorization Server
Currently, Spring Security does not provide support for implementing an OAuth 2.0 Authorization
Server. However, this functionality is available from the Spring Security OAuth project, which will
eventually be superseded by Spring Security completely. Until then, you can use the spring-
security-oauth2-autoconfigure module to easily set up an OAuth 2.0 authorization server; see its
documentation for instructions.
Relying Party
A relying party registration represents a paired configuration between an Identity Provider, IDP,
and a Service Provider, SP. You can register multiple relying parties under the
spring.security.saml2.relyingparty prefix, as shown in the following example:
215
Properties
spring.security.saml2.relyingparty.registration.my-relying-
party1.signing.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-
party1.signing.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-
party1.decryption.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-
party1.decryption.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-
party1.identityprovider.verification.credentials[0].certificate-location=path-to-
verification-cert
spring.security.saml2.relyingparty.registration.my-relying-
party1.identityprovider.entity-id=remote-idp-entity-id1
spring.security.saml2.relyingparty.registration.my-relying-
party1.identityprovider.sso-url=https://remoteidp1.sso.url
spring.security.saml2.relyingparty.registration.my-relying-
party2.signing.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-
party2.signing.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-
party2.decryption.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-
party2.decryption.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-
party2.identityprovider.verification.credentials[0].certificate-location=path-to-
other-verification-cert
spring.security.saml2.relyingparty.registration.my-relying-
party2.identityprovider.entity-id=remote-idp-entity-id2
spring.security.saml2.relyingparty.registration.my-relying-
party2.identityprovider.sso-url=https://remoteidp2.sso.url
216
Yaml
spring:
security:
saml2:
relyingparty:
registration:
my-relying-party1:
signing:
credentials:
- private-key-location: "path-to-private-key"
certificate-location: "path-to-certificate"
decryption:
credentials:
- private-key-location: "path-to-private-key"
certificate-location: "path-to-certificate"
identityprovider:
verification:
credentials:
- certificate-location: "path-to-verification-cert"
entity-id: "remote-idp-entity-id1"
sso-url: "https://remoteidp1.sso.url"
my-relying-party2:
signing:
credentials:
- private-key-location: "path-to-private-key"
certificate-location: "path-to-certificate"
decryption:
credentials:
- private-key-location: "path-to-private-key"
certificate-location: "path-to-certificate"
identityprovider:
verification:
credentials:
- certificate-location: "path-to-other-verification-cert"
entity-id: "remote-idp-entity-id2"
sso-url: "https://remoteidp2.sso.url"
• JDBC
• Redis
• Hazelcast
• MongoDB
217
The servlet auto-configuration replaces the need to use @Enable*HttpSession.
When building a reactive web application, the following stores can be auto-configured:
• Redis
• MongoDB
If a single Spring Session module is present on the classpath, Spring Boot uses that store
implementation automatically. If you have more than one implementation, you must choose the
StoreType that you wish to use to store the sessions. For instance, to use JDBC as the back-end store,
you can configure your application as follows:
Properties
spring.session.store-type=jdbc
Yaml
spring:
session:
store-type: "jdbc"
TIP You can disable Spring Session by setting the store-type to none.
Each store has specific additional settings. For instance, it is possible to customize the name of the
table for the JDBC store, as shown in the following example:
Properties
spring.session.jdbc.table-name=SESSIONS
Yaml
spring:
session:
jdbc:
table-name: "SESSIONS"
For setting the timeout of the session you can use the spring.session.timeout property. If that
property is not set with a servlet web application, the auto-configuration falls back to the value of
server.servlet.session.timeout.
You can take control over Spring Session’s configuration using @Enable*HttpSession (servlet) or
@Enable*WebSession (reactive). This will cause the auto-configuration to back off. Spring Session can
then be configured using the annotation’s attributes rather than the previously described
configuration properties.
218
8.6. Spring HATEOAS
If you develop a RESTful API that makes use of hypermedia, Spring Boot provides auto-
configuration for Spring HATEOAS that works well with most applications. The auto-configuration
replaces the need to use @EnableHypermediaSupport and registers a number of beans to ease building
hypermedia-based applications, including a LinkDiscoverers (for client side support) and an
ObjectMapper configured to correctly marshal responses into the desired representation. The
ObjectMapper is customized by setting the various spring.jackson.* properties or, if one exists, by a
Jackson2ObjectMapperBuilder bean.
You can take control of Spring HATEOAS’s configuration by using @EnableHypermediaSupport. Note
that doing so disables the ObjectMapper customization described earlier.
219
Chapter 9. Data
Spring Boot integrates with a number of data technologies, both SQL and NoSQL.
See the “How-to” section for more advanced examples, typically to take full control
TIP
over the configuration of the DataSource.
Spring Boot can auto-configure embedded H2, HSQL, and Derby databases. You need not provide
any connection URLs. You need only include a build dependency to the embedded database that
you want to use. If there are multiple embedded databases on the classpath, set the
spring.datasource.embedded-database-connection configuration property to control which one is
used. Setting the property to none disables auto-configuration of an embedded database.
If you are using this feature in your tests, you may notice that the same database is
reused by your whole test suite regardless of the number of application contexts
NOTE
that you use. If you want to make sure that each context has a separate embedded
database, you should set spring.datasource.generate-unique-name to true.
220
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
If, for whatever reason, you do configure the connection URL for an embedded
database, take care to ensure that the database’s automatic shutdown is disabled. If
you use H2, you should use DB_CLOSE_ON_EXIT=FALSE to do so. If you use HSQLDB, you
TIP
should ensure that shutdown=true is not used. Disabling the database’s automatic
shutdown lets Spring Boot control when the database is closed, thereby ensuring that
it happens once access to the database is no longer needed.
DataSource Configuration
Properties
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
Yaml
spring:
datasource:
url: "jdbc:mysql://localhost/test"
username: "dbuser"
password: "dbpass"
You should at least specify the URL by setting the spring.datasource.url property.
NOTE
Otherwise, Spring Boot tries to auto-configure an embedded database.
221
Spring Boot can deduce the JDBC driver class for most databases from the URL. If you
TIP need to specify a specific class, you can use the spring.datasource.driver-class-name
property.
See DataSourceProperties for more of the supported options. These are the standard options that
work regardless of the actual implementation. It is also possible to fine-tune implementation-
specific settings by using their respective prefix (spring.datasource.hikari.*,
spring.datasource.tomcat.*, spring.datasource.dbcp2.*, and spring.datasource.oracleucp.*). See the
documentation of the connection pool implementation you are using for more details.
For instance, if you use the Tomcat connection pool, you could customize many additional settings,
as shown in the following example:
Properties
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.test-on-borrow=true
Yaml
spring:
datasource:
tomcat:
max-wait: 10000
max-active: 50
test-on-borrow: true
This will set the pool to wait 10000ms before throwing an exception if no connection is available,
limit the maximum number of connections to 50 and validate the connection before borrowing it
from the pool.
Spring Boot uses the following algorithm for choosing a specific implementation:
1. We prefer HikariCP for its performance and concurrency. If HikariCP is available, we always
choose it.
4. If none of HikariCP, Tomcat, and DBCP2 are available and if Oracle UCP is available, we use it.
222
If you use the spring-boot-starter-jdbc or spring-boot-starter-data-jpa “starters”,
NOTE
you automatically get a dependency to HikariCP.
You can bypass that algorithm completely and specify the connection pool to use by setting the
spring.datasource.type property. This is especially important if you run your application in a
Tomcat container, as tomcat-jdbc is provided by default.
Additional connection pools can always be configured manually, using DataSourceBuilder. If you
define your own DataSource bean, auto-configuration does not occur. The following connection
pools are supported by DataSourceBuilder:
• HikariCP
• Commons DBCP2
• H2 JdbcDataSource
• PostgreSQL PGSimpleDataSource
If you deploy your Spring Boot application to an Application Server, you might want to configure
and manage your DataSource by using your Application Server’s built-in features and access it by
using JNDI.
Properties
spring.datasource.jndi-name=java:jboss/datasources/customers
Yaml
spring:
datasource:
jndi-name: "java:jboss/datasources/customers"
Spring’s JdbcTemplate and NamedParameterJdbcTemplate classes are auto-configured, and you can
@Autowire them directly into your own beans, as shown in the following example:
223
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
You can customize some properties of the template by using the spring.jdbc.template.* properties,
as shown in the following example:
Properties
spring.jdbc.template.max-rows=500
Yaml
spring:
jdbc:
template:
max-rows: 500
The Java Persistence API is a standard technology that lets you “map” objects to relational
databases. The spring-boot-starter-data-jpa POM provides a quick way to get started. It provides
the following key dependencies:
224
We do not go into too many details of JPA or Spring Data here. You can follow the
TIP “Accessing Data with JPA” guide from spring.io and read the Spring Data JPA and
Hibernate reference documentation.
Entity Classes
Traditionally, JPA “Entity” classes are specified in a persistence.xml file. With Spring Boot, this file is
not necessary and “Entity Scanning” is used instead. By default, all packages below your main
configuration class (the one annotated with @EnableAutoConfiguration or @SpringBootApplication)
are searched.
Any classes annotated with @Entity, @Embeddable, or @MappedSuperclass are considered. A typical
entity class resembles the following example:
225
import java.io.Serializable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class City implements Serializable {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String state;
protected City() {
// no-args constructor required by JPA spec
// this one is protected since it should not be used directly
}
// ... etc
You can customize entity scanning locations by using the @EntityScan annotation. See
TIP
the “Separate @Entity Definitions from Spring Configuration” how-to.
226
Spring Data JPA Repositories
Spring Data JPA repositories are interfaces that you can define to access data. JPA queries are
created automatically from your method names. For example, a CityRepository interface might
declare a findAllByState(String state) method to find all the cities in a given state.
For more complex queries, you can annotate your method with Spring Data’s Query annotation.
Spring Data repositories usually extend from the Repository or CrudRepository interfaces. If you use
auto-configuration, repositories are searched from the package containing your main configuration
class (the one annotated with @EnableAutoConfiguration or @SpringBootApplication) down.
The following example shows a typical Spring Data repository interface definition:
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
Spring Data JPA repositories support three different modes of bootstrapping: default, deferred, and
lazy. To enable deferred or lazy bootstrapping, set the spring.data.jpa.repositories.bootstrap-mode
property to deferred or lazy respectively. When using deferred or lazy bootstrapping, the auto-
configured EntityManagerFactoryBuilder will use the context’s AsyncTaskExecutor, if any, as the
bootstrap executor. If more than one exists, the one named applicationTaskExecutor will be used.
When using deferred or lazy bootstrapping, make sure to defer any access to the JPA
infrastructure after the application context bootstrap phase. You can use
NOTE SmartInitializingSingleton to invoke any initialization that requires the JPA
infrastructure. For JPA components (such as converters) that are created as Spring
beans, use ObjectProvider to delay the resolution of dependencies, if any.
We have barely scratched the surface of Spring Data JPA. For complete details, see the
TIP
Spring Data JPA reference documentation.
If Spring Data Envers is available, JPA repositories are auto-configured to support typical Envers
queries.
To use Spring Data Envers, make sure your repository extends from RevisionRepository as show in
the following example:
227
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.history.RevisionRepository;
NOTE For more details, check the Spring Data Envers reference documentation.
By default, JPA databases are automatically created only if you use an embedded database (H2,
HSQL, or Derby). You can explicitly configure JPA settings by using spring.jpa.* properties. For
example, to create and drop tables you can add the following line to your application.properties:
Properties
spring.jpa.hibernate.ddl-auto=create-drop
Yaml
spring:
jpa:
hibernate.ddl-auto: "create-drop"
Hibernate’s own internal property name for this (if you happen to remember it
better) is hibernate.hbm2ddl.auto. You can set it, along with other Hibernate native
NOTE properties, by using spring.jpa.properties.* (the prefix is stripped before adding
them to the entity manager). The following line shows an example of setting JPA
properties for Hibernate:
Properties
spring.jpa.properties.hibernate[globally_quoted_identifiers]=true
228
Yaml
spring:
jpa:
properties:
hibernate:
"globally_quoted_identifiers": "true"
The line in the preceding example passes a value of true for the
hibernate.globally_quoted_identifiers property to the Hibernate entity manager.
By default, the DDL execution (or validation) is deferred until the ApplicationContext has started.
There is also a spring.jpa.generate-ddl flag, but it is not used if Hibernate auto-configuration is
active, because the ddl-auto settings are more fine-grained.
Spring Data includes repository support for JDBC and will automatically generate SQL for the
methods on CrudRepository. For more advanced queries, a @Query annotation is provided.
Spring Boot will auto-configure Spring Data’s JDBC repositories when the necessary dependencies
are on the classpath. They can be added to your project with a single dependency on spring-boot-
starter-data-jdbc. If necessary, you can take control of Spring Data JDBC’s configuration by adding
the @EnableJdbcRepositories annotation or a JdbcConfiguration subclass to your application.
TIP For complete details of Spring Data JDBC, see the reference documentation.
jOOQ Object Oriented Querying (jOOQ) is a popular product from Data Geekery which generates
Java code from your database and lets you build type-safe SQL queries through its fluent API. Both
the commercial and open source editions can be used with Spring Boot.
Code Generation
In order to use jOOQ type-safe queries, you need to generate Java classes from your database
schema. You can follow the instructions in the jOOQ user manual. If you use the jooq-codegen-maven
plugin and you also use the spring-boot-starter-parent “parent POM”, you can safely omit the
plugin’s <version> tag. You can also use Spring Boot-defined version variables (such as h2.version)
to declare the plugin’s database dependency. The following listing shows an example:
229
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<executions>
...
</executions>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
<configuration>
<jdbc>
<driver>org.h2.Driver</driver>
<url>jdbc:h2:~/yourdatabase</url>
</jdbc>
<generator>
...
</generator>
</configuration>
</plugin>
Using DSLContext
The fluent API offered by jOOQ is initiated through the org.jooq.DSLContext interface. Spring Boot
auto-configures a DSLContext as a Spring Bean and connects it to your application DataSource. To use
the DSLContext, you can inject it, as shown in the following example:
230
import java.util.GregorianCalendar;
import java.util.List;
import org.jooq.DSLContext;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
TIP The jOOQ manual tends to use a variable named create to hold the DSLContext.
You can then use the DSLContext to construct your queries, as shown in the following example:
Unless the spring.jooq.sql-dialect property has been configured, Spring Boot determines the SQL
dialect to use for your datasource. If Spring Boot could not detect the dialect, it uses DEFAULT.
Spring Boot can only auto-configure dialects supported by the open source version
NOTE
of jOOQ.
Customizing jOOQ
You can also create your own org.jooq.Configuration @Bean if you want to take complete control of
231
the jOOQ configuration.
The Reactive Relational Database Connectivity (R2DBC) project brings reactive programming APIs
to relational databases. R2DBC’s io.r2dbc.spi.Connection provides a standard method of working
with non-blocking database connections. Connections are provided by using a ConnectionFactory,
similar to a DataSource with jdbc.
Properties
spring.r2dbc.url=r2dbc:postgresql://localhost/test
spring.r2dbc.username=dbuser
spring.r2dbc.password=dbpass
Yaml
spring:
r2dbc:
url: "r2dbc:postgresql://localhost/test"
username: "dbuser"
password: "dbpass"
You do not need to specify a driver class name, since Spring Boot obtains the driver
TIP
from R2DBC’s Connection Factory discovery.
At least the url should be provided. Information specified in the URL takes
NOTE precedence over individual properties, that is name, username, password and pooling
options.
To customize the connections created by a ConnectionFactory, that is, set specific parameters that
you do not want (or cannot) configure in your central database configuration, you can use a
ConnectionFactoryOptionsBuilderCustomizer @Bean. The following example shows how to manually
override the database port while the rest of the options is taken from the application configuration:
232
import io.r2dbc.spi.ConnectionFactoryOptions;
import
org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer
;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyR2dbcConfiguration {
@Bean
public ConnectionFactoryOptionsBuilderCustomizer connectionFactoryPortCustomizer()
{
return (builder) -> builder.option(ConnectionFactoryOptions.PORT, 5432);
}
The following examples show how to set some PostgreSQL connection options:
import java.util.HashMap;
import java.util.Map;
import io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider;
import
org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsBuilderCustomizer
;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyPostgresR2dbcConfiguration {
@Bean
public ConnectionFactoryOptionsBuilderCustomizer postgresCustomizer() {
Map<String, String> options = new HashMap<>();
options.put("lock_timeout", "30s");
options.put("statement_timeout", "60s");
return (builder) ->
builder.option(PostgresqlConnectionFactoryProvider.OPTIONS, options);
}
When a ConnectionFactory bean is available, the regular JDBC DataSource auto-configuration backs
off. If you want to retain the JDBC DataSource auto-configuration, and are comfortable with the risk
233
of using the blocking JDBC API in a reactive application, add
@Import(DataSourceAutoConfiguration.class) on a @Configuration class in your application to re-
enable it.
Similarly to the JDBC support, Spring Boot can automatically configure an embedded database for
reactive usage. You need not provide any connection URLs. You need only include a build
dependency to the embedded database that you want to use, as shown in the following example:
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-h2</artifactId>
<scope>runtime</scope>
</dependency>
If you are using this feature in your tests, you may notice that the same database is
reused by your whole test suite regardless of the number of application contexts
NOTE
that you use. If you want to make sure that each context has a separate embedded
database, you should set spring.r2dbc.generate-unique-name to true.
Using DatabaseClient
A DatabaseClient bean is auto-configured, and you can @Autowire it directly into your own beans, as
shown in the following example:
import java.util.Map;
import reactor.core.publisher.Flux;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
234
Spring Data R2DBC Repositories
Spring Data R2DBC repositories are interfaces that you can define to access data. Queries are
created automatically from your method names. For example, a CityRepository interface might
declare a findAllByState(String state) method to find all the cities in a given state.
For more complex queries, you can annotate your method with Spring Data’s Query annotation.
Spring Data repositories usually extend from the Repository or CrudRepository interfaces. If you use
auto-configuration, repositories are searched from the package containing your main configuration
class (the one annotated with @EnableAutoConfiguration or @SpringBootApplication) down.
The following example shows a typical Spring Data repository interface definition:
import reactor.core.publisher.Mono;
import org.springframework.data.repository.Repository;
We have barely scratched the surface of Spring Data R2DBC. For complete details, see
TIP
the Spring Data R2DBC reference documentation.
• MongoDB
• Neo4J
• Elasticsearch
• Redis
• GemFire or Geode
• Cassandra
• Couchbase
• LDAP
Spring Boot provides auto-configuration for Redis, MongoDB, Neo4j, Solr, Elasticsearch, Cassandra,
Couchbase, LDAP and InfluxDB. You can make use of the other projects, but you must configure
them yourself. See the appropriate reference documentation at spring.io/projects/spring-data.
235
9.2.1. Redis
Redis is a cache, message broker, and richly-featured key-value store. Spring Boot offers basic auto-
configuration for the Lettuce and Jedis client libraries and the abstractions on top of them provided
by Spring Data Redis.
Connecting to Redis
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
If you add your own @Bean of any of the auto-configured types, it replaces the default (except in the
case of RedisTemplate, when the exclusion is based on the bean name, redisTemplate, not its type).
236
9.2.2. MongoDB
MongoDB is an open-source NoSQL document database that uses a JSON-like schema instead of
traditional table-based relational data. Spring Boot offers several conveniences for working with
MongoDB, including the spring-boot-starter-data-mongodb and spring-boot-starter-data-mongodb-
reactive “Starters”.
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
If you have defined your own MongoClient, it will be used to auto-configure a suitable
MongoDatabaseFactory.
The auto-configured MongoClient is created using a MongoClientSettings bean. If you have defined
your own MongoClientSettings, it will be used without modification and the spring.data.mongodb
properties will be ignored. Otherwise a MongoClientSettings will be auto-configured and will have
the spring.data.mongodb properties applied to it. In either case, you can declare one or more
MongoClientSettingsBuilderCustomizer beans to fine-tune the MongoClientSettings configuration.
Each will be called in order with the MongoClientSettings.Builder that is used to build the
MongoClientSettings.
You can set the spring.data.mongodb.uri property to change the URL and configure additional
237
settings such as the replica set, as shown in the following example:
Properties
spring.data.mongodb.uri=mongodb://user:secret@mongo1.example.com:12345,mongo2.example.
com:23456/test
Yaml
spring:
data:
mongodb:
uri:
"mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test"
Alternatively, you can specify connection details using discrete properties. For example, you might
declare the following settings in your application.properties:
Properties
spring.data.mongodb.host=mongoserver.example.com
spring.data.mongodb.port=27017
spring.data.mongodb.database=test
spring.data.mongodb.username=user
spring.data.mongodb.password=secret
Yaml
spring:
data:
mongodb:
host: "mongoserver.example.com"
port: 27017
database: "test"
username: "user"
password: "secret"
If you do not use Spring Data MongoDB, you can inject a MongoClient bean instead of
using MongoDatabaseFactory. If you want to take complete control of establishing the
TIP
MongoDB connection, you can also declare your own MongoDatabaseFactory or
MongoClient bean.
238
If you are using the reactive driver, Netty is required for SSL. The auto-
NOTE configuration configures this factory automatically if Netty is available and the
factory to use has not been customized already.
MongoTemplate
Spring Data MongoDB provides a MongoTemplate class that is very similar in its design to Spring’s
JdbcTemplate. As with JdbcTemplate, Spring Boot auto-configures a bean for you to inject the
template, as follows:
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
Spring Data includes repository support for MongoDB. As with the JPA repositories discussed
earlier, the basic principle is that queries are constructed automatically, based on method names.
In fact, both Spring Data JPA and Spring Data MongoDB share the same common infrastructure. You
could take the JPA example from earlier and, assuming that City is now a MongoDB data class
rather than a JPA @Entity, it works in the same way, as shown in the following example:
239
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
TIP You can customize document scanning locations by using the @EntityScan annotation.
For complete details of Spring Data MongoDB, including its rich object mapping
TIP
technologies, see its reference documentation.
Embedded Mongo
Spring Boot offers auto-configuration for Embedded Mongo. To use it in your Spring Boot
application, add a dependency on de.flapdoodle.embed:de.flapdoodle.embed.mongo and set the
spring.mongodb.embedded.version property to match the version of MongoDB that your application
will use in production.
The default download configuration allows access to most of the versions listed in
Embedded Mongo’s Version class as well as some others. Configuring an
NOTE inaccessible version will result in an error when attempting to download the server.
Such an error can be corrected by defining an appropriately configured
DownloadConfigBuilderCustomizer bean.
The port that Mongo listens on can be configured by setting the spring.data.mongodb.port property.
To use a randomly allocated free port, use a value of 0. The MongoClient created by
MongoAutoConfiguration is automatically configured to use the randomly allocated port.
If you do not configure a custom port, the embedded support uses a random port
NOTE
(rather than 27017) by default.
If you have SLF4J on the classpath, the output produced by Mongo is automatically routed to a
logger named org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongo.
You can declare your own IMongodConfig and IRuntimeConfig beans to take control of the Mongo
instance’s configuration and logging routing. The download configuration can be customized by
declaring a DownloadConfigBuilderCustomizer bean.
9.2.3. Neo4j
Neo4j is an open-source NoSQL graph database that uses a rich data model of nodes connected by
240
first class relationships, which is better suited for connected big data than traditional RDBMS
approaches. Spring Boot offers several conveniences for working with Neo4j, including the spring-
boot-starter-data-neo4j “Starter”.
To access a Neo4j server, you can inject an auto-configured org.neo4j.driver.Driver. By default, the
instance tries to connect to a Neo4j server at localhost:7687 using the Bolt protocol. The following
example shows how to inject a Neo4j Driver that gives you access, amongst other things, to a
Session:
import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.neo4j.driver.Values;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
You can configure various aspects of the driver using spring.neo4j.* properties. The following
example shows how to configure the uri and credentials to use:
Properties
spring.neo4j.uri=bolt://my-server:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret
241
Yaml
spring:
neo4j:
uri: "bolt://my-server:7687"
authentication:
username: "neo4j"
password: "secret"
The auto-configured Driver is created using ConfigBuilder. To fine-tune its configuration, declare
one or more ConfigBuilderCustomizer beans. Each will be called in order with the ConfigBuilder that
is used to build the Driver.
Spring Data includes repository support for Neo4j. For complete details of Spring Data Neo4j, see
the reference documentation.
Spring Data Neo4j shares the common infrastructure with Spring Data JPA as many other Spring
Data modules do. You could take the JPA example from earlier and define City as Spring Data Neo4j
@Node rather than JPA @Entity and the repository abstraction works in the same way, as shown in
the following example:
import java.util.Optional;
import org.springframework.data.neo4j.repository.Neo4jRepository;
You can customize the locations to look for repositories and entities by using
@EnableNeo4jRepositories and @EntityScan respectively on a @Configuration-bean.
242
In an application using the reactive style, a ReactiveTransactionManager is not auto-
configured. To enable transaction management, the following bean must be defined
in your configuration:
import org.neo4j.driver.Driver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import
org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider;
import
org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransaction
Manager;
NOTE
@Configuration(proxyBeanMethods = false)
public class MyNeo4jConfiguration {
@Bean
public ReactiveNeo4jTransactionManager
reactiveTransactionManager(Driver driver,
ReactiveDatabaseSelectionProvider databaseNameProvider) {
return new ReactiveNeo4jTransactionManager(driver,
databaseNameProvider);
}
9.2.4. Solr
Apache Solr is a search engine. Spring Boot offers basic auto-configuration for the Solr 5 client
library.
Connecting to Solr
You can inject an auto-configured SolrClient instance as you would any other Spring bean. By
default, the instance tries to connect to a server at localhost:8983/solr. The following example
shows how to inject a Solr bean:
243
import java.io.IOException;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.SolrPingResponse;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
If you add your own @Bean of type SolrClient, it replaces the default.
9.2.5. Elasticsearch
Elasticsearch is an open source, distributed, RESTful search and analytics engine. Spring Boot offers
basic auto-configuration for Elasticsearch clients.
• The official Java "Low Level" and "High Level" REST clients
Elasticsearch ships two different REST clients that you can use to query a cluster: the "Low Level"
client and the "High Level" client. Spring Boot provides support for the "High Level" client, which
ships with org.elasticsearch.client:elasticsearch-rest-high-level-client. Additionally, Spring
Boot provides support for a reactive client, based on Spring Framework’s WebClient, that ships with
org.springframework.data:spring-data-elasticsearch. By default, the clients will target
localhost:9200. You can use spring.elasticsearch.* properties to further tune how the clients are
configured, as shown in the following example:
244
Properties
spring.elasticsearch.uris=https://search.example.com:9200
spring.elasticsearch.socket-timeout=10s
spring.elasticsearch.username=user
spring.elasticsearch.password=secret
Yaml
spring:
elasticsearch:
uris: "https://search.example.com:9200"
socket-timeout: "10s"
username: "user"
password: "secret"
If your application needs access to a "Low Level" RestClient, you can get it by calling
TIP
client.getLowLevelClient() on the auto-configured RestHighLevelClient.
Properties
spring.elasticsearch.restclient.sniffer.interval=10m
spring.elasticsearch.restclient.sniffer.delay-after-failure=30s
Yaml
spring:
elasticsearch:
restclient:
sniffer:
interval: "10m"
delay-after-failure: "30s"
245
Connecting to Elasticsearch using ReactiveElasticsearchClient
Properties
spring.elasticsearch.webclient.max-in-memory-size=1MB
Yaml
spring:
elasticsearch:
webclient:
max-in-memory-size: "1MB"
246
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
In the presence of spring-data-elasticsearch and the required dependencies for using a WebClient
(typically spring-boot-starter-webflux), Spring Boot can also auto-configure a
ReactiveElasticsearchClient and a ReactiveElasticsearchTemplate as beans. They are the reactive
equivalent of the other REST clients.
Spring Data includes repository support for Elasticsearch. As with the JPA repositories discussed
earlier, the basic principle is that queries are constructed for you automatically based on method
names.
In fact, both Spring Data JPA and Spring Data Elasticsearch share the same common infrastructure.
You could take the JPA example from earlier and, assuming that City is now an Elasticsearch
@Document class rather than a JPA @Entity, it works in the same way.
TIP For complete details of Spring Data Elasticsearch, see the reference documentation.
Spring Boot supports both classic and reactive Elasticsearch repositories, using the
ElasticsearchRestTemplate or ReactiveElasticsearchTemplate beans. Most likely those beans are
auto-configured by Spring Boot given the required dependencies are present.
If you wish to use your own template for backing the Elasticsearch repositories, you can add your
own ElasticsearchRestTemplate or ElasticsearchOperations @Bean, as long as it is named
"elasticsearchTemplate". Same applies to ReactiveElasticsearchTemplate and
ReactiveElasticsearchOperations, with the bean name "reactiveElasticsearchTemplate".
You can choose to disable the repositories support with the following property:
247
Properties
spring.data.elasticsearch.repositories.enabled=false
Yaml
spring:
data:
elasticsearch:
repositories:
enabled: false
9.2.6. Cassandra
Cassandra is an open source, distributed database management system designed to handle large
amounts of data across many commodity servers. Spring Boot offers auto-configuration for
Cassandra and the abstractions on top of it provided by Spring Data Cassandra. There is a spring-
boot-starter-data-cassandra “Starter” for collecting the dependencies in a convenient way.
Connecting to Cassandra
Properties
spring.data.cassandra.keyspace-name=mykeyspace
spring.data.cassandra.contact-points=cassandrahost1:9042,cassandrahost2:9042
spring.data.cassandra.local-datacenter=datacenter1
Yaml
spring:
data:
cassandra:
keyspace-name: "mykeyspace"
contact-points: "cassandrahost1:9042,cassandrahost2:9042"
local-datacenter: "datacenter1"
If the port is the same for all your contact points you can use a shortcut and only specify the host
names, as shown in the following example:
248
Properties
spring.data.cassandra.keyspace-name=mykeyspace
spring.data.cassandra.contact-points=cassandrahost1,cassandrahost2
spring.data.cassandra.local-datacenter=datacenter1
Yaml
spring:
data:
cassandra:
keyspace-name: "mykeyspace"
contact-points: "cassandrahost1,cassandrahost2"
local-datacenter: "datacenter1"
Those two examples are identical as the port default to 9042. If you need to configure
TIP
the port, use spring.data.cassandra.port.
The Cassandra driver has its own configuration infrastructure that loads an
application.conf at the root of the classpath.
Spring Boot does not look for such a file by default but can load one using
spring.data.cassandra.config. If a property is both present in
NOTE spring.data.cassandra.* and the configuration file, the value in
spring.data.cassandra.* takes precedence.
For more advanced driver customizations, you can register an arbitrary number of
beans that implement DriverConfigLoaderBuilderCustomizer. The CqlSession can be
customized with a bean of type CqlSessionBuilderCustomizer.
If you use CqlSessionBuilder to create multiple CqlSession beans, keep in mind the
NOTE
builder is mutable so make sure to inject a fresh copy for each session.
249
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
If you add your own @Bean of type CassandraTemplate, it replaces the default.
Spring Data includes basic repository support for Cassandra. Currently, this is more limited than
the JPA repositories discussed earlier and needs to annotate finder methods with @Query.
TIP For complete details of Spring Data Cassandra, see the reference documentation.
9.2.7. Couchbase
Connecting to Couchbase
You can get a Cluster by adding the Couchbase SDK and some configuration. The spring.couchbase.*
properties can be used to customize the connection. Generally, you provide the connection string,
username, and password, as shown in the following example:
Properties
spring.couchbase.connection-string=couchbase://192.168.1.123
spring.couchbase.username=user
spring.couchbase.password=secret
250
Yaml
spring:
couchbase:
connection-string: "couchbase://192.168.1.123"
username: "user"
password: "secret"
It is also possible to customize some of the ClusterEnvironment settings. For instance, the following
configuration changes the timeout to use to open a new Bucket and enables SSL support:
Properties
spring.couchbase.env.timeouts.connect=3s
spring.couchbase.env.ssl.key-store=/location/of/keystore.jks
spring.couchbase.env.ssl.key-store-password=secret
Yaml
spring:
couchbase:
env:
timeouts:
connect: "3s"
ssl:
key-store: "/location/of/keystore.jks"
key-store-password: "secret"
Check the spring.couchbase.env.* properties for more details. To take more control,
TIP
one or more ClusterEnvironmentBuilderCustomizer beans can be used.
Spring Data includes repository support for Couchbase. For complete details of Spring Data
Couchbase, see the reference documentation.
You can inject an auto-configured CouchbaseTemplate instance as you would with any other Spring
Bean, provided a CouchbaseClientFactory bean is available. This happens when a Cluster is
available, as described above, and a bucket name has been specified:
Properties
spring.data.couchbase.bucket-name=my-bucket
251
Yaml
spring:
data:
couchbase:
bucket-name: "my-bucket"
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
There are a few beans that you can define in your own configuration to override those provided by
the auto-configuration:
To avoid hard-coding those names in your own config, you can reuse BeanNames provided by Spring
Data Couchbase. For instance, you can customize the converters to use, as follows:
252
import org.assertj.core.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.config.BeanNames;
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;
@Configuration(proxyBeanMethods = false)
public class MyCouchbaseConfiguration {
@Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
public CouchbaseCustomConversions myCustomConversions() {
return new CouchbaseCustomConversions(Arrays.asList(new MyConverter()));
}
9.2.8. LDAP
To connect to an LDAP server, make sure you declare a dependency on the spring-boot-starter-
data-ldap “Starter” or spring-ldap-core and then declare the URLs of your server in your
application.properties, as shown in the following example:
Properties
spring.ldap.urls=ldap://myserver:1235
spring.ldap.username=admin
spring.ldap.password=secret
Yaml
spring:
ldap:
urls: "ldap://myserver:1235"
username: "admin"
password: "secret"
If you need to customize connection settings, you can use the spring.ldap.base and
253
spring.ldap.base-environment properties.
Spring Data includes repository support for LDAP. For complete details of Spring Data LDAP, see the
reference documentation.
You can also inject an auto-configured LdapTemplate instance as you would with any other Spring
Bean, as shown in the following example:
import java.util.List;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
For testing purposes, Spring Boot supports auto-configuration of an in-memory LDAP server from
UnboundID. To configure the server, add a dependency to com.unboundid:unboundid-ldapsdk and
declare a spring.ldap.embedded.base-dn property, as follows:
Properties
spring.ldap.embedded.base-dn=dc=spring,dc=io
254
Yaml
spring:
ldap:
embedded:
base-dn: "dc=spring,dc=io"
In yaml files, you can use the yaml list notation. In properties files, you must
include the index as part of the property name:
Properties
NOTE spring.ldap.embedded.base-dn[0]=dc=spring,dc=io
spring.ldap.embedded.base-dn[1]=dc=pivotal,dc=io
Yaml
spring.ldap.embedded.base-dn:
- "dc=spring,dc=io"
- "dc=pivotal,dc=io"
By default, the server starts on a random port and triggers the regular LDAP support. There is no
need to specify a spring.ldap.urls property.
If there is a schema.ldif file on your classpath, it is used to initialize the server. If you want to load
the initialization script from a different resource, you can also use the spring.ldap.embedded.ldif
property.
By default, a standard schema is used to validate LDIF files. You can turn off validation altogether by
setting the spring.ldap.embedded.validation.enabled property. If you have custom attributes, you
can use spring.ldap.embedded.validation.schema to define your custom attribute types or object
classes.
9.2.9. InfluxDB
InfluxDB is an open-source time series database optimized for fast, high-availability storage and
retrieval of time series data in fields such as operations monitoring, application metrics, Internet-
of-Things sensor data, and real-time analytics.
Connecting to InfluxDB
Spring Boot auto-configures an InfluxDB instance, provided the influxdb-java client is on the
classpath and the URL of the database is set, as shown in the following example:
255
Properties
spring.influx.url=https://172.0.0.1:8086
Yaml
spring:
influx:
url: "https://172.0.0.1:8086"
If the connection to InfluxDB requires a user and password, you can set the spring.influx.user and
spring.influx.password properties accordingly.
InfluxDB relies on OkHttp. If you need to tune the http client InfluxDB uses behind the scenes, you
can register an InfluxDbOkHttpClientBuilderProvider bean.
If you need more control over the configuration, consider registering an InfluxDbCustomizer bean.
256
Chapter 10. Messaging
The Spring Framework provides extensive support for integrating with messaging systems, from
simplified use of the JMS API using JmsTemplate to a complete infrastructure to receive messages
asynchronously. Spring AMQP provides a similar feature set for the Advanced Message Queuing
Protocol. Spring Boot also provides auto-configuration options for RabbitTemplate and RabbitMQ.
Spring WebSocket natively includes support for STOMP messaging, and Spring Boot has support for
that through starters and a small amount of auto-configuration. Spring Boot also has support for
Apache Kafka.
10.1. JMS
The javax.jms.ConnectionFactory interface provides a standard method of creating a
javax.jms.Connection for interacting with a JMS broker. Although Spring needs a ConnectionFactory
to work with JMS, you generally need not use it directly yourself and can instead rely on higher
level messaging abstractions. (See the relevant section of the Spring Framework reference
documentation for details.) Spring Boot also auto-configures the necessary infrastructure to send
and receive messages.
Spring Boot can auto-configure a ConnectionFactory when it detects that ActiveMQ Artemis is
available on the classpath. If the broker is present, an embedded broker is automatically started
and configured (unless the mode property has been explicitly set). The supported modes are
embedded (to make explicit that an embedded broker is required and that an error should occur if
the broker is not available on the classpath) and native (to connect to a broker using the netty
transport protocol). When the latter is configured, Spring Boot configures a ConnectionFactory that
connects to a broker running on the local machine with the default settings.
Properties
spring.artemis.mode=native
spring.artemis.broker-url=tcp://192.168.1.210:9876
spring.artemis.user=admin
spring.artemis.password=secret
257
Yaml
spring:
artemis:
mode: native
broker-url: "tcp://192.168.1.210:9876"
user: "admin"
password: "secret"
When embedding the broker, you can choose if you want to enable persistence and list the
destinations that should be made available. These can be specified as a comma-separated list to
create them with the default options, or you can define bean(s) of type
org.apache.activemq.artemis.jms.server.config.JMSQueueConfiguration or
org.apache.activemq.artemis.jms.server.config.TopicConfiguration, for advanced queue and topic
configurations, respectively.
Properties
spring.jms.cache.session-cache-size=5
Yaml
spring:
jms:
cache:
session-cache-size: 5
No JNDI lookup is involved, and destinations are resolved against their names, using either the name
attribute in the Artemis configuration or the names provided through configuration.
If you are running your application in an application server, Spring Boot tries to locate a JMS
ConnectionFactory by using JNDI. By default, the java:/JmsXA and java:/XAConnectionFactory location
are checked. You can use the spring.jms.jndi-name property if you need to specify an alternative
location, as shown in the following example:
Properties
spring.jms.jndi-name=java:/MyConnectionFactory
258
Yaml
spring:
jms:
jndi-name: "java:/MyConnectionFactory"
Spring’s JmsTemplate is auto-configured, and you can autowire it directly into your own beans, as
shown in the following example:
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
When the JMS infrastructure is present, any bean can be annotated with @JmsListener to create a
listener endpoint. If no JmsListenerContainerFactory has been defined, a default one is configured
automatically. If a DestinationResolver, a MessageConverter, or a javax.jms.ExceptionListener beans
are defined, they are associated automatically with the default factory.
259
The following component creates a listener endpoint on the someQueue destination:
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@JmsListener(destination = "someQueue")
public void processMessage(String content) {
// ...
}
If you need to create more JmsListenerContainerFactory instances or if you want to override the
default, Spring Boot provides a DefaultJmsListenerContainerFactoryConfigurer that you can use to
initialize a DefaultJmsListenerContainerFactory with the same settings as the one that is auto-
configured.
For instance, the following example exposes another factory that uses a specific MessageConverter:
260
import jakarta.jms.ConnectionFactory;
import
org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigure
r;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
@Configuration(proxyBeanMethods = false)
public class MyJmsConfiguration {
@Bean
public DefaultJmsListenerContainerFactory
myFactory(DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new
DefaultJmsListenerContainerFactory();
ConnectionFactory connectionFactory = getCustomConnectionFactory();
configurer.configure(factory, connectionFactory);
factory.setMessageConverter(new MyMessageConverter());
return factory;
}
Then you can use the factory in any @JmsListener-annotated method as follows:
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
10.2. AMQP
The Advanced Message Queuing Protocol (AMQP) is a platform-neutral, wire-level protocol for
message-oriented middleware. The Spring AMQP project applies core Spring concepts to the
261
development of AMQP-based messaging solutions. Spring Boot offers several conveniences for
working with AMQP through RabbitMQ, including the spring-boot-starter-amqp “Starter”.
RabbitMQ is a lightweight, reliable, scalable, and portable message broker based on the AMQP
protocol. Spring uses RabbitMQ to communicate through the AMQP protocol.
Properties
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=secret
Yaml
spring:
rabbitmq:
host: "localhost"
port: 5672
username: "admin"
password: "secret"
Alternatively, you could configure the same connection using the addresses attribute:
Properties
spring.rabbitmq.addresses=amqp://admin:secret@localhost
Yaml
spring:
rabbitmq:
addresses: "amqp://admin:secret@localhost"
When specifying addresses that way, the host and port properties are ignored. If the
NOTE
address uses the amqps protocol, SSL support is enabled automatically.
See RabbitProperties for more of the supported property-based configuration options. To configure
lower-level details of the RabbitMQ ConnectionFactory that is used by Spring AMQP, define a
ConnectionFactoryCustomizer bean.
262
TIP See Understanding AMQP, the protocol used by RabbitMQ for more details.
Spring’s AmqpTemplate and AmqpAdmin are auto-configured, and you can autowire them directly into
your own beans, as shown in the following example:
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
To retry operations, you can enable retries on the AmqpTemplate (for example, in the event that the
broker connection is lost):
Properties
spring.rabbitmq.template.retry.enabled=true
spring.rabbitmq.template.retry.initial-interval=2s
263
Yaml
spring:
rabbitmq:
template:
retry:
enabled: true
initial-interval: "2s"
Retries are disabled by default. You can also customize the RetryTemplate programmatically by
declaring a RabbitRetryTemplateCustomizer bean.
If you need to create more RabbitTemplate instances or if you want to override the default, Spring
Boot provides a RabbitTemplateConfigurer bean that you can use to initialize a RabbitTemplate with
the same settings as the factories used by the auto-configuration.
To send a message to a particular stream, specify the name of the stream, as shown in the following
example:
Properties
spring.rabbitmq.stream.name=my-stream
Yaml
spring:
rabbitmq:
stream:
name: "my-stream"
If you need to create more RabbitStreamTemplate instances or if you want to override the default,
Spring Boot provides a RabbitStreamTemplateConfigurer bean that you can use to initialize a
RabbitStreamTemplate with the same settings as the factories used by the auto-configuration.
When the Rabbit infrastructure is present, any bean can be annotated with @RabbitListener to
create a listener endpoint. If no RabbitListenerContainerFactory has been defined, a default
SimpleRabbitListenerContainerFactory is automatically configured and you can switch to a direct
container using the spring.rabbitmq.listener.type property. If a MessageConverter or a
MessageRecoverer bean is defined, it is automatically associated with the default factory.
The following sample component creates a listener endpoint on the someQueue queue:
264
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@RabbitListener(queues = "someQueue")
public void processMessage(String content) {
// ...
}
If you need to create more RabbitListenerContainerFactory instances or if you want to override the
default, Spring Boot provides a SimpleRabbitListenerContainerFactoryConfigurer and a
DirectRabbitListenerContainerFactoryConfigurer that you can use to initialize a
SimpleRabbitListenerContainerFactory and a DirectRabbitListenerContainerFactory with the same
settings as the factories used by the auto-configuration.
It does not matter which container type you chose. Those two beans are exposed by
TIP
the auto-configuration.
For instance, the following configuration class exposes another factory that uses a specific
MessageConverter:
265
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import
org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfig
urer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyRabbitConfiguration {
@Bean
public SimpleRabbitListenerContainerFactory
myFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer) {
SimpleRabbitListenerContainerFactory factory = new
SimpleRabbitListenerContainerFactory();
ConnectionFactory connectionFactory = getCustomConnectionFactory();
configurer.configure(factory, connectionFactory);
factory.setMessageConverter(new MyMessageConverter());
return factory;
}
Then you can use the factory in any @RabbitListener-annotated method, as follows:
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
You can enable retries to handle situations where your listener throws an exception. By default,
RejectAndDontRequeueRecoverer is used, but you can define a MessageRecoverer of your own. When
retries are exhausted, the message is rejected and either dropped or routed to a dead-letter
exchange if the broker is configured to do so. By default, retries are disabled. You can also
customize the RetryTemplate programmatically by declaring a RabbitRetryTemplateCustomizer bean.
266
By default, if retries are disabled and the listener throws an exception, the
delivery is retried indefinitely. You can modify this behavior in two ways: Set
the defaultRequeueRejected property to false so that zero re-deliveries are
IMPORTANT
attempted or throw an AmqpRejectAndDontRequeueException to signal the
message should be rejected. The latter is the mechanism used when retries
are enabled and the maximum number of delivery attempts is reached.
Properties
spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=myGroup
Yaml
spring:
kafka:
bootstrap-servers: "localhost:9092"
consumer:
group-id: "myGroup"
To create a topic on startup, add a bean of type NewTopic. If the topic already exists, the
TIP
bean is ignored.
Spring’s KafkaTemplate is auto-configured, and you can autowire it directly in your own beans, as
shown in the following example:
267
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
When the Apache Kafka infrastructure is present, any bean can be annotated with @KafkaListener
to create a listener endpoint. If no KafkaListenerContainerFactory has been defined, a default one is
automatically configured with keys defined in spring.kafka.listener.*.
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@KafkaListener(topics = "someTopic")
public void processMessage(String content) {
// ...
}
268
Depending on the listener type, a RecordMessageConverter or BatchMessageConverter bean is
associated to the default factory. If only a RecordMessageConverter bean is present for a batch
listener, it is wrapped in a BatchMessageConverter.
Spring for Apache Kafka provides a factory bean to create a StreamsBuilder object and manage the
lifecycle of its streams. Spring Boot auto-configures the required KafkaStreamsConfiguration bean as
long as kafka-streams is on the classpath and Kafka Streams is enabled by the @EnableKafkaStreams
annotation.
Enabling Kafka Streams means that the application id and bootstrap servers must be set. The
former can be configured using spring.kafka.streams.application-id, defaulting to
spring.application.name if not set. The latter can be set globally or specifically overridden only for
streams.
Several additional properties are available using dedicated properties; other arbitrary Kafka
properties can be set using the spring.kafka.streams.properties namespace. See also Additional
Kafka Properties for more information.
To use the factory bean, wire StreamsBuilder into your @Bean as shown in the following example:
269
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KeyValue;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.kstream.KStream;
import org.apache.kafka.streams.kstream.Produced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafkaStreams;
import org.springframework.kafka.support.serializer.JsonSerde;
@Configuration(proxyBeanMethods = false)
@EnableKafkaStreams
public class MyKafkaStreamsConfiguration {
@Bean
public KStream<Integer, String> kStream(StreamsBuilder streamsBuilder) {
KStream<Integer, String> stream = streamsBuilder.stream("ks1In");
stream.map(this::uppercaseValue).to("ks1Out", Produced.with(Serdes.Integer(),
new JsonSerde<>()));
return stream;
}
By default, the streams managed by the StreamBuilder object it creates are started automatically.
You can customize this behavior using the spring.kafka.streams.auto-startup property.
The properties supported by auto configuration are shown in Common Application Properties. Note
that, for the most part, these properties (hyphenated or camelCase) map directly to the Apache
Kafka dotted properties. See the Apache Kafka documentation for details.
The first few of these properties apply to all components (producers, consumers, admins, and
streams) but can be specified at the component level if you wish to use different values. Apache
Kafka designates properties with an importance of HIGH, MEDIUM, or LOW. Spring Boot auto-
configuration supports all HIGH importance properties, some selected MEDIUM and LOW
properties, and any properties that do not have a default value.
Only a subset of the properties supported by Kafka are available directly through the
KafkaProperties class. If you wish to configure the producer or consumer with additional properties
that are not directly supported, use the following properties:
270
Properties
spring.kafka.properties[prop.one]=first
spring.kafka.admin.properties[prop.two]=second
spring.kafka.consumer.properties[prop.three]=third
spring.kafka.producer.properties[prop.four]=fourth
spring.kafka.streams.properties[prop.five]=fifth
Yaml
spring:
kafka:
properties:
"[prop.one]": "first"
admin:
properties:
"[prop.two]": "second"
consumer:
properties:
"[prop.three]": "third"
producer:
properties:
"[prop.four]": "fourth"
streams:
properties:
"[prop.five]": "fifth"
This sets the common prop.one Kafka property to first (applies to producers, consumers and
admins), the prop.two admin property to second, the prop.three consumer property to third, the
prop.four producer property to fourth and the prop.five streams property to fifth.
Properties
spring.kafka.consumer.value-
deserializer=org.springframework.kafka.support.serializer.JsonDeserializer
spring.kafka.consumer.properties[spring.json.value.default.type]=com.example.Invoice
spring.kafka.consumer.properties[spring.json.trusted.packages]=com.example.main,com.ex
ample.another
271
Yaml
spring:
kafka:
consumer:
value-deserializer:
"org.springframework.kafka.support.serializer.JsonDeserializer"
properties:
"[spring.json.value.default.type]": "com.example.Invoice"
"[spring.json.trusted.packages]": "com.example.main,com.example.another"
Similarly, you can disable the JsonSerializer default behavior of sending type information in
headers:
Properties
spring.kafka.producer.value-
serializer=org.springframework.kafka.support.serializer.JsonSerializer
spring.kafka.producer.properties[spring.json.add.type.headers]=false
Yaml
spring:
kafka:
producer:
value-serializer: "org.springframework.kafka.support.serializer.JsonSerializer"
properties:
"[spring.json.add.type.headers]": false
Properties set in this way override any configuration item that Spring Boot
IMPORTANT
explicitly supports.
Spring for Apache Kafka provides a convenient way to test projects with an embedded Apache
Kafka broker. To use this feature, annotate a test class with @EmbeddedKafka from the spring-kafka-
test module. For more information, please see the Spring for Apache Kafka reference manual.
To make Spring Boot auto-configuration work with the aforementioned embedded Apache Kafka
broker, you need to remap a system property for embedded broker addresses (populated by the
EmbeddedKafkaBroker) into the Spring Boot configuration property for Apache Kafka. There are
several ways to do that:
272
static {
System.setProperty(EmbeddedKafkaBroker.BROKER_LIST_PROPERTY,
"spring.kafka.bootstrap-servers");
}
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.kafka.test.context.EmbeddedKafka;
@SpringBootTest
@EmbeddedKafka(topics = "someTopic", bootstrapServersProperty =
"spring.kafka.bootstrap-servers")
class MyTest {
// ...
Properties
spring.kafka.bootstrap-servers=${spring.embedded.kafka.brokers}
Yaml
spring:
kafka:
bootstrap-servers: "${spring.embedded.kafka.brokers}"
10.4. RSocket
RSocket is a binary protocol for use on byte stream transports. It enables symmetric interaction
models through async message passing over a single connection.
The spring-messaging module of the Spring Framework provides support for RSocket requesters
and responders, both on the client and on the server side. See the RSocket section of the Spring
Framework reference for more details, including an overview of the RSocket protocol.
Spring Boot auto-configures an RSocketStrategies bean that provides all the required infrastructure
for encoding and decoding RSocket payloads. By default, the auto-configuration will try to configure
the following (in order):
273
1. CBOR codecs with Jackson
The spring-boot-starter-rsocket starter provides both dependencies. See the Jackson support
section to know more about customization possibilities.
Developers can customize the RSocketStrategies component by creating beans that implement the
RSocketStrategiesCustomizer interface. Note that their @Order is important, as it determines the
order of codecs.
Spring Boot provides RSocket server auto-configuration. The required dependencies are provided
by the spring-boot-starter-rsocket.
Spring Boot allows exposing RSocket over WebSocket from a WebFlux server, or standing up an
independent RSocket server. This depends on the type of application and its configuration.
For WebFlux application (that is of type WebApplicationType.REACTIVE), the RSocket server will be
plugged into the Web Server only if the following properties match:
Properties
spring.rsocket.server.mapping-path=/rsocket
spring.rsocket.server.transport=websocket
Yaml
spring:
rsocket:
server:
mapping-path: "/rsocket"
transport: "websocket"
Plugging RSocket into a web server is only supported with Reactor Netty, as
WARNING
RSocket itself is built with that library.
Properties
spring.rsocket.server.port=9898
274
Yaml
spring:
rsocket:
server:
port: 9898
Spring Boot will auto-configure the Spring Messaging infrastructure for RSocket.
This means that Spring Boot will create a RSocketMessageHandler bean that will handle RSocket
requests to your application.
Once the RSocket channel is established between server and client, any party can send or receive
requests to the other.
As a server, you can get injected with an RSocketRequester instance on any handler method of an
RSocket @Controller. As a client, you need to configure and establish an RSocket connection first.
Spring Boot auto-configures an RSocketRequester.Builder for such cases with the expected codecs
and applies any RSocketConnectorConfigurer bean.
The RSocketRequester.Builder instance is a prototype bean, meaning each injection point will
provide you with a new instance . This is done on purpose since this builder is stateful and you
should not create requesters with different setups using the same instance.
275
import reactor.core.publisher.Mono;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.stereotype.Service;
@Service
public class MyService {
Spring Integration polling logic relies on the auto-configured TaskScheduler. The default
PollerMetadata (poll unbounded number of messages every second) can be customized with
spring.integration.poller.* configuration properties.
Spring Boot also configures some features that are triggered by the presence of additional Spring
Integration modules. If spring-integration-jmx is also on the classpath, message processing
statistics are published over JMX. If spring-integration-jdbc is available, the default database
schema can be created on startup, as shown in the following line:
Properties
spring.integration.jdbc.initialize-schema=always
Yaml
spring:
integration:
jdbc:
initialize-schema: "always"
276
If spring-integration-rsocket is available, developers can configure an RSocket server using
"spring.rsocket.server.*" properties and let it use IntegrationRSocketEndpoint or
RSocketOutboundGateway components to handle incoming RSocket messages. This infrastructure can
handle Spring Integration RSocket channel adapters and @MessageMapping handlers (given
"spring.integration.rsocket.server.message-mapping-enabled" is configured).
Properties
Yaml
Properties
Yaml
277
Chapter 11. IO
Most applications will need to deal with input and output concerns at some point. Spring Boot
provides utilities and integrations with a range of technologies to help when you need IO
capabilities. This section covers standard IO features such as caching and validation as well as more
advanced topics such as scheduling and distributed transactions. We will also cover calling remote
REST or SOAP services and sending email.
11.1. Caching
The Spring Framework provides support for transparently adding caching to an application. At its
core, the abstraction applies caching to methods, thus reducing the number of executions based on
the information available in the cache. The caching logic is applied transparently, without any
interference to the invoker. Spring Boot auto-configures the cache infrastructure as long as caching
support is enabled by using the @EnableCaching annotation.
NOTE Check the relevant section of the Spring Framework reference for more details.
In a nutshell, to add caching to an operation of your service add the relevant annotation to its
method, as shown in the following example:
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class MyMathService {
@Cacheable("piDecimals")
public int computePiDecimal(int precision) {
...
}
This example demonstrates the use of caching on a potentially costly operation. Before invoking
computePiDecimal, the abstraction looks for an entry in the piDecimals cache that matches the i
argument. If an entry is found, the content in the cache is immediately returned to the caller, and
the method is not invoked. Otherwise, the method is invoked, and the cache is updated before
returning the value.
You can also use the standard JSR-107 (JCache) annotations (such as
CAUTION @CacheResult) transparently. However, we strongly advise you to not mix and
match the Spring Cache and JCache annotations.
If you do not add any specific cache library, Spring Boot auto-configures a simple provider that uses
concurrent maps in memory. When a cache is required (such as piDecimals in the preceding
example), this provider creates it for you. The simple provider is not really recommended for
278
production usage, but it is great for getting started and making sure that you understand the
features. When you have made up your mind about the cache provider to use, please make sure to
read its documentation to figure out how to configure the caches that your application uses. Nearly
all providers require you to explicitly configure every cache that you use in the application. Some
offer a way to customize the default caches defined by the spring.cache.cache-names property.
TIP It is also possible to transparently update or evict data from the cache.
The cache abstraction does not provide an actual store and relies on abstraction materialized by the
org.springframework.cache.Cache and org.springframework.cache.CacheManager interfaces.
If you have not defined a bean of type CacheManager or a CacheResolver named cacheResolver (see
CachingConfigurer), Spring Boot tries to detect the following providers (in the indicated order):
1. Generic
3. Hazelcast
4. Couchbase
5. Redis
6. Caffeine
7. Simple
If the CacheManager is auto-configured by Spring Boot, you can further tune its configuration before
it is fully initialized by exposing a bean that implements the CacheManagerCustomizer interface. The
following example sets a flag to say that null values should not be passed down to the underlying
map:
279
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyCacheManagerConfiguration {
@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer()
{
return (cacheManager) -> cacheManager.setAllowNullValues(false);
}
Generic
Generic caching is used if the context defines at least one org.springframework.cache.Cache bean. A
CacheManager wrapping all beans of that type is created.
JCache (JSR-107)
It might happen that more than one provider is present, in which case the provider must be
explicitly specified. Even if the JSR-107 standard does not enforce a standardized way to define the
location of the configuration file, Spring Boot does its best to accommodate setting a cache with
implementation details, as shown in the following example:
Properties
280
Yaml
When a cache library offers both a native implementation and JSR-107 support,
NOTE Spring Boot prefers the JSR-107 support, so that the same features are available if
you switch to a different JSR-107 implementation.
Hazelcast
Spring Boot has general support for Hazelcast. If a HazelcastInstance has been auto-configured, it is
automatically wrapped in a CacheManager.
Couchbase
Properties
spring.cache.cache-names=cache1,cache2
spring.cache.couchbase.expiration=10m
281
Yaml
spring:
cache:
cache-names: "cache1,cache2"
couchbase:
expiration: "10m"
import java.time.Duration;
import
org.springframework.boot.autoconfigure.cache.CouchbaseCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.cache.CouchbaseCacheConfiguration;
@Configuration(proxyBeanMethods = false)
public class MyCouchbaseCacheManagerConfiguration {
@Bean
public CouchbaseCacheManagerBuilderCustomizer
myCouchbaseCacheManagerBuilderCustomizer() {
return (builder) -> builder
.withCacheConfiguration("cache1", CouchbaseCacheConfiguration
.defaultCacheConfig().entryExpiry(Duration.ofSeconds(10)))
.withCacheConfiguration("cache2", CouchbaseCacheConfiguration
.defaultCacheConfig().entryExpiry(Duration.ofMinutes(1)));
}
Redis
Properties
spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=10m
282
Yaml
spring:
cache:
cache-names: "cache1,cache2"
redis:
time-to-live: "10m"
By default, a key prefix is added so that, if two separate caches use the same key,
NOTE Redis does not have overlapping keys and cannot return invalid values. We strongly
recommend keeping this setting enabled if you create your own RedisCacheManager.
import java.time.Duration;
import
org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
@Configuration(proxyBeanMethods = false)
public class MyRedisCacheManagerConfiguration {
@Bean
public RedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer() {
return (builder) -> builder
.withCacheConfiguration("cache1", RedisCacheConfiguration
.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)))
.withCacheConfiguration("cache2", RedisCacheConfiguration
.defaultCacheConfig().entryTtl(Duration.ofMinutes(1)));
}
Caffeine
Caffeine is a Java 8 rewrite of Guava’s cache that supersedes support for Guava. If Caffeine is
present, a CaffeineCacheManager (provided by the spring-boot-starter-cache “Starter”) is auto-
configured. Caches can be created on startup by setting the spring.cache.cache-names property and
283
can be customized by one of the following (in the indicated order):
For instance, the following configuration creates cache1 and cache2 caches with a maximum size of
500 and a time to live of 10 minutes
Properties
spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
Yaml
spring:
cache:
cache-names: "cache1,cache2"
caffeine:
spec: "maximumSize=500,expireAfterAccess=600s"
Simple
If none of the other providers can be found, a simple implementation using a ConcurrentHashMap as
the cache store is configured. This is the default if no caching library is present in your application.
By default, caches are created as needed, but you can restrict the list of available caches by setting
the cache-names property. For instance, if you want only cache1 and cache2 caches, set the cache-
names property as follows:
Properties
spring.cache.cache-names=cache1,cache2
Yaml
spring:
cache:
cache-names: "cache1,cache2"
If you do so and your application uses a cache not listed, then it fails at runtime when the cache is
needed, but not on startup. This is similar to the way the "real" cache providers behave if you use
284
an undeclared cache.
None
Properties
spring.cache.type=none
Yaml
spring:
cache:
type: "none"
11.2. Hazelcast
If Hazelcast is on the classpath and a suitable configuration is found, Spring Boot auto-configures a
HazelcastInstance that you can inject in your application.
Spring Boot first attempts to create a client by checking the following configuration options:
If a client can not be created, Spring Boot attempts to configure an embedded server. If you define a
com.hazelcast.config.Config bean, Spring Boot uses that. If your configuration defines an instance
name, Spring Boot tries to locate an existing instance rather than creating a new one.
You could also specify the Hazelcast configuration file to use through configuration, as shown in the
following example:
Properties
spring.hazelcast.config=classpath:config/my-hazelcast.xml
285
Yaml
spring:
hazelcast:
config: "classpath:config/my-hazelcast.xml"
Otherwise, Spring Boot tries to find the Hazelcast configuration from the default locations:
hazelcast.xml in the working directory or at the root of the classpath, or a .yaml counterpart in the
same locations. We also check if the hazelcast.config system property is set. See the Hazelcast
documentation for more details.
Spring Boot also has explicit caching support for Hazelcast. If caching is enabled,
NOTE
the HazelcastInstance is automatically wrapped in a CacheManager implementation.
Beans of the following types are automatically picked up and associated with the Scheduler:
• JobDetail: defines a particular Job. JobDetail instances can be built with the JobBuilder API.
• Calendar.
Properties
spring.quartz.job-store-type=jdbc
Yaml
spring:
quartz:
job-store-type: "jdbc"
When the JDBC store is used, the schema can be initialized on startup, as shown in the following
example:
286
Properties
spring.quartz.jdbc.initialize-schema=always
Yaml
spring:
quartz:
jdbc:
initialize-schema: "always"
To have Quartz use a DataSource other than the application’s main DataSource, declare a DataSource
bean, annotating its @Bean method with @QuartzDataSource. Doing so ensures that the Quartz-specific
DataSource is used by both the SchedulerFactoryBean and for schema initialization. Similarly, to have
Quartz use a TransactionManager other than the application’s main TransactionManager declare a
TransactionManager bean, annotating its @Bean method with @QuartzTransactionManager.
By default, jobs created by configuration will not overwrite already registered jobs that have been
read from a persistent job store. To enable overwriting existing job definitions set the
spring.quartz.overwrite-existing-jobs property.
In particular, an Executor bean is not associated with the scheduler as Quartz offers
a way to configure the scheduler through spring.quartz.properties. If you need to
NOTE
customize the task executor, consider implementing
SchedulerFactoryBeanCustomizer.
Jobs can define setters to inject data map properties. Regular beans can also be injected in a similar
manner, as shown in the following example:
287
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
@Override
protected void executeInternal(JobExecutionContext context) throws
JobExecutionException {
this.myService.someMethod(context.getFireTime(), this.name);
}
See the reference documentation for a detailed explanation of how you can use
TIP
JavaMailSender.
In particular, certain default timeout values are infinite, and you may want to change that to avoid
having a thread blocked by an unresponsive mail server, as shown in the following example:
288
Properties
spring.mail.properties[mail.smtp.connectiontimeout]=5000
spring.mail.properties[mail.smtp.timeout]=3000
spring.mail.properties[mail.smtp.writetimeout]=5000
Yaml
spring:
mail:
properties:
"[mail.smtp.connectiontimeout]": 5000
"[mail.smtp.timeout]": 3000
"[mail.smtp.writetimeout]": 5000
Properties
spring.mail.jndi-name=mail/Session
Yaml
spring:
mail:
jndi-name: "mail/Session"
When a jndi-name is set, it takes precedence over all other Session-related settings.
11.5. Validation
The method validation feature supported by Bean Validation 1.1 is automatically enabled as long as
a JSR-303 implementation (such as Hibernate validator) is on the classpath. This lets bean methods
be annotated with javax.validation constraints on their parameters and/or on their return value.
Target classes with such annotated methods need to be annotated with the @Validated annotation at
the type level for their methods to be searched for inline constraint annotations.
For instance, the following service triggers the validation of the first argument, making sure its size
is between 8 and 10:
289
import jakarta.validation.constraints.Size;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@Service
@Validated
public class MyBean {
The application’s MessageSource is used when resolving {parameters} in constraint messages. This
allows you to use your application’s messages.properties files for Bean Validation messages. Once
the parameters have been resolved, message interpolation is completed using Bean Validation’s
default interpolator.
11.6.1. RestTemplate
If you need to call remote REST services from your application, you can use the Spring Framework’s
RestTemplate class. Since RestTemplate instances often need to be customized before being used,
Spring Boot does not provide any single auto-configured RestTemplate bean. It does, however, auto-
configure a RestTemplateBuilder, which can be used to create RestTemplate instances when needed.
The auto-configured RestTemplateBuilder ensures that sensible HttpMessageConverters are applied to
RestTemplate instances.
290
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class MyService {
RestTemplate Customization
There are three main approaches to RestTemplate customization, depending on how broadly you
want the customizations to apply.
To make the scope of any customizations as narrow as possible, inject the auto-configured
RestTemplateBuilder and then call its methods as required. Each method call returns a new
RestTemplateBuilder instance, so the customizations only affect this use of the builder.
The following example shows a customizer that configures the use of a proxy for all hosts except
192.168.0.5:
291
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.routing.HttpRoutePlanner;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.apache.http.protocol.HttpContext;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Override
public void customize(RestTemplate restTemplate) {
HttpRoutePlanner routePlanner = new CustomRoutePlanner(new
HttpHost("proxy.example.com"));
HttpClient httpClient =
HttpClientBuilder.create().setRoutePlanner(routePlanner).build();
restTemplate.setRequestFactory(new
HttpComponentsClientHttpRequestFactory(httpClient));
}
CustomRoutePlanner(HttpHost proxy) {
super(proxy);
}
@Override
public HttpHost determineProxy(HttpHost target, HttpRequest request,
HttpContext context) throws HttpException {
if (target.getHostName().equals("192.168.0.5")) {
return null;
}
return super.determineProxy(target, request, context);
}
}
Finally, you can define your own RestTemplateBuilder bean. Doing so will replace the auto-
configured builder. If you want any RestTemplateCustomizer beans to be applied to your custom
builder, as the auto-configuration would have done, configure it using a
RestTemplateBuilderConfigurer. The following example exposes a RestTemplateBuilder that matches
what Spring Boot’s auto-configuration would have done, except that custom connect and read
292
timeouts are also specified:
import java.time.Duration;
import
org.springframework.boot.autoconfigure.web.client.RestTemplateBuilderConfigurer;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyRestTemplateBuilderConfiguration {
@Bean
public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer
configurer) {
return configurer.configure(new
RestTemplateBuilder()).setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(2));
}
The most extreme (and rarely used) option is to create your own RestTemplateBuilder bean without
using a configurer. In addition to replacing the auto-configured builder, this also prevents any
RestTemplateCustomizer beans from being used.
11.6.2. WebClient
If you have Spring WebFlux on your classpath, you can also choose to use WebClient to call remote
REST services. Compared to RestTemplate, this client has a more functional feel and is fully reactive.
You can learn more about the WebClient in the dedicated section in the Spring Framework docs.
Spring Boot creates and pre-configures a WebClient.Builder for you. It is strongly advised to inject it
in your components and use it to create WebClient instances. Spring Boot is configuring that builder
to share HTTP resources, reflect codecs setup in the same fashion as the server ones (see WebFlux
HTTP codecs auto-configuration), and more.
293
import org.neo4j.cypherdsl.core.Relationship.Details;
import reactor.core.publisher.Mono;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
@Service
public class MyService {
WebClient Runtime
Spring Boot will auto-detect which ClientHttpConnector to use to drive WebClient, depending on the
libraries available on the application classpath. For now, Reactor Netty and Jetty RS client are
supported.
Developers can override the resource configuration for Jetty and Reactor Netty by providing a
custom ReactorResourceFactory or JettyResourceFactory bean - this will be applied to both clients
and servers.
If you wish to override that choice for the client, you can define your own ClientHttpConnector bean
and have full control over the client configuration.
You can learn more about the WebClient configuration options in the Spring Framework reference
documentation.
WebClient Customization
There are three main approaches to WebClient customization, depending on how broadly you want
the customizations to apply.
294
To make the scope of any customizations as narrow as possible, inject the auto-configured
WebClient.Builder and then call its methods as required. WebClient.Builder instances are stateful:
Any change on the builder is reflected in all clients subsequently created with it. If you want to
create several clients with the same builder, you can also consider cloning the builder with
WebClient.Builder other = builder.clone();.
Finally, you can fall back to the original API and use WebClient.create(). In that case, no auto-
configuration or WebClientCustomizer is applied.
The Spring Web Services features can be easily accessed with the spring-boot-starter-webservices
module.
SimpleWsdl11Definition and SimpleXsdSchema beans can be automatically created for your WSDLs
and XSDs respectively. To do so, configure their location, as shown in the following example:
Properties
spring.webservices.wsdl-locations=classpath:/wsdl
Yaml
spring:
webservices:
wsdl-locations: "classpath:/wsdl"
If you need to call remote Web services from your application, you can use the WebServiceTemplate
class. Since WebServiceTemplate instances often need to be customized before being used, Spring
Boot does not provide any single auto-configured WebServiceTemplate bean. It does, however, auto-
configure a WebServiceTemplateBuilder, which can be used to create WebServiceTemplate instances
when needed.
295
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.client.core.SoapActionCallback;
@Service
public class MyService {
import java.time.Duration;
import org.springframework.boot.webservices.client.HttpWebServiceMessageSenderBuilder;
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.transport.WebServiceMessageSender;
@Configuration(proxyBeanMethods = false)
public class MyWebServiceTemplateConfiguration {
@Bean
public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) {
WebServiceMessageSender sender = new HttpWebServiceMessageSenderBuilder()
.setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(2))
.build();
return builder.messageSenders(sender).build();
}
296
11.8. Distributed Transactions with JTA
Spring Boot supports distributed JTA transactions across multiple XA resources by using a
transaction manager retrieved from JNDI.
If you package your Spring Boot application as a war or ear file and deploy it to a Jakarta EE
application server, you can use your application server’s built-in transaction manager. Spring Boot
tries to auto-configure a transaction manager by looking at common JNDI locations
(java:comp/UserTransaction, java:comp/TransactionManager, and so on). When using a transaction
service provided by your application server, you generally also want to ensure that all resources
are managed by the server and exposed over JNDI. Spring Boot tries to auto-configure JMS by
looking for a ConnectionFactory at the JNDI path (java:/JmsXA or java:/XAConnectionFactory), and
you can use the spring.datasource.jndi-name property to configure your DataSource.
When using JTA, the primary JMS ConnectionFactory bean is XA-aware and participates in
distributed transactions. You can inject into your bean without needing to use any @Qualifier:
In some situations, you might want to process certain JMS messages by using a non-XA
ConnectionFactory. For example, your JMS processing logic might take longer than the XA timeout.
If you want to use a non-XA ConnectionFactory, you can the nonXaJmsConnectionFactory bean:
For consistency, the jmsConnectionFactory bean is also provided by using the bean alias
xaJmsConnectionFactory:
297
public MyBean(@Qualifier("xaJmsConnectionFactory") ConnectionFactory
connectionFactory) {
// ...
}
The next few sections go into detail about deploying applications to cloud platforms. You can read
about building container images in the next section or skip to the production-ready features
section.
298
Chapter 12. Container Images
Spring Boot applications can be containerized using Dockerfiles, or by using Cloud Native
Buildpacks to create optimized docker compatible container images that you can run anywhere.
If you are running your application from a container, you can use an executable jar, but it is also
often an advantage to explode it and run it in a different way. Certain PaaS implementations may
also choose to unpack archives before they run. For example, Cloud Foundry operates this way. One
way to run an unpacked archive is by starting the appropriate launcher, as follows:
This is actually slightly faster on startup (depending on the size of the jar) than running from an
unexploded archive. At runtime you should not expect any differences.
Once you have unpacked the jar file, you can also get an extra boost to startup time by running the
app with its "natural" main method instead of the JarLauncher. For example:
Using the JarLauncher over the application’s main method has the added benefit of a
NOTE predictable classpath order. The jar contains a classpath.idx file which is used by
the JarLauncher when constructing the classpath.
To make it easier to create optimized Docker images, Spring Boot supports adding a layer index file
to the jar. It provides a list of layers and the parts of the jar that should be contained within them.
The list of layers in the index is ordered based on the order in which the layers should be added to
the Docker/OCI image. Out-of-the-box, the following layers are supported:
299
• dependencies (for regular released dependencies)
- "dependencies":
- BOOT-INF/lib/library1.jar
- BOOT-INF/lib/library2.jar
- "spring-boot-loader":
- org/springframework/boot/loader/JarLauncher.class
- org/springframework/boot/loader/jar/JarEntry.class
- "snapshot-dependencies":
- BOOT-INF/lib/library3-SNAPSHOT.jar
- "application":
- META-INF/MANIFEST.MF
- BOOT-INF/classes/a/b/C.class
This layering is designed to separate code based on how likely it is to change between application
builds. Library code is less likely to change between builds, so it is placed in its own layers to allow
tooling to re-use the layers from cache. Application code is more likely to change between builds so
it is isolated in a separate layer.
Spring Boot also supports layering for war files with the help of a layers.idx.
For Maven, see the packaging layered jar or war section for more details on adding a layer index to
the archive. For Gradle, see the packaging layered jar or war section of the Gradle plugin
documentation.
12.2. Dockerfiles
While it is possible to convert a Spring Boot fat jar into a docker image with just a few lines in the
Dockerfile, we will use the layering feature to create an optimized docker image. When you create a
jar containing the layers index file, the spring-boot-jarmode-layertools jar will be added as a
dependency to your jar. With this jar on the classpath, you can launch your application in a special
mode which allows the bootstrap code to run something entirely different from your application,
for example, something that extracts the layers.
The layertools mode can not be used with a fully executable Spring Boot
CAUTION archive that includes a launch script. Disable launch script configuration when
building a jar file that is intended to be used with layertools.
Here’s how you can launch your jar with a layertools jar mode:
300
$ java -Djarmode=layertools -jar my-app.jar
Usage:
java -Djarmode=layertools -jar my-app.jar
Available commands:
list List layers from the jar that can be extracted
extract Extracts layers from the jar for image creation
help Help about any command
The extract command can be used to easily split the application into layers to be added to the
dockerfile. Here is an example of a Dockerfile using jarmode.
FROM adoptopenjdk:11-jre-hotspot
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
Assuming the above Dockerfile is in the current directory, your docker image can be built with
docker build ., or optionally specifying the path to your application jar, as shown in the following
example:
This is a multi-stage dockerfile. The builder stage extracts the directories that are needed later. Each
of the COPY commands relates to the layers extracted by the jarmode.
Of course, a Dockerfile can be written without using the jarmode. You can use some combination of
unzip and mv to move things to the right layer but jarmode simplifies that.
301
such as Cloud Foundry or Heroku then you’ve probably used a buildpack. Buildpacks are the part of
the platform that takes your application and converts it into something that the platform can
actually run. For example, Cloud Foundry’s Java buildpack will notice that you’re pushing a .jar file
and automatically add a relevant JRE.
With Cloud Native Buildpacks, you can create Docker compatible images that you can run
anywhere. Spring Boot includes buildpack support directly for both Maven and Gradle. This means
you can just type a single command and quickly get a sensible image into your locally running
Docker daemon.
See the individual plugin documentation on how to use buildpacks with Maven and Gradle.
The Paketo Spring Boot buildpack has also been updated to support the layers.idx
NOTE file so any customization that is applied to it will be reflected in the image created
by the buildpack.
302
Chapter 13. Production-ready Features
Spring Boot includes a number of additional features to help you monitor and manage your
application when you push it to production. You can choose to manage and monitor your
application by using HTTP endpoints or with JMX. Auditing, health, and metrics gathering can also
be automatically applied to your application.
Definition of Actuator
To add the actuator to a Maven-based project, add the following ‘Starter’ dependency:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
13.2. Endpoints
Actuator endpoints let you monitor and interact with your application. Spring Boot includes a
number of built-in endpoints and lets you add your own. For example, the health endpoint provides
basic application health information.
You can enable or disable each individual endpoint and expose them (make them remotely
accessible) over HTTP or JMX. An endpoint is considered to be available when it is both enabled
and exposed. The built-in endpoints are auto-configured only when they are available. Most
applications choose exposure over HTTP, where the ID of the endpoint and a prefix of /actuator is
mapped to a URL. For example, by default, the health endpoint is mapped to /actuator/health.
303
To learn more about the Actuator’s endpoints and their request and response formats,
TIP
see the separate API documentation (HTML or PDF).
ID Description
auditevents Exposes audit events information for the current application.
Requires an AuditEventRepository bean.
beans Displays a complete list of all the Spring beans in your application.
caches Exposes available caches.
conditions Shows the conditions that were evaluated on configuration and auto-
configuration classes and the reasons why they did or did not match.
configprops Displays a collated list of all @ConfigurationProperties.
env Exposes properties from Spring’s ConfigurableEnvironment.
flyway Shows any Flyway database migrations that have been applied.
Requires one or more Flyway beans.
health Shows application health information.
httptrace Displays HTTP trace information (by default, the last 100 HTTP
request-response exchanges). Requires an HttpTraceRepository bean.
info Displays arbitrary application info.
integrationgraph Shows the Spring Integration graph. Requires a dependency on
spring-integration-core.
loggers Shows and modifies the configuration of loggers in the application.
liquibase Shows any Liquibase database migrations that have been applied.
Requires one or more Liquibase beans.
metrics Shows “metrics” information for the current application.
mappings Displays a collated list of all @RequestMapping paths.
quartz Shows information about Quartz Scheduler jobs.
scheduledtasks Displays the scheduled tasks in your application.
sessions Allows retrieval and deletion of user sessions from a Spring Session-
backed session store. Requires a servlet-based web application that
uses Spring Session.
shutdown Lets the application be gracefully shutdown. Disabled by default.
startup Shows the startup steps data collected by the ApplicationStartup.
Requires the SpringApplication to be configured with a
BufferingApplicationStartup.
threaddump Performs a thread dump.
If your application is a web application (Spring MVC or Spring WebFlux), you can use the following
304
additional endpoints:
ID Description
heapdump Returns a heap dump file. On a HotSpot JVM, an HPROF-format file is
returned. On an OpenJ9 JVM, a PHD-format file is returned.
jolokia Exposes JMX beans over HTTP when Jolokia is on the classpath (not
available for WebFlux). Requires a dependency on jolokia-core.
logfile Returns the contents of the logfile (if the logging.file.name or the
logging.file.path property has been set). Supports the use of the
HTTP Range header to retrieve part of the log file’s content.
prometheus Exposes metrics in a format that can be scraped by a Prometheus
server. Requires a dependency on micrometer-registry-prometheus.
By default, all endpoints except for shutdown are enabled. To configure the enablement of an
endpoint, use its management.endpoint.<id>.enabled property. The following example enables the
shutdown endpoint:
Properties
management.endpoint.shutdown.enabled=true
Yaml
management:
endpoint:
shutdown:
enabled: true
If you prefer endpoint enablement to be opt-in rather than opt-out, set the
management.endpoints.enabled-by-default property to false and use individual endpoint enabled
properties to opt back in. The following example enables the info endpoint and disables all other
endpoints:
Properties
management.endpoints.enabled-by-default=false
management.endpoint.info.enabled=true
305
Yaml
management:
endpoints:
enabled-by-default: false
endpoint:
info:
enabled: true
Disabled endpoints are removed entirely from the application context. If you want
NOTE to change only the technologies over which an endpoint is exposed, use the include
and exclude properties instead.
Since Endpoints may contain sensitive information, you should carefully consider when to expose
them. The following table shows the default exposure for the built-in endpoints:
ID JMX Web
auditevents Yes No
beans Yes No
caches Yes No
conditions Yes No
configprops Yes No
env Yes No
flyway Yes No
health Yes Yes
heapdump N/A No
httptrace Yes No
info Yes No
integrationgraph Yes No
jolokia N/A No
logfile N/A No
loggers Yes No
liquibase Yes No
metrics Yes No
mappings Yes No
prometheus N/A No
quartz Yes No
306
ID JMX Web
scheduledtasks Yes No
sessions Yes No
shutdown Yes No
startup Yes No
threaddump Yes No
To change which endpoints are exposed, use the following technology-specific include and exclude
properties:
Property Default
management.endpoints.jmx.exposure.exclude
management.endpoints.jmx.exposure.include *
management.endpoints.web.exposure.exclude
management.endpoints.web.exposure.include health
The include property lists the IDs of the endpoints that are exposed. The exclude property lists the
IDs of the endpoints that should not be exposed. The exclude property takes precedence over the
include property. You can configure both the include and the exclude properties with a list of
endpoint IDs.
For example, to stop exposing all endpoints over JMX and only expose the health and info
endpoints, use the following property:
Properties
management.endpoints.jmx.exposure.include=health,info
Yaml
management:
endpoints:
jmx:
exposure:
include: "health,info"
* can be used to select all endpoints. For example, to expose everything over HTTP except the env
and beans endpoints, use the following properties:
Properties
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=env,beans
307
Yaml
management:
endpoints:
web:
exposure:
include: "*"
exclude: "env,beans"
* has a special meaning in YAML, so be sure to add quotation marks if you want to
NOTE
include (or exclude) all endpoints.
If your application is exposed publicly, we strongly recommend that you also secure
NOTE
your endpoints.
If you want to implement your own strategy for when endpoints are exposed, you can
TIP
register an EndpointFilter bean.
13.2.3. Security
For security purposes, all actuators other than /health are disabled by default. You can use the
management.endpoints.web.exposure.include property to enable the actuators.
If you wish to configure custom security for HTTP endpoints (for example, to allow only users with
a certain role to access them), Spring Boot provides some convenient RequestMatcher objects that
you can use in combination with Spring Security.
A typical Spring Security configuration might look something like the following example:
308
import
org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception
{
http.requestMatcher(EndpointRequest.toAnyEndpoint())
.authorizeRequests((requests) ->
requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
http.httpBasic();
return http.build();
}
If you deploy applications behind a firewall, you may prefer that all your actuator endpoints can be
accessed without requiring authentication. You can do so by changing the
management.endpoints.web.exposure.include property, as follows:
Properties
management.endpoints.web.exposure.include=*
Yaml
management:
endpoints:
web:
exposure:
include: "*"
Additionally, if Spring Security is present, you would need to add custom security configuration that
allows unauthenticated access to the endpoints, as the following example shows:
309
import
org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception
{
http.requestMatcher(EndpointRequest.toAnyEndpoint())
.authorizeRequests((requests) -> requests.anyRequest().permitAll());
return http.build();
}
In both of the preceding examples, the configuration applies only to the actuator
endpoints. Since Spring Boot’s security configuration backs off completely in the
NOTE
presence of any SecurityFilterChain bean, you need to configure an additional
SecurityFilterChain bean with rules that apply to the rest of the application.
Since Spring Boot relies on Spring Security’s defaults, CSRF protection is turned on by default. This
means that the actuator endpoints that require a POST (shutdown and loggers endpoints), a PUT, or a
DELETE get a 403 (forbidden) error when the default security configuration is in use.
You can find additional information about CSRF protection in the Spring Security Reference Guide.
Endpoints automatically cache responses to read operations that do not take any parameters. To
configure the amount of time for which an endpoint caches a response, use its cache.time-to-live
property. The following example sets the time-to-live of the beans endpoint’s cache to 10 seconds:
Properties
management.endpoint.beans.cache.time-to-live=10s
310
Yaml
management:
endpoint:
beans:
cache:
time-to-live: "10s"
A “discovery page” is added with links to all the endpoints. The “discovery page” is available on
/actuator by default.
To disable the “discovery page”, add the following property to your application properties:
Properties
management.endpoints.web.discovery.enabled=false
Yaml
management:
endpoints:
web:
discovery:
enabled: false
When a custom management context path is configured, the “discovery page” automatically moves
from /actuator to the root of the management context. For example, if the management context
path is /management, the discovery page is available from /management. When the management
context path is set to /, the discovery page is disabled to prevent the possibility of a clash with other
mappings.
Cross-origin resource sharing (CORS) is a W3C specification that lets you specify in a flexible way
what kind of cross-domain requests are authorized. If you use Spring MVC or Spring WebFlux, you
can configure Actuator’s web endpoints to support such scenarios.
CORS support is disabled by default and is only enabled once you have set the
management.endpoints.web.cors.allowed-origins property. The following configuration permits GET
and POST calls from the example.com domain:
311
Properties
management.endpoints.web.cors.allowed-origins=https://example.com
management.endpoints.web.cors.allowed-methods=GET,POST
Yaml
management:
endpoints:
web:
cors:
allowed-origins: "https://example.com"
allowed-methods: "GET,POST"
If you add a @Bean annotated with @Endpoint, any methods annotated with @ReadOperation,
@WriteOperation, or @DeleteOperation are automatically exposed over JMX and, in a web application,
over HTTP as well. Endpoints can be exposed over HTTP by using Spring MVC, or Spring WebFlux.
The following example exposes a read operation that returns a custom object:
@ReadOperation
public CustomData getData() {
return new CustomData("test", 5);
}
You can also write technology-specific endpoints by using @JmxEndpoint or @WebEndpoint. These
endpoints are restricted to their respective technologies. For example, @WebEndpoint is exposed only
over HTTP and not over JMX.
Finally, if you need access to web-framework-specific functionality, you can implement servlet or
Spring @Controller and @RestController endpoints at the cost of them not being available over JMX
or when using a different web framework.
Receiving Input
Operations on an endpoint receive input through their parameters. When exposed over the web,
the values for these parameters are taken from the URL’s query parameters and from the JSON
request body. When exposed over JMX, the parameters are mapped to the parameters of the
MBean’s operations. Parameters are required by default. They can be made optional by annotating
312
them with either @javax.annotation.Nullable or @org.springframework.lang.Nullable.
You can map each root property in the JSON request body to a parameter of the endpoint. Consider
the following JSON request body:
{
"name": "test",
"counter": 42
}
You can use this to invoke a write operation that takes String name and int counter parameters, as
the following example shows:
@WriteOperation
public void updateData(String name, int counter) {
// injects "test" and 42
}
Because endpoints are technology agnostic, only simple types can be specified in the
TIP method signature. In particular, declaring a single parameter with a CustomData type
that defines a name and counter properties is not supported.
To let the input be mapped to the operation method’s parameters, Java code that
implements an endpoint should be compiled with -parameters, and Kotlin code that
NOTE implements an endpoint should be compiled with -java-parameters. This will
happen automatically if you use Spring Boot’s Gradle plugin or if you use Maven
and spring-boot-starter-parent.
The parameters passed to endpoint operation methods are, if necessary, automatically converted to
the required type. Before calling an operation method, the input received over JMX or HTTP is
converted to the required types by using an instance of ApplicationConversionService as well as any
Converter or GenericConverter beans qualified with @EndpointConverter.
Path
The path of the predicate is determined by the ID of the endpoint and the base path of the web-
exposed endpoints. The default base path is /actuator. For example, an endpoint with an ID of
313
sessions uses /actuator/sessions as its path in the predicate.
You can further customize the path by annotating one or more parameters of the operation method
with @Selector. Such a parameter is added to the path predicate as a path variable. The variable’s
value is passed into the operation method when the endpoint operation is invoked. If you want to
capture all remaining path elements, you can add @Selector(Match=ALL_REMAINING) to the last
parameter and make it a type that is conversion-compatible with a String[].
HTTP method
The HTTP method of the predicate is determined by the operation type, as shown in the following
table:
Consumes
For a @WriteOperation (HTTP POST) that uses the request body, the consumes clause of the predicate is
application/vnd.spring-boot.actuator.v2+json, application/json. For all other operations, the
consumes clause is empty.
Produces
The produces clause of the predicate can be determined by the produces attribute of the
@DeleteOperation, @ReadOperation, and @WriteOperation annotations. The attribute is optional. If it is
not used, the produces clause is determined automatically.
If the operation method returns void or Void, the produces clause is empty. If the operation method
returns a org.springframework.core.io.Resource, the produces clause is application/octet-stream.
For all other operations, the produces clause is application/vnd.spring-boot.actuator.v2+json,
application/json.
The default response status for an endpoint operation depends on the operation type (read, write,
or delete) and what, if anything, the operation returns.
If a @ReadOperation returns a value, the response status will be 200 (OK). If it does not return a
value, the response status will be 404 (Not Found).
If a @WriteOperation or @DeleteOperation returns a value, the response status will be 200 (OK). If it
does not return a value, the response status will be 204 (No Content).
314
Web Endpoint Range Requests
You can use an HTTP range request to request part of an HTTP resource. Operations that return a
org.springframework.core.io.Resource automatically support range requests.
An operation on a web endpoint or a web-specific endpoint extension can receive the current
java.security.Principal or org.springframework.boot.actuate.endpoint.SecurityContext as a
method parameter. The former is typically used in conjunction with @Nullable to provide different
behavior for authenticated and unauthenticated users. The latter is typically used to perform
authorization checks by using its isUserInRole(String) method.
Servlet Endpoints
Controller Endpoints
You can use health information to check the status of your running application. It is often used by
monitoring software to alert someone when a production system goes down. The information
exposed by the health endpoint depends on the management.endpoint.health.show-details and
management.endpoint.health.show-components properties, which can be configured with one of the
following values:
Name Description
never Details are never shown.
when-authorized Details are shown only to authorized users. Authorized roles can be
configured by using management.endpoint.health.roles.
always Details are shown to all users.
The default value is never. A user is considered to be authorized when they are in one or more of
the endpoint’s roles. If the endpoint has no configured roles (the default), all authenticated users
are considered to be authorized. You can configure the roles by using the
management.endpoint.health.roles property.
315
If you have secured your application and wish to use always, your security
NOTE configuration must permit access to the health endpoint for both authenticated and
unauthenticated users.
Health information is collected from the content of a HealthContributorRegistry (by default, all
HealthContributor instances defined in your ApplicationContext). Spring Boot includes a number of
auto-configured HealthContributors, and you can also write your own.
By default, the final system health is derived by a StatusAggregator, which sorts the statuses from
each HealthIndicator based on an ordered list of statuses. The first status in the sorted list is used as
the overall health status. If no HealthIndicator returns a status that is known to the
StatusAggregator, an UNKNOWN status is used.
You can use the HealthContributorRegistry to register and unregister health indicators
TIP
at runtime.
Auto-configured HealthIndicators
When appropriate, Spring Boot auto-configures the HealthIndicators listed in the following table.
You can also enable or disable selected indicators by configuring management.health.key.enabled,
with the key listed in the following table:
316
Key Name Description
rabbit RabbitHealthIndicator Checks that a Rabbit server is up.
redis RedisHealthIndicator Checks that a Redis server is up.
solr SolrHealthIndicator Checks that a Solr server is up.
TIP You can disable them all by setting the management.health.defaults.enabled property.
To provide custom health information, you can register Spring beans that implement the
HealthIndicator interface. You need to provide an implementation of the health() method and
return a Health response. The Health response should include a status and can optionally include
additional details to be displayed. The following code shows a sample HealthIndicator
implementation:
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCode = check();
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
317
The identifier for a given HealthIndicator is the name of the bean without the
NOTE HealthIndicator suffix, if it exists. In the preceding example, the health information
is available in an entry named my.
In addition to Spring Boot’s predefined Status types, Health can return a custom Status that
represents a new system state. In such cases, you also need to provide a custom implementation of
the StatusAggregator interface, or you must configure the default implementation by using the
management.endpoint.health.status.order configuration property.
For example, assume a new Status with a code of FATAL is being used in one of your HealthIndicator
implementations. To configure the severity order, add the following property to your application
properties:
Properties
management.endpoint.health.status.order=fatal,down,out-of-service,unknown,up
Yaml
management:
endpoint:
health:
status:
order: "fatal,down,out-of-service,unknown,up"
The HTTP status code in the response reflects the overall health status. By default, OUT_OF_SERVICE
and DOWN map to 503. Any unmapped health statuses, including UP, map to 200. You might also want
to register custom status mappings if you access the health endpoint over HTTP. Configuring a
custom mapping disables the defaults mappings for DOWN and OUT_OF_SERVICE. If you want to retain
the default mappings, you must explicitly configure them, alongside any custom mappings. For
example, the following property maps FATAL to 503 (service unavailable) and retains the default
mappings for DOWN and OUT_OF_SERVICE:
Properties
management.endpoint.health.status.http-mapping.down=503
management.endpoint.health.status.http-mapping.fatal=503
management.endpoint.health.status.http-mapping.out-of-service=503
318
Yaml
management:
endpoint:
health:
status:
http-mapping:
down: 503
fatal: 503
out-of-service: 503
TIP If you need more control, you can define your own HttpCodeStatusMapper bean.
The following table shows the default status mappings for the built-in statuses:
Status Mapping
DOWN SERVICE_UNAVAILABLE (503)
OUT_OF_SERVICE SERVICE_UNAVAILABLE (503)
UP No mapping by default, so HTTP status is 200
UNKNOWN No mapping by default, so HTTP status is 200
For reactive applications, such as those that use Spring WebFlux, ReactiveHealthContributor
provides a non-blocking contract for getting application health. Similar to a traditional
HealthContributor, health information is collected from the content of a
ReactiveHealthContributorRegistry (by default, all HealthContributor and ReactiveHealthContributor
instances defined in your ApplicationContext). Regular HealthContributors that do not check against
a reactive API are executed on the elastic scheduler.
To provide custom health information from a reactive API, you can register Spring beans that
implement the ReactiveHealthIndicator interface. The following code shows a sample
ReactiveHealthIndicator implementation:
319
import reactor.core.publisher.Mono;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyReactiveHealthIndicator implements ReactiveHealthIndicator {
@Override
public Mono<Health> health() {
return doHealthCheck().onErrorResume((exception) ->
Mono.just(new Health.Builder().down(exception).build()));
}
Auto-configured ReactiveHealthIndicators
If necessary, reactive indicators replace the regular ones. Also, any HealthIndicator
TIP
that is not handled explicitly is wrapped automatically.
Health Groups
It is sometimes useful to organize health indicators into groups that you can use for different
320
purposes.
Properties
management.endpoint.health.group.custom.include=db
Yaml
management:
endpoint:
health:
group:
custom:
include: "db"
Similarly, to create a group that excludes the database indicators from the group and includes all
the other indicators, you can define the following:
Properties
management.endpoint.health.group.custom.exclude=db
Yaml
management:
endpoint:
health:
group:
custom:
exclude: "db"
By default, groups inherit the same StatusAggregator and HttpCodeStatusMapper settings as the
system health. However, you can also define these on a per-group basis. You can also override the
show-details and roles properties if required:
Properties
management.endpoint.health.group.custom.show-details=when-authorized
management.endpoint.health.group.custom.roles=admin
management.endpoint.health.group.custom.status.order=fatal,up
management.endpoint.health.group.custom.status.http-mapping.fatal=500
management.endpoint.health.group.custom.status.http-mapping.out-of-service=500
321
Yaml
management:
endpoint:
health:
group:
custom:
show-details: "when-authorized"
roles: "admin"
status:
order: "fatal,up"
http-mapping:
fatal: 500
out-of-service: 500
A health group can also include/exclude a CompositeHealthContributor. You can also include/exclude
only a certain component of a CompositeHealthContributor. This can be done using the fully
qualified name of the component as follows:
management.endpoint.health.group.custom.include="test/primary"
management.endpoint.health.group.custom.exclude="test/primary/b"
In the example above, the custom group will include the HealthContributor with the name primary
which is a component of the composite test. Here, primary itself is a composite and the
HealthContributor with the name b will be excluded from the custom group.
Health groups can be made available at an additional path on either the main or management port.
This is useful in cloud environments such as Kubernetes, where it is quite common to use a
separate management port for the actuator endpoints for security purposes. Having a separate port
could lead to unreliable health checks because the main application might not work properly even
if the health check is successful. The health group can be configured with an additional path as
follows:
management.endpoint.health.group.live.additional-path="server:/healthz"
This would make the live health group available on the main server port at /healthz. The prefix is
mandatory and must be either server: (represents the main server port) or management: (represents
the management port, if configured.) The path must be a single path segment.
DataSource Health
The DataSource health indicator shows the health of both standard data sources and routing data
source beans. The health of a routing data source includes the health of each of its target data
sources. In the health endpoint’s response, each of a routing data source’s targets is named by using
322
its routing key. If you prefer not to include routing data sources in the indicator’s output, set
management.health.db.ignore-routing-data-sources to true.
Applications deployed on Kubernetes can provide information about their internal state with
Container Probes. Depending on your Kubernetes configuration, the kubelet calls those probes and
reacts to the result.
By default, Spring Boot manages your Application Availability State. If deployed in a Kubernetes
environment, actuator gathers the “Liveness” and “Readiness” information from the
ApplicationAvailability interface and uses that information in dedicated health indicators:
LivenessStateHealthIndicator and ReadinessStateHealthIndicator. These indicators are shown on
the global health endpoint ("/actuator/health"). They are also exposed as separate HTTP Probes by
using health groups: "/actuator/health/liveness" and "/actuator/health/readiness".
You can then configure your Kubernetes infrastructure with the following endpoint information:
livenessProbe:
httpGet:
path: "/actuator/health/liveness"
port: <actuator-port>
failureThreshold: ...
periodSeconds: ...
readinessProbe:
httpGet:
path: "/actuator/health/readiness"
port: <actuator-port>
failureThreshold: ...
periodSeconds: ...
<actuator-port> should be set to the port that the actuator endpoints are available
NOTE on. It could be the main web server port or a separate management port if the
"management.server.port" property has been set.
These health groups are automatically enabled only if the application runs in a Kubernetes
environment. You can enable them in any environment by using the
management.endpoint.health.probes.enabled configuration property.
If your Actuator endpoints are deployed on a separate management context, the endpoints do not
use the same web infrastructure (port, connection pools, framework components) as the main
323
application. In this case, a probe check could be successful even if the main application does not
work properly (for example, it cannot accept new connections). For this reason, is it a good idea to
make the liveness and readiness health groups available on the main server port. This can be done
by setting the following property:
management.endpoint.health.probes.add-additional-paths=true
This would make liveness available at /livez and readiness at readyz on the main server port.
Actuator configures the “liveness” and “readiness” probes as Health Groups. This means that all the
health groups features are available for them. You can, for example, configure additional Health
Indicators:
Properties
management.endpoint.health.group.readiness.include=readinessState,customCheck
Yaml
management:
endpoint:
health:
group:
readiness:
include: "readinessState,customCheck"
By default, Spring Boot does not add other health indicators to these groups.
The “liveness” probe should not depend on health checks for external systems. If the liveness state
of an application is broken, Kubernetes tries to solve that problem by restarting the application
instance. This means that if an external system (such as a database, a Web API, or an external
cache) fails, Kubernetes might restart all application instances and create cascading failures.
As for the “readiness” probe, the choice of checking external systems must be made carefully by the
application developers. For this reason, Spring Boot does not include any additional health checks
in the readiness probe. If the readiness state of an application instance is unready, Kubernetes does
not route traffic to that instance. Some external systems might not be shared by application
instances, in which case they could be included in a readiness probe. Other external systems might
not be essential to the application (the application could have circuit breakers and fallbacks), in
which case they definitely should not be included. Unfortunately, an external system that is shared
by all application instances is common, and you have to make a judgement call: Include it in the
readiness probe and expect that the application is taken out of service when the external service is
down or leave it out and deal with failures higher up the stack, perhaps by using a circuit breaker
in the caller.
324
If all instances of an application are unready, a Kubernetes Service with
type=ClusterIP or NodePort does not accept any incoming connections. There is no
HTTP error response (503 and so on), since there is no connection. A service with
type=LoadBalancer might or might not accept connections, depending on the
NOTE
provider. A service that has an explicit ingress also responds in a way that depends
on the implementation — the ingress service itself has to decide how to handle the
“connection refused” from downstream. HTTP 503 is quite likely in the case of both
load balancer and ingress.
Also, if an application uses Kubernetes autoscaling, it may react differently to applications being
taken out of the load-balancer, depending on its autoscaler configuration.
An important aspect of the Kubernetes Probes support is its consistency with the application
lifecycle. There is a significant difference between the AvailabilityState (which is the in-memory,
internal state of the application) and the actual probe (which exposes that state). Depending on the
phase of application lifecycle, the probe might not be available.
Spring Boot publishes application events during startup and shutdown, and probes can listen to
such events and expose the AvailabilityState information.
The following tables show the AvailabilityState and the state of HTTP connectors at different
stages.
Ready CORRECT ACCEPTING_TR Accepts requests Startup tasks are finished. The
AFFIC application is receiving traffic.
325
Shutdown Liveness Readiness HTTP server Notes
phase State State
Shutdown N/A N/A Server is shut down The application context is closed
complete and the application is shut down.
See Kubernetes container lifecycle section for more information about Kubernetes
TIP
deployment.
Application information exposes various information collected from all InfoContributor beans
defined in your ApplicationContext. Spring Boot includes a number of auto-configured
InfoContributor beans, and you can write your own.
Auto-configured InfoContributors
With no prerequisites to indicate that they should be enabled, the env, java, and os contributors are
disabled by default. Each can be enabled by setting its management.info.<id>.enabled property to
true.
The build and git info contributors are enabled by default. Each can be disabled by setting its
management.info.<id>.enabled property to false. Alternatively, to disable every contributor that is
usually enabled by default, set the management.info.defaults.enabled property to false.
When the env contributor is enabled, you can customize the data exposed by the info endpoint by
setting info.* Spring properties. All Environment properties under the info key are automatically
exposed. For example, you could add the following settings to your application.properties file:
326
Properties
info.app.encoding=UTF-8
info.app.java.source=11
info.app.java.target=11
Yaml
info:
app:
encoding: "UTF-8"
java:
source: "11"
target: "11"
Rather than hardcoding those values, you could also expand info properties at build
time.
Assuming you use Maven, you could rewrite the preceding example as follows:
Properties
info.app.encoding=@project.build.sourceEncoding@
info.app.java.source=@java.version@
info.app.java.target=@java.version@
TIP
Yaml
info:
app:
encoding: "@project.build.sourceEncoding@"
java:
source: "@java.version@"
target: "@java.version@"
Another useful feature of the info endpoint is its ability to publish information about the state of
your git source code repository when the project was built. If a GitProperties bean is available, you
can use the info endpoint to expose these properties.
327
content of git.properties), use the management.info.git.mode property, as follows:
Properties
management.info.git.mode=full
Yaml
management:
info:
git:
mode: "full"
To disable the git commit information from the info endpoint completely, set the
management.info.git.enabled property to false, as follows:
Properties
management.info.git.enabled=false
Yaml
management:
info:
git:
enabled: false
Build Information
If a BuildProperties bean is available, the info endpoint can also publish information about your
build. This happens if a META-INF/build-info.properties file is available in the classpath.
The Maven and Gradle plugins can both generate that file. See "how to generate build
TIP
information" for more details.
Java Information
The info endpoint publishes information about your Java runtime environment, see JavaInfo for
more details.
OS Information
The info endpoint publishes information about your Operating System, see OsInfo for more details.
To provide custom application information, you can register Spring beans that implement the
InfoContributor interface.
328
The following example contributes an example entry with a single value:
import java.util.Collections;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
@Component
public class MyInfoContributor implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("example", Collections.singletonMap("key", "value"));
}
If you reach the info endpoint, you should see a response that contains the following additional
entry:
{
"example": {
"key" : "value"
}
}
TIP Actuator is supported natively with Spring MVC and Spring WebFlux.
Sometimes, it is useful to customize the prefix for the management endpoints. For example, your
application might already use /actuator for another purpose. You can use the
management.endpoints.web.base-path property to change the prefix for your management endpoint,
as the following example shows:
329
Properties
management.endpoints.web.base-path=/manage
Yaml
management:
endpoints:
web:
base-path: "/manage"
Unless the management port has been configured to expose endpoints by using a
different HTTP port, management.endpoints.web.base-path is relative to
NOTE server.servlet.context-path (for servlet web applications) or spring.webflux.base-
path (for reactive web applications). If management.server.port is configured,
management.endpoints.web.base-path is relative to management.server.base-path.
If you want to map endpoints to a different path, you can use the management.endpoints.web.path-
mapping property.
Properties
management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=healthcheck
Yaml
management:
endpoints:
web:
base-path: "/"
path-mapping:
health: "healthcheck"
Exposing management endpoints by using the default HTTP port is a sensible choice for cloud-
based deployments. If, however, your application runs inside your own data center, you may prefer
to expose endpoints by using a different HTTP port.
You can set the management.server.port property to change the HTTP port, as the following example
shows:
330
Properties
management.server.port=8081
Yaml
management:
server:
port: 8081
On Cloud Foundry, by default, applications receive requests only on port 8080 for
both HTTP and TCP routing. If you want to use a custom management port on Cloud
NOTE
Foundry, you need to explicitly set up the application’s routes to forward traffic to
the custom port.
When configured to use a custom port, you can also configure the management server with its own
SSL by using the various management.server.ssl.* properties. For example, doing so lets a
management server be available over HTTP while the main application uses HTTPS, as the
following property settings show:
Properties
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:store.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=false
Yaml
server:
port: 8443
ssl:
enabled: true
key-store: "classpath:store.jks"
key-password: "secret"
management:
server:
port: 8080
ssl:
enabled: false
Alternatively, both the main server and the management server can use SSL but with different key
stores, as follows:
331
Properties
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:main.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=true
management.server.ssl.key-store=classpath:management.jks
management.server.ssl.key-password=secret
Yaml
server:
port: 8443
ssl:
enabled: true
key-store: "classpath:main.jks"
key-password: "secret"
management:
server:
port: 8080
ssl:
enabled: true
key-store: "classpath:management.jks"
key-password: "secret"
You can customize the address on which the management endpoints are available by setting the
management.server.address property. Doing so can be useful if you want to listen only on an internal
or ops-facing network or to listen only for connections from localhost.
You can listen on a different address only when the port differs from the main
NOTE
server port.
The following example application.properties does not allow remote management connections:
Properties
management.server.port=8081
management.server.address=127.0.0.1
332
Yaml
management:
server:
port: 8081
address: "127.0.0.1"
If you do not want to expose endpoints over HTTP, you can set the management port to -1, as the
following example shows:
Properties
management.server.port=-1
Yaml
management:
server:
port: -1
You can also achieve this by using the management.endpoints.web.exposure.exclude property, as the
following example shows:
Properties
management.endpoints.web.exposure.exclude=*
Yaml
management:
endpoints:
web:
exposure:
exclude: "*"
If your platform provides a standard MBeanServer, Spring Boot uses that and defaults to the VM
MBeanServer, if necessary. If all that fails, a new MBeanServer is created.
333
See the JmxAutoConfiguration class for more details.
By default, Spring Boot also exposes management endpoints as JMX MBeans under the
org.springframework.boot domain. To take full control over endpoint registration in the JMX
domain, consider registering your own EndpointObjectNameFactory implementation.
The name of the MBean is usually generated from the id of the endpoint. For example, the health
endpoint is exposed as org.springframework.boot:type=Endpoint,name=Health.
If your application contains more than one Spring ApplicationContext, you may find that names
clash. To solve this problem, you can set the spring.jmx.unique-names property to true so that MBean
names are always unique.
You can also customize the JMX domain under which endpoints are exposed. The following settings
show an example of doing so in application.properties:
Properties
spring.jmx.unique-names=true
management.endpoints.jmx.domain=com.example.myapp
Yaml
spring:
jmx:
unique-names: true
management:
endpoints:
jmx:
domain: "com.example.myapp"
If you do not want to expose endpoints over JMX, you can set the
management.endpoints.jmx.exposure.exclude property to *, as the following example shows:
Properties
management.endpoints.jmx.exposure.exclude=*
334
Yaml
management:
endpoints:
jmx:
exposure:
exclude: "*"
13.5. Loggers
Spring Boot Actuator includes the ability to view and configure the log levels of your application at
runtime. You can view either the entire list or an individual logger’s configuration, which is made
up of both the explicitly configured logging level as well as the effective logging level given to it by
the logging framework. These levels can be one of:
• TRACE
• DEBUG
• INFO
• WARN
• ERROR
• FATAL
• OFF
• null
To configure a given logger, POST a partial entity to the resource’s URI, as the following example
shows:
{
"configuredLevel": "DEBUG"
}
To “reset” the specific level of the logger (and use the default configuration instead),
TIP
you can pass a value of null as the configuredLevel.
13.6. Metrics
Spring Boot Actuator provides dependency management and auto-configuration for Micrometer, an
application metrics facade that supports numerous monitoring systems, including:
• AppOptics
335
• Atlas
• Datadog
• Dynatrace
• Elastic
• Ganglia
• Graphite
• Humio
• Influx
• JMX
• KairosDB
• New Relic
• Prometheus
• SignalFx
• Simple (in-memory)
• Stackdriver
• StatsD
• Wavefront
Spring Boot auto-configures a composite MeterRegistry and adds a registry to the composite for
each of the supported implementations that it finds on the classpath. Having a dependency on
micrometer-registry-{system} in your runtime classpath is enough for Spring Boot to configure the
registry.
Most registries share common features. For instance, you can disable a particular registry even if
the Micrometer registry implementation is on the classpath. The following example disables
Datadog:
Properties
management.metrics.export.datadog.enabled=false
336
Yaml
management:
metrics:
export:
datadog:
enabled: false
You can also disable all registries unless stated otherwise by the registry-specific property, as the
following example shows:
Properties
management.metrics.export.defaults.enabled=false
Yaml
management:
metrics:
export:
defaults:
enabled: false
Spring Boot also adds any auto-configured registries to the global static composite registry on the
Metrics class, unless you explicitly tell it not to:
Properties
management.metrics.use-global-registry=false
Yaml
management:
metrics:
use-global-registry: false
You can register any number of MeterRegistryCustomizer beans to further configure the registry,
such as applying common tags, before any meters are registered with the registry:
337
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyMeterRegistryConfiguration {
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return (registry) -> registry.config().commonTags("region", "us-east-1");
}
You can apply customizations to particular registry implementations by being more specific about
the generic type:
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.graphite.GraphiteMeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyMeterRegistryConfiguration {
@Bean
public MeterRegistryCustomizer<GraphiteMeterRegistry>
graphiteMetricsNamingConvention() {
return (registry) -> registry.config().namingConvention(this::name);
}
Spring Boot also configures built-in instrumentation that you can control through configuration or
dedicated annotation markers.
338
AppOptics
Properties
management.metrics.export.appoptics.api-token=YOUR_TOKEN
Yaml
management:
metrics:
export:
appoptics:
api-token: "YOUR_TOKEN"
Atlas
By default, metrics are exported to Atlas running on your local machine. You can provide the
location of the Atlas server:
Properties
management.metrics.export.atlas.uri=https://atlas.example.com:7101/api/v1/publish
Yaml
management:
metrics:
export:
atlas:
uri: "https://atlas.example.com:7101/api/v1/publish"
Datadog
A Datadog registry periodically pushes metrics to datadoghq. To export metrics to Datadog, you
must provide your API key:
Properties
management.metrics.export.datadog.api-key=YOUR_KEY
339
Yaml
management:
metrics:
export:
datadog:
api-key: "YOUR_KEY"
You can also change the interval at which metrics are sent to Datadog:
Properties
management.metrics.export.datadog.step=30s
Yaml
management:
metrics:
export:
datadog:
step: "30s"
Dynatrace
Dynatrace offers two metrics ingest APIs, both of which are implemented for Micrometer.
Configuration properties in the v1 namespace apply only when exporting to the Timeseries v1 API.
Configuration properties in the v2 namespace apply only when exporting to the Metrics v2 API.
Note that this integration can export only to either the v1 or v2 version of the API at a time. If the
device-id (required for v1 but not used in v2) is set in the v1 namespace, metrics are exported to the
v1 endpoint. Otherwise, v2 is assumed.
v2 API
If a local OneAgent is running on the host, metrics are automatically exported to the local OneAgent
ingest endpoint. The ingest endpoint forwards the metrics to the Dynatrace backend. This is the
default behavior and requires no special setup beyond a dependency on io.micrometer:micrometer-
registry-dynatrace.
If no local OneAgent is running, the endpoint of the Metrics v2 API and an API token are required.
The API token must have the “Ingest metrics” (metrics.ingest) permission set. We recommend
limiting the scope of the token to this one permission. You must ensure that the endpoint URI
contains the path (for example, /api/v2/metrics/ingest):
The URL of the Metrics API v2 ingest endpoint is different according to your deployment option:
• SaaS: https://{your-environment-id}.live.dynatrace.com/api/v2/metrics/ingest
340
The example below configures metrics export using the example environment id:
Properties
management.metrics.export.dynatrace.uri=https://example.live.dynatrace.com/api/v2/metr
ics/ingest
management.metrics.export.dynatrace.api-token=YOUR_TOKEN
Yaml
management:
metrics:
export:
dynatrace:
uri: "https://example.live.dynatrace.com/api/v2/metrics/ingest"
api-token: "YOUR_TOKEN"
When using the Dynatrace v2 API, the following optional features are available:
• Metric key prefix: Sets a prefix that is prepended to all exported metric keys.
• Default dimensions: Specify key-value pairs that are added to all exported metrics. If tags with
the same key are specified with Micrometer, they overwrite the default dimensions.
It is possible to not specify a URI and API token, as shown in the following example. In this scenario,
the local OneAgent endpoint is used:
Properties
management.metrics.export.dynatrace.v2.metric-key-prefix=your.key.prefix
management.metrics.export.dynatrace.v2.enrich-with-dynatrace-metadata=true
management.metrics.export.dynatrace.v2.default-dimensions.key1=value1
management.metrics.export.dynatrace.v2.default-dimensions.key2=value2
Yaml
management:
metrics:
export:
dynatrace:
# Specify uri and api-token here if not using the local OneAgent endpoint.
v2:
metric-key-prefix: "your.key.prefix"
enrich-with-dynatrace-metadata: true
default-dimensions:
key1: "value1"
key2: "value2"
341
v1 API (Legacy)
The Dynatrace v1 API metrics registry pushes metrics to the configured URI periodically by using
the Timeseries v1 API. For backwards-compatibility with existing setups, when device-id is set
(required for v1, but not used in v2), metrics are exported to the Timeseries v1 endpoint. To export
metrics to Dynatrace, your API token, device ID, and URI must be provided:
Properties
management.metrics.export.dynatrace.uri=https://{your-environment-
id}.live.dynatrace.com
management.metrics.export.dynatrace.api-token=YOUR_TOKEN
management.metrics.export.dynatrace.v1.device-id=YOUR_DEVICE_ID
Yaml
management:
metrics:
export:
dynatrace:
uri: "https://{your-environment-id}.live.dynatrace.com"
api-token: "YOUR_TOKEN"
v1:
device-id: "YOUR_DEVICE_ID"
For the v1 API, you must specify the base environment URI without a path, as the v1 endpoint path
is added automatically.
Version-independent Settings
In addition to the API endpoint and token, you can also change the interval at which metrics are
sent to Dynatrace. The default export interval is 60s. The following example sets the export interval
to 30 seconds:
Properties
management.metrics.export.dynatrace.step=30s
Yaml
management:
metrics:
export:
dynatrace:
step: "30s"
You can find more information on how to set up the Dynatrace exporter for Micrometer in the
Micrometer documentation.
342
Elastic
By default, metrics are exported to Elastic running on your local machine. You can provide the
location of the Elastic server to use by using the following property:
Properties
management.metrics.export.elastic.host=https://elastic.example.com:8086
Yaml
management:
metrics:
export:
elastic:
host: "https://elastic.example.com:8086"
Ganglia
By default, metrics are exported to Ganglia running on your local machine. You can provide the
Ganglia server host and port, as the following example shows:
Properties
management.metrics.export.ganglia.host=ganglia.example.com
management.metrics.export.ganglia.port=9649
Yaml
management:
metrics:
export:
ganglia:
host: "ganglia.example.com"
port: 9649
Graphite
By default, metrics are exported to Graphite running on your local machine. You can provide the
Graphite server host and port, as the following example shows:
Properties
management.metrics.export.graphite.host=graphite.example.com
management.metrics.export.graphite.port=9004
343
Yaml
management:
metrics:
export:
graphite:
host: "graphite.example.com"
port: 9004
To take control over this behavior, define your GraphiteMeterRegistry and supply your
own HierarchicalNameMapper. An auto-configured GraphiteConfig and Clock beans are
provided unless you define your own:
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.core.instrument.util.HierarchicalNameMapper;
import io.micrometer.graphite.GraphiteConfig;
import io.micrometer.graphite.GraphiteMeterRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
TIP
public class MyGraphiteConfiguration {
@Bean
public GraphiteMeterRegistry graphiteMeterRegistry(GraphiteConfig
config, Clock clock) {
return new GraphiteMeterRegistry(config, clock,
this::toHierarchicalName);
}
Humio
By default, the Humio registry periodically pushes metrics to cloud.humio.com. To export metrics to
SaaS Humio, you must provide your API token:
344
Properties
management.metrics.export.humio.api-token=YOUR_TOKEN
Yaml
management:
metrics:
export:
humio:
api-token: "YOUR_TOKEN"
You should also configure one or more tags to identify the data source to which metrics are pushed:
Properties
management.metrics.export.humio.tags.alpha=a
management.metrics.export.humio.tags.bravo=b
Yaml
management:
metrics:
export:
humio:
tags:
alpha: "a"
bravo: "b"
Influx
By default, metrics are exported to an Influx v1 instance running on your local machine with the
default configuration. To export metrics to InfluxDB v2, configure the org, bucket, and
authentication token for writing metrics. You can provide the location of the Influx server to use by
using:
Properties
management.metrics.export.influx.uri=https://influx.example.com:8086
Yaml
management:
metrics:
export:
influx:
uri: "https://influx.example.com:8086"
345
JMX
Micrometer provides a hierarchical mapping to JMX, primarily as a cheap and portable way to view
metrics locally. By default, metrics are exported to the metrics JMX domain. You can provide the
domain to use by using:
Properties
management.metrics.export.jmx.domain=com.example.app.metrics
Yaml
management:
metrics:
export:
jmx:
domain: "com.example.app.metrics"
346
To take control over this behavior, define your JmxMeterRegistry and supply your own
HierarchicalNameMapper. An auto-configured JmxConfig and Clock beans are provided
unless you define your own:
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.core.instrument.util.HierarchicalNameMapper;
import io.micrometer.jmx.JmxConfig;
import io.micrometer.jmx.JmxMeterRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
TIP
public class MyJmxConfiguration {
@Bean
public JmxMeterRegistry jmxMeterRegistry(JmxConfig config, Clock
clock) {
return new JmxMeterRegistry(config, clock,
this::toHierarchicalName);
}
KairosDB
By default, metrics are exported to KairosDB running on your local machine. You can provide the
location of the KairosDB server to use by using:
Properties
management.metrics.export.kairos.uri=https://kairosdb.example.com:8080/api/v1/datapoin
ts
Yaml
management:
metrics:
export:
kairos:
uri: "https://kairosdb.example.com:8080/api/v1/datapoints"
347
New Relic
A New Relic registry periodically pushes metrics to New Relic. To export metrics to New Relic, you
must provide your API key and account ID:
Properties
management.metrics.export.newrelic.api-key=YOUR_KEY
management.metrics.export.newrelic.account-id=YOUR_ACCOUNT_ID
Yaml
management:
metrics:
export:
newrelic:
api-key: "YOUR_KEY"
account-id: "YOUR_ACCOUNT_ID"
You can also change the interval at which metrics are sent to New Relic:
Properties
management.metrics.export.newrelic.step=30s
Yaml
management:
metrics:
export:
newrelic:
step: "30s"
By default, metrics are published through REST calls, but you can also use the Java Agent API if you
have it on the classpath:
Properties
management.metrics.export.newrelic.client-provider-type=insights-agent
Yaml
management:
metrics:
export:
newrelic:
client-provider-type: "insights-agent"
348
Finally, you can take full control by defining your own NewRelicClientProvider bean.
Prometheus
Prometheus expects to scrape or poll individual application instances for metrics. Spring Boot
provides an actuator endpoint at /actuator/prometheus to present a Prometheus scrape with the
appropriate format.
By default, the endpoint is not available and must be exposed. See exposing endpoints
TIP
for more details.
scrape_configs:
- job_name: "spring"
metrics_path: "/actuator/prometheus"
static_configs:
- targets: ["HOST:PORT"]
For ephemeral or batch jobs that may not exist long enough to be scraped, you can use Prometheus
Pushgateway support to expose the metrics to Prometheus. To enable Prometheus Pushgateway
support, add the following dependency to your project:
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_pushgateway</artifactId>
</dependency>
When the Prometheus Pushgateway dependency is present on the classpath and the
management.metrics.export.prometheus.pushgateway.enabled property is set to true, a
PrometheusPushGatewayManager bean is auto-configured. This manages the pushing of metrics to a
Prometheus Pushgateway.
SignalFx
SignalFx registry periodically pushes metrics to SignalFx. To export metrics to SignalFx, you must
provide your access token:
Properties
management.metrics.export.signalfx.access-token=YOUR_ACCESS_TOKEN
349
Yaml
management:
metrics:
export:
signalfx:
access-token: "YOUR_ACCESS_TOKEN"
You can also change the interval at which metrics are sent to SignalFx:
Properties
management.metrics.export.signalfx.step=30s
Yaml
management:
metrics:
export:
signalfx:
step: "30s"
Simple
Micrometer ships with a simple, in-memory backend that is automatically used as a fallback if no
other registry is configured. This lets you see what metrics are collected in the metrics endpoint.
The in-memory backend disables itself as soon as you use any other available backend. You can also
disable it explicitly:
Properties
management.metrics.export.simple.enabled=false
Yaml
management:
metrics:
export:
simple:
enabled: false
Stackdriver
The Stackdriver registry periodically pushes metrics to Stackdriver. To export metrics to SaaS
Stackdriver, you must provide your Google Cloud project ID:
350
Properties
management.metrics.export.stackdriver.project-id=my-project
Yaml
management:
metrics:
export:
stackdriver:
project-id: "my-project"
You can also change the interval at which metrics are sent to Stackdriver:
Properties
management.metrics.export.stackdriver.step=30s
Yaml
management:
metrics:
export:
stackdriver:
step: "30s"
StatsD
The StatsD registry eagerly pushes metrics over UDP to a StatsD agent. By default, metrics are
exported to a StatsD agent running on your local machine. You can provide the StatsD agent host,
port, and protocol to use by using:
Properties
management.metrics.export.statsd.host=statsd.example.com
management.metrics.export.statsd.port=9125
management.metrics.export.statsd.protocol=udp
Yaml
management:
metrics:
export:
statsd:
host: "statsd.example.com"
port: 9125
protocol: "udp"
351
You can also change the StatsD line protocol to use (it defaults to Datadog):
Properties
management.metrics.export.statsd.flavor=etsy
Yaml
management:
metrics:
export:
statsd:
flavor: "etsy"
Wavefront
The Wavefront registry periodically pushes metrics to Wavefront. If you are exporting metrics to
Wavefront directly, you must provide your API token:
Properties
management.metrics.export.wavefront.api-token=YOUR_API_TOKEN
Yaml
management:
metrics:
export:
wavefront:
api-token: "YOUR_API_TOKEN"
Alternatively, you can use a Wavefront sidecar or an internal proxy in your environment to
forward metrics data to the Wavefront API host:
Properties
management.metrics.export.wavefront.uri=proxy://localhost:2878
Yaml
management:
metrics:
export:
wavefront:
uri: "proxy://localhost:2878"
352
If you publish metrics to a Wavefront proxy (as described in the Wavefront
NOTE
documentation), the host must be in the proxy://HOST:PORT format.
You can also change the interval at which metrics are sent to Wavefront:
Properties
management.metrics.export.wavefront.step=30s
Yaml
management:
metrics:
export:
wavefront:
step: "30s"
Spring Boot provides automatic meter registration for a wide variety of technologies. In most
situations, the defaults provide sensible metrics that can be published to any of the supported
monitoring systems.
JVM Metrics
Auto-configuration enables JVM Metrics by using core Micrometer classes. JVM metrics are
published under the jvm. meter name.
• Thread utilization
System Metrics
Auto-configuration enables system metrics by using core Micrometer classes. System metrics are
published under the system., process., and disk. meter names.
• CPU metrics
• Uptime metrics (both the amount of time the application has been running and a fixed gauge of
the absolute start time)
353
• Disk space available
Metrics are tagged by the fully qualified name of the application class.
Logger Metrics
Auto-configuration enables the event metrics for both Logback and Log4J2. The details are
published under the log4j2.events. or logback.events. meter names.
Auto-configuration enables the instrumentation of all requests handled by Spring MVC controllers
and functional handlers. By default, metrics are generated with the name, http.server.requests.
You can customize the name by setting the management.metrics.web.server.request.metric-name
property.
@Timed annotations are supported on @Controller classes and @RequestMapping methods (see @Timed
Annotation Support for details). If you do not want to record metrics for all Spring MVC requests,
you can set management.metrics.web.server.request.autotime.enabled to false and exclusively use
@Timed annotations instead.
By default, Spring MVC related metrics are tagged with the following information:
Tag Description
exception The simple class name of any exception that was
thrown while handling the request.
method The request’s method (for example, GET or POST)
outcome The request’s outcome, based on the status code
of the response. 1xx is INFORMATIONAL, 2xx is
SUCCESS, 3xx is REDIRECTION, 4xx is CLIENT_ERROR,
and 5xx is SERVER_ERROR
status The response’s HTTP status code (for example,
200 or 500)
354
Tag Description
uri The request’s URI template prior to variable
substitution, if possible (for example,
/api/person/{id})
To add to the default tags, provide one or more @Beans that implement WebMvcTagsContributor. To
replace the default tags, provide a @Bean that implements WebMvcTagsProvider.
In some cases, exceptions handled in web controllers are not recorded as request
TIP metrics tags. Applications can opt in and record exceptions by setting handled
exceptions as request attributes.
By default, all requests are handled. To customize the filter, provide a @Bean that implements
FilterRegistrationBean<WebMvcMetricsFilter>.
@Timed annotations are supported on @Controller classes and @RequestMapping methods (see @Timed
Annotation Support for details). If you do not want to record metrics for all Spring WebFlux
requests, you can set management.metrics.web.server.request.autotime.enabled to false and
exclusively use @Timed annotations instead.
By default, WebFlux related metrics are tagged with the following information:
Tag Description
exception The simple class name of any exception that was
thrown while handling the request.
method The request’s method (for example, GET or POST)
outcome The request’s outcome, based on the status code
of the response. 1xx is INFORMATIONAL, 2xx is
SUCCESS, 3xx is REDIRECTION, 4xx is CLIENT_ERROR,
and 5xx is SERVER_ERROR
status The response’s HTTP status code (for example,
200 or 500)
uri The request’s URI template prior to variable
substitution, if possible (for example,
/api/person/{id})
To add to the default tags, provide one or more beans that implement WebFluxTagsContributor. To
replace the default tags, provide a bean that implements WebFluxTagsProvider.
355
In some cases, exceptions handled in controllers and handler functions are not
TIP recorded as request metrics tags. Applications can opt in and record exceptions by
setting handled exceptions as request attributes.
Spring Boot Actuator manages the instrumentation of both RestTemplate and WebClient. For that,
you have to inject the auto-configured builder and use it to create instances:
You can also manually apply the customizers responsible for this instrumentation, namely
MetricsRestTemplateCustomizer and MetricsWebClientCustomizer.
By default, metrics are generated with the name, http.client.requests. You can customize the name
by setting the management.metrics.web.client.request.metric-name property.
By default, metrics generated by an instrumented client are tagged with the following information:
Tag Description
clientName The host portion of the URI
method The request’s method (for example, GET or POST)
outcome The request’s outcome, based on the status code
of the response. 1xx is INFORMATIONAL, 2xx is
SUCCESS, 3xx is REDIRECTION, 4xx is CLIENT_ERROR,
and 5xx is SERVER_ERROR. Otherwise, it is UNKNOWN.
status The response’s HTTP status code if available (for
example, 200 or 500) or IO_ERROR in case of I/O
issues. Otherwise, it is CLIENT_ERROR.
uri The request’s URI template prior to variable
substitution, if possible (for example,
/api/person/{id})
To customize the tags, and depending on your choice of client, you can provide a @Bean that
implements RestTemplateExchangeTagsProvider or WebClientExchangeTagsProvider. There are
convenience static functions in RestTemplateExchangeTags and WebClientExchangeTags.
Tomcat Metrics
356
Cache Metrics
Auto-configuration enables the instrumentation of all available Cache instances on startup, with
metrics prefixed with cache. Cache instrumentation is standardized for a basic set of metrics.
Additional, cache-specific metrics are also available.
• Caffeine
• Hazelcast
• Redis
Metrics are tagged by the name of the cache and by the name of the CacheManager, which is derived
from the bean name.
Only caches that are configured on startup are bound to the registry. For caches not
defined in the cache’s configuration, such as caches created on the fly or
NOTE
programmatically after the startup phase, an explicit registration is required. A
CacheMetricsRegistrar bean is made available to make that process easier.
DataSource Metrics
Auto-configuration enables the instrumentation of all available DataSource objects with metrics
prefixed with jdbc.connections. Data source instrumentation results in gauges that represent the
currently active, idle, maximum allowed, and minimum allowed connections in the pool.
Metrics are also tagged by the name of the DataSource computed based on the bean name.
By default, Spring Boot provides metadata for all supported data sources. You can add
TIP additional DataSourcePoolMetadataProvider beans if your favorite data source is not
supported. See DataSourcePoolMetadataProvidersConfiguration for examples.
Also, Hikari-specific metrics are exposed with a hikaricp prefix. Each metric is tagged by the name
of the pool (you can control it with spring.datasource.name).
Auto-configuration enables the instrumentation of all Spring Data Repository method invocations.
By default, metrics are generated with the name, spring.data.repository.invocations. You can
customize the name by setting the management.metrics.data.repository.metric-name property.
@Timed annotations are supported on Repository classes and methods (see @Timed Annotation
Support for details). If you do not want to record metrics for all Repository invocations, you can set
management.metrics.data.repository.autotime.enabled to false and exclusively use @Timed
annotations instead.
By default, repository invocation related metrics are tagged with the following information:
357
Tag Description
repository The simple class name of the source Repository.
method The name of the Repository method that was
invoked.
state The result state (SUCCESS, ERROR, CANCELED, or
RUNNING).
exception The simple class name of any exception that was
thrown from the invocation.
RabbitMQ Metrics
Auto-configuration enables the instrumentation of all available RabbitMQ connection factories with
a metric named rabbitmq.
Kafka Metrics
MongoDB Metrics
A timer metric named mongodb.driver.commands is created for each command issued to the
underlying MongoDB driver. Each metric is tagged with the following information by default:
Tag Description
command The name of the command issued.
cluster.id The identifier of the cluster to which the
command was sent.
server.address The address of the server to which the command
was sent.
358
Tag Description
status The outcome of the command (SUCCESS or
FAILED).
To replace the default metric tags, define a MongoCommandTagsProvider bean, as the following
example shows:
import io.micrometer.core.instrument.binder.mongodb.MongoCommandTagsProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyCommandTagsProviderConfiguration {
@Bean
public MongoCommandTagsProvider customCommandTagsProvider() {
return new CustomCommandTagsProvider();
}
Properties
management.metrics.mongo.command.enabled=false
Yaml
management:
metrics:
mongo:
command:
enabled: false
The following gauge metrics are created for the connection pool:
• mongodb.driver.pool.size reports the current size of the connection pool, including idle and and
in-use members.
• mongodb.driver.pool.waitqueuesize reports the current size of the wait queue for a connection
359
from the pool.
Tag Description
cluster.id The identifier of the cluster to which the
connection pool corresponds.
server.address The address of the server to which the
connection pool corresponds.
import io.micrometer.core.instrument.binder.mongodb.MongoConnectionPoolTagsProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyConnectionPoolTagsProviderConfiguration {
@Bean
public MongoConnectionPoolTagsProvider customConnectionPoolTagsProvider() {
return new CustomConnectionPoolTagsProvider();
}
To disable the auto-configured connection pool metrics, set the following property:
Properties
management.metrics.mongo.connectionpool.enabled=false
Yaml
management:
metrics:
mongo:
connectionpool:
enabled: false
Jetty Metrics
360
@Timed Annotation Support
You can use the @Timed annotation from the io.micrometer.core.annotation package with several of
the supported technologies described earlier. If supported, you can use the annotation at either the
class level or the method level.
For example, the following code shows how you can use the annotation to instrument all request
mappings in a @RestController:
import java.util.List;
import io.micrometer.core.annotation.Timed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Timed
public class MyController {
@GetMapping("/api/addresses")
public List<Address> listAddress() {
return ...
}
@GetMapping("/api/people")
public List<Person> listPeople() {
return ...
}
If you want only to instrument a single mapping, you can use the annotation on the method instead
of the class:
361
import java.util.List;
import io.micrometer.core.annotation.Timed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/api/addresses")
public List<Address> listAddress() {
return ...
}
@GetMapping("/api/people")
@Timed
public List<Person> listPeople() {
return ...
}
You can also combine class-level and method-level annotations if you want to change the timing
details for a specific method:
362
import java.util.List;
import io.micrometer.core.annotation.Timed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Timed
public class MyController {
@GetMapping("/api/addresses")
public List<Address> listAddress() {
return ...
}
@GetMapping("/api/people")
@Timed(extraTags = { "region", "us-east-1" })
@Timed(value = "all.people", longTask = true)
public List<Person> listPeople() {
return ...
}
A @Timed annotation with longTask = true enables a long task timer for the method.
NOTE Long task timers require a separate metric name and can be stacked with a short
task timer.
Redis Metrics
363
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tags;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
If your metrics depend on other beans, we recommend that you use a MeterBinder to register them:
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.springframework.context.annotation.Bean;
@Bean
public MeterBinder queueSize(Queue queue) {
return (registry) -> Gauge.builder("queueSize",
queue::size).register(registry);
}
Using a MeterBinder ensures that the correct dependency relationships are set up and that the bean
is available when the metric’s value is retrieved. A MeterBinder implementation can also be useful if
you find that you repeatedly instrument a suite of metrics across components or applications.
By default, metrics from all MeterBinder beans are automatically bound to the
NOTE
Spring-managed MeterRegistry.
If you need to apply customizations to specific Meter instances, you can use the
io.micrometer.core.instrument.config.MeterFilter interface.
For example, if you want to rename the mytag.region tag to mytag.area for all meter IDs beginning
364
with com.example, you can do the following:
import io.micrometer.core.instrument.config.MeterFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyMetricsFilterConfiguration {
@Bean
public MeterFilter renameRegionTagMeterFilter() {
return MeterFilter.renameTag("com.example", "mytag.region", "mytag.area");
}
Common Tags
Common tags are generally used for dimensional drill-down on the operating environment, such as
host, instance, region, stack, and others. Commons tags are applied to all meters and can be
configured, as the following example shows:
Properties
management.metrics.tags.region=us-east-1
management.metrics.tags.stack=prod
Yaml
management:
metrics:
tags:
region: "us-east-1"
stack: "prod"
The preceding example adds region and stack tags to all meters with a value of us-east-1 and prod,
respectively.
The order of common tags is important if you use Graphite. As the order of common
NOTE tags cannot be guaranteed by using this approach, Graphite users are advised to
define a custom MeterFilter instead.
365
Per-meter Properties
In addition to MeterFilter beans, you can apply a limited set of customization on a per-meter basis
by using properties. Per-meter customizations apply to any meter IDs that start with the given
name. The following example disables any meters that have an ID starting with example.remote
Properties
management.metrics.enable.example.remote=false
Yaml
management:
metrics:
enable:
example:
remote: false
Property Description
management.metrics.enable Whether to prevent meters from emitting any
metrics.
management.metrics.distribution.percentiles- Whether to publish a histogram suitable for
histogram computing aggregable (across dimension)
percentile approximations.
management.metrics.distribution.minimum- Publish fewer histogram buckets by clamping
expected-value, the range of expected values.
management.metrics.distribution.maximum-
expected-value
management.metrics.distribution.percentiles Publish percentile values computed in your
application
For more details on the concepts behind percentiles-histogram, percentiles, and slo, see the
“Histograms and percentiles” section of the Micrometer documentation.
Spring Boot provides a metrics endpoint that you can use diagnostically to examine the metrics
366
collected by an application. The endpoint is not available by default and must be exposed. See
exposing endpoints for more details.
Navigating to /actuator/metrics displays a list of available meter names. You can drill down to view
information about a particular meter by providing its name as a selector — for example,
/actuator/metrics/jvm.memory.max.
The name you use here should match the name used in the code, not the name after it
has been naming-convention normalized for a monitoring system to which it is
TIP shipped. In other words, if jvm.memory.max appears as jvm_memory_max in Prometheus
because of its snake case naming convention, you should still use jvm.memory.max as the
selector when inspecting the meter in the metrics endpoint.
You can also add any number of tag=KEY:VALUE query parameters to the end of the URL to
dimensionally drill down on a meter — for example,
/actuator/metrics/jvm.memory.max?tag=area:nonheap.
The reported measurements are the sum of the statistics of all meters that match the
meter name and any tags that have been applied. In the preceding example, the
returned Value statistic is the sum of the maximum memory footprints of the “Code
TIP Cache”, “Compressed Class Space”, and “Metaspace” areas of the heap. If you wanted
to see only the maximum size for the “Metaspace”, you could add an additional
tag=id:Metaspace — that is,
/actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace.
13.7. Auditing
Once Spring Security is in play, Spring Boot Actuator has a flexible audit framework that publishes
events (by default, “authentication success”, “failure” and “access denied” exceptions). This feature
can be very useful for reporting and for implementing a lock-out policy based on authentication
failures.
You can enable auditing by providing a bean of type AuditEventRepository in your application’s
configuration. For convenience, Spring Boot offers an InMemoryAuditEventRepository.
InMemoryAuditEventRepository has limited capabilities, and we recommend using it only for
development environments. For production environments, consider creating your own alternative
AuditEventRepository implementation.
To customize published security events, you can provide your own implementations of
AbstractAuthenticationAuditListener and AbstractAuthorizationAuditListener.
You can also use the audit services for your own business events. To do so, either inject the
AuditEventRepository bean into your own components and use that directly or publish an
AuditApplicationEvent with the Spring ApplicationEventPublisher (by implementing
ApplicationEventPublisherAware).
367
13.8. HTTP Tracing
You can enable HTTP Tracing by providing a bean of type HttpTraceRepository in your application’s
configuration. For convenience, Spring Boot offers InMemoryHttpTraceRepository, which stores traces
for the last 100 (the default) request-response exchanges. InMemoryHttpTraceRepository is limited
compared to other tracing solutions, and we recommend using it only for development
environments. For production environments, we recommend using a production-ready tracing or
observability solution, such as Zipkin or Spring Cloud Sleuth. Alternatively, you can create your
own HttpTraceRepository.
You can use the httptrace endpoint to obtain information about the request-response exchanges
that are stored in the HttpTraceRepository.
To customize the items that are included in each trace, use the management.trace.http.include
configuration property. For advanced customization, consider registering your own
HttpExchangeTracer implementation.
• ApplicationPidFileWriter creates a file that contains the application PID (by default, in the
application directory with a file name of application.pid).
• WebServerPortFileWriter creates a file (or files) that contain the ports of the running web server
(by default, in the application directory with a file name of application.port).
By default, these writers are not activated, but you can enable them:
• By Extending Configuration
In the META-INF/spring.factories file, you can activate the listener (or listeners) that writes a PID
file:
org.springframework.context.ApplicationListener=\
org.springframework.boot.context.ApplicationPidFileWriter,\
org.springframework.boot.web.context.WebServerPortFileWriter
You can also activate a listener by invoking the SpringApplication.addListeners(…) method and
passing the appropriate Writer object. This method also lets you customize the file name and path
368
in the Writer constructor.
The extended support lets Cloud Foundry management UIs (such as the web application that you
can use to view deployed applications) be augmented with Spring Boot actuator information. For
example, an application status page can include full health information instead of the typical
“running” or “stopped” status.
If you want to fully disable the /cloudfoundryapplication endpoints, you can add the following
setting to your application.properties file:
Properties
management.cloudfoundry.enabled=false
Yaml
management:
cloudfoundry:
enabled: false
By default, the security verification for /cloudfoundryapplication endpoints makes SSL calls to
various Cloud Foundry services. If your Cloud Foundry UAA or Cloud Controller services use self-
signed certificates, you need to set the following property:
Properties
management.cloudfoundry.skip-ssl-validation=true
Yaml
management:
cloudfoundry:
skip-ssl-validation: true
369
13.10.3. Custom Context Path
If the server’s context-path has been configured to anything other than /, the Cloud Foundry
endpoints are not available at the root of the application. For example, if server.servlet.context-
path=/app, Cloud Foundry endpoints are available at /app/cloudfoundryapplication/*.
import java.io.IOException;
import java.util.Collections;
import jakarta.servlet.GenericServlet;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContainerInitializer;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import org.apache.catalina.Host;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyCloudFoundryConfiguration {
@Bean
public TomcatServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected void prepareContext(Host host, ServletContextInitializer[]
initializers) {
super.prepareContext(host, initializers);
StandardContext child = new StandardContext();
child.addLifecycleListener(new Tomcat.FixContextListener());
child.setPath("/cloudfoundryapplication");
ServletContainerInitializer initializer =
getServletContextInitializer(getContextPath());
child.addServletContainerInitializer(initializer,
Collections.emptySet());
child.setCrossContext(true);
370
host.addChild(child);
}
};
}
@Override
public void service(ServletRequest req, ServletResponse res) throws
ServletException, IOException {
ServletContext context =
req.getServletContext().getContext(contextPath);
context.getRequestDispatcher("/cloudfoundryapplication").forward(req, res);
}
};
context.addServlet("cloudfoundry", servlet).addMapping("/*");
};
}
Otherwise, you can continue on to read about “deployment options” or jump ahead for some in-
depth information about Spring Boot’s build tool plugins.
371
Chapter 14. Deploying Spring Boot
Applications
Spring Boot’s flexible packaging options provide a great deal of choice when it comes to deploying
your application. You can deploy Spring Boot applications to a variety of cloud platforms, to
virtual/real machines, or make them fully executable for Unix systems.
Two popular cloud providers, Heroku and Cloud Foundry, employ a “buildpack” approach. The
buildpack wraps your deployed code in whatever is needed to start your application. It might be a
JDK and a call to java, an embedded web server, or a full-fledged application server. A buildpack is
pluggable, but ideally you should be able to get by with as few customizations to it as possible. This
reduces the footprint of functionality that is not under your control. It minimizes divergence
between development and production environments.
Ideally, your application, like a Spring Boot executable jar, has everything that it needs to run
packaged within it.
In this section, we look at what it takes to get the application that we developed in the “Getting
Started” section up and running in the Cloud.
Cloud Foundry provides default buildpacks that come into play if no other buildpack is specified.
The Cloud Foundry Java buildpack has excellent support for Spring applications, including Spring
Boot. You can deploy stand-alone executable jar applications as well as traditional .war packaged
applications.
Once you have built your application (by using, for example, mvn clean package) and have installed
the cf command line tool, deploy your application by using the cf push command, substituting the
path to your compiled .jar. Be sure to have logged in with your cf command line client before
pushing an application. The following line shows using the cf push command to deploy an
application:
372
See the cf push documentation for more options. If there is a Cloud Foundry manifest.yml file
present in the same directory, it is considered.
At this point, cf starts uploading your application, producing output similar to the following
example:
Uploading acloudyspringtime... OK
Preparing to start acloudyspringtime... OK
-----> Downloaded app package (8.9M)
-----> Java Buildpack Version: v3.12 (offline) | https://github.com/cloudfoundry/java-
buildpack.git#6f25b7e
-----> Downloading Open Jdk JRE 1.8.0_121 from https://java-
buildpack.cloudfoundry.org/openjdk/trusty/x86_64/openjdk-1.8.0_121.tar.gz (found in
cache)
Expanding Open Jdk JRE to .java-buildpack/open_jdk_jre (1.6s)
-----> Downloading Open JDK Like Memory Calculator 2.0.2_RELEASE from https://java-
buildpack.cloudfoundry.org/memory-calculator/trusty/x86_64/memory-calculator-
2.0.2_RELEASE.tar.gz (found in cache)
Memory Settings: -Xss349K -Xmx681574K -XX:MaxMetaspaceSize=104857K -Xms681574K
-XX:MetaspaceSize=104857K
-----> Downloading Container Certificate Trust Store 1.0.0_RELEASE from https://java-
buildpack.cloudfoundry.org/container-certificate-trust-store/container-certificate-
trust-store-1.0.0_RELEASE.jar (found in cache)
Adding certificates to .java-
buildpack/container_certificate_trust_store/truststore.jks (0.6s)
-----> Downloading Spring Auto Reconfiguration 1.10.0_RELEASE from https://java-
buildpack.cloudfoundry.org/auto-reconfiguration/auto-reconfiguration-
1.10.0_RELEASE.jar (found in cache)
Checking status of app 'acloudyspringtime'...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
...
1 of 1 instances running (1 running)
App started
Once your application is live, you can verify the status of the deployed application by using the cf
apps command, as shown in the following example:
373
$ cf apps
Getting applications in ...
OK
Once Cloud Foundry acknowledges that your application has been deployed, you should be able to
find the application at the URI given. In the preceding example, you could find it at
https://acloudyspringtime.cfapps.io/.
Binding to Services
By default, metadata about the running application as well as service connection information is
exposed to the application as environment variables (for example: $VCAP_SERVICES). This
architecture decision is due to Cloud Foundry’s polyglot (any language and platform can be
supported as a buildpack) nature. Process-scoped environment variables are language agnostic.
Environment variables do not always make for the easiest API, so Spring Boot automatically
extracts them and flattens the data into properties that can be accessed through Spring’s
Environment abstraction, as shown in the following example:
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class MyBean implements EnvironmentAware {
@Override
public void setEnvironment(Environment environment) {
this.instanceId = environment.getProperty("vcap.application.instance_id");
}
// ...
All Cloud Foundry properties are prefixed with vcap. You can use vcap properties to access
application information (such as the public URL of the application) and service information (such
as database credentials). See the ‘CloudFoundryVcapEnvironmentPostProcessor’ Javadoc for
complete details.
374
TIP The Java CFEnv project is a better fit for tasks such as configuring a DataSource.
14.1.2. Kubernetes
Spring Boot auto-detects Kubernetes deployment environments by checking the environment for
"*_SERVICE_HOST" and "*_SERVICE_PORT" variables. You can override this detection with the
spring.main.cloud-platform configuration property.
Spring Boot helps you to manage the state of your application and export it with HTTP Kubernetes
Probes using Actuator.
When Kubernetes deletes an application instance, the shutdown process involves several
subsystems concurrently: shutdown hooks, unregistering the service, removing the instance from
the load-balancer… Because this shutdown processing happens in parallel (and due to the nature of
distributed systems), there is a window during which traffic can be routed to a pod that has also
begun its shutdown processing.
You can configure a sleep execution in a preStop handler to avoid requests being routed to a pod
that has already begun shutting down. This sleep should be long enough for new requests to stop
being routed to the pod and its duration will vary from deployment to deployment. The preStop
handler can be configured by using the PodSpec in the pod’s configuration file as follows:
spec:
containers:
- name: "example-container"
image: "example-image"
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"]
Once the pre-stop hook has completed, SIGTERM will be sent to the container and graceful
shutdown will begin, allowing any remaining in-flight requests to complete.
When Kubernetes sends a SIGTERM signal to the pod, it waits for a specified time
called the termination grace period (the default for which is 30 seconds). If the
containers are still running after the grace period, they are sent the SIGKILL signal
NOTE and forcibly removed. If the pod takes longer than 30 seconds to shut down, which
could be because you have increased spring.lifecycle.timeout-per-shutdown-phase,
make sure to increase the termination grace period by setting the
terminationGracePeriodSeconds option in the Pod YAML.
14.1.3. Heroku
Heroku is another popular PaaS platform. To customize Heroku builds, you provide a Procfile,
375
which provides the incantation required to deploy an application. Heroku assigns a port for the
Java application to use and then ensures that routing to the external URI works.
You must configure your application to listen on the correct port. The following example shows the
Procfile for our starter REST application:
Spring Boot makes -D arguments available as properties accessible from a Spring Environment
instance. The server.port configuration property is fed to the embedded Tomcat, Jetty, or Undertow
instance, which then uses the port when it starts up. The $PORT environment variable is assigned to
us by the Heroku PaaS.
This should be everything you need. The most common deployment workflow for Heroku
deployments is to git push the code to production, as shown in the following example:
376
Initializing repository, done.
Counting objects: 95, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (78/78), done.
Writing objects: 100% (95/95), 8.66 MiB | 606.00 KiB/s, done.
Total 95 (delta 31), reused 0 (delta 0)
To git@heroku.com:agile-sierra-1405.git
* [new branch] main -> main
Your application should now be up and running on Heroku. For more details, see Deploying Spring
Boot Applications to Heroku.
14.1.4. OpenShift
OpenShift has many resources describing how to deploy Spring Boot applications, including:
• Architecture guide
377
• OpenShift Commons Briefing
Amazon Web Services offers multiple ways to install Spring Boot-based applications, either as
traditional web applications (war) or as executable jar files with an embedded web server. The
options include:
Each has different features and pricing models. In this document, we describe to approach using
AWS Elastic Beanstalk.
As described in the official Elastic Beanstalk Java guide, there are two main options to deploy a Java
application. You can either use the “Tomcat Platform” or the “Java SE platform”.
This option applies to Spring Boot projects that produce a war file. No special configuration is
required. You need only follow the official guide.
This option applies to Spring Boot projects that produce a jar file and run an embedded web
container. Elastic Beanstalk environments run an nginx instance on port 80 to proxy the actual
application, running on port 5000. To configure it, add the following line to your
application.properties file:
server.port=5000
deploy:
artifact: target/demo-0.0.1-SNAPSHOT.jar
378
Reduce costs by setting the environment type
By default an Elastic Beanstalk environment is load balanced. The load balancer has a
significant cost. To avoid that cost, set the environment type to “Single instance”, as
described in the Amazon documentation. You can also create single instance
TIP
environments by using the CLI and the following command:
eb create -s
Summary
This is one of the easiest ways to get to AWS, but there are more things to cover, such as how to
integrate Elastic Beanstalk into any CI / CD tool, use the Elastic Beanstalk Maven plugin instead of
the CLI, and others. There is a blog post covering these topics more in detail.
CloudCaptain works by turning your Spring Boot executable jar or war into a minimal VM image
that can be deployed unchanged either on VirtualBox or on AWS. CloudCaptain comes with deep
integration for Spring Boot and uses the information from your Spring Boot configuration file to
automatically configure ports and health check URLs. CloudCaptain leverages this information both
for the images it produces as well as for all the resources it provisions (instances, security groups,
elastic load balancers, and so on).
Once you have created a CloudCaptain account, connected it to your AWS account, installed the
latest version of the CloudCaptain Client, and ensured that the application has been built by Maven
or Gradle (by using, for example, mvn clean package), you can deploy your Spring Boot application
to AWS with a command similar to the following:
See the boxfuse run documentation for more options. If there is a boxfuse.conf file present in the
current directory, it is considered.
At this point, CloudCaptain creates an image for your application, uploads it, and configures and
starts the necessary resources on AWS, resulting in output similar to the following example:
379
Fusing Image for myapp-1.0.jar ...
Image fused in 00:06.838s (53937 K) -> axelfontaine/myapp:1.0
Creating axelfontaine/myapp ...
Pushing axelfontaine/myapp:1.0 ...
Verifying axelfontaine/myapp:1.0 ...
Creating Elastic IP ...
Mapping myapp-axelfontaine.boxfuse.io to 52.28.233.167 ...
Waiting for AWS to create an AMI for axelfontaine/myapp:1.0 in eu-central-1 (this may
take up to 50 seconds) ...
AMI created in 00:23.557s -> ami-d23f38cf
Creating security group boxfuse-sg_axelfontaine/myapp:1.0 ...
Launching t2.micro instance of axelfontaine/myapp:1.0 (ami-d23f38cf) in eu-central-1
...
Instance launched in 00:30.306s -> i-92ef9f53
Waiting for AWS to boot Instance i-92ef9f53 and Payload to start at
https://52.28.235.61/ ...
Payload started in 00:29.266s -> https://52.28.235.61/
Remapping Elastic IP 52.28.233.167 to i-92ef9f53 ...
Waiting 15s for AWS to complete Elastic IP Zero Downtime transition ...
Deployment completed successfully. axelfontaine/myapp:1.0 is up and running at
https://myapp-axelfontaine.boxfuse.io/
See the blog post on deploying Spring Boot apps on EC2 as well as the documentation for the
CloudCaptain Spring Boot integration to get started with a Maven build to run the app.
14.1.7. Azure
This Getting Started guide walks you through deploying your Spring Boot application to either
Azure Spring Cloud or Azure App Service.
Google Cloud has several options that can be used to launch Spring Boot applications. The easiest to
get started with is probably App Engine, but you could also find ways to run Spring Boot in a
container with Container Engine or on a virtual machine with Compute Engine.
To run in App Engine, you can create a project in the UI first, which sets up a unique identifier for
you and also sets up HTTP routes. Add a Java app to the project and leave it empty and then use the
Google Cloud SDK to push your Spring Boot app into that slot from the command line or CI build.
App Engine Standard requires you to use WAR packaging. Follow these steps to deploy App Engine
Standard application to Google Cloud.
Alternatively, App Engine Flex requires you to create an app.yaml file to describe the resources your
app requires. Normally, you put this file in src/main/appengine, and it should resemble the following
file:
380
service: "default"
runtime: "java"
env: "flex"
runtime_config:
jdk: "openjdk8"
handlers:
- url: "/.*"
script: "this field is required, but ignored"
manual_scaling:
instances: 1
health_check:
enable_health_check: false
env_variables:
ENCRYPT_KEY: "your_encryption_key_here"
You can deploy the app (for example, with a Maven plugin) by adding the project ID to the build
configuration, as shown in the following example:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>1.3.0</version>
<configuration>
<project>myproject</project>
</configuration>
</plugin>
Then deploy with mvn appengine:deploy (if you need to authenticate first, the build fails).
381
Fully executable jars work by embedding an extra script at the front of the file.
Currently, some tools do not accept this format, so you may not always be able
to use this technique. For example, jar -xf may silently fail to extract a jar or
CAUTION
war that has been made fully executable. It is recommended that you make
your jar or war fully executable only if you intend to execute it directly, rather
than running it with java -jar or deploying it to a servlet container.
To create a ‘fully executable’ jar with Maven, use the following plugin configuration:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
bootJar {
launchScript()
}
You can then run your application by typing ./my-application.jar (where my-application is the
name of your artifact). The directory containing the jar is used as your application’s working
directory.
The default script supports most Linux distributions and is tested on CentOS and Ubuntu. Other
platforms, such as OS X and FreeBSD, require the use of a custom embeddedLaunchScript.
Spring Boot application can be easily started as Unix/Linux services by using either init.d or
systemd.
If you configured Spring Boot’s Maven or Gradle plugin to generate a fully executable jar, and you
do not use a custom embeddedLaunchScript, your application can be used as an init.d service. To do
382
so, symlink the jar to init.d to support the standard start, stop, restart, and status commands.
• Starts the services as the user that owns the jar file
Assuming that you have a Spring Boot application installed in /var/myapp, to install a Spring Boot
application as an init.d service, create a symlink, as follows:
Once installed, you can start and stop the service in the usual way. For example, on a Debian-based
system, you could start it with the following command:
If your application fails to start, check the log file written to /var/log/<appname>.log for
TIP
errors.
You can also flag the application to start automatically by using your standard operating system
tools. For example, on Debian, you could use the following command:
The following is a set of guidelines on how to secure a Spring Boot application that
NOTE runs as an init.d service. It is not intended to be an exhaustive list of everything that
should be done to harden an application and the environment in which it runs.
When executed as root, as is the case when root is being used to start an init.d service, the default
executable script runs the application as the user specified in the RUN_AS_USER environment
variable. When the environment variable is not set, the user who owns the jar file is used instead.
You should never run a Spring Boot application as root, so RUN_AS_USER should never be root and
your application’s jar file should never be owned by root. Instead, create a specific user to run your
application and set the RUN_AS_USER environment variable or use chown to make it the owner of the
jar file, as shown in the following example:
In this case, the default executable script runs the application as the bootapp user.
383
To reduce the chances of the application’s user account being compromised, you
TIP should consider preventing it from using a login shell. For example, you can set the
account’s shell to /usr/sbin/nologin.
You should also take steps to prevent the modification of your application’s jar file. Firstly,
configure its permissions so that it cannot be written and can only be read or executed by its
owner, as shown in the following example:
Second, you should also take steps to limit the damage if your application or the account that is
running it is compromised. If an attacker does gain access, they could make the jar file writable and
change its contents. One way to protect against this is to make it immutable by using chattr, as
shown in the following example:
This will prevent any user, including root, from modifying the jar.
If root is used to control the application’s service and you use a .conf file to customize its startup,
the .conf file is read and evaluated by the root user. It should be secured accordingly. Use chmod so
that the file can only be read by the owner and use chown to make root the owner, as shown in the
following example:
systemd is the successor of the System V init system and is now being used by many modern Linux
distributions. Although you can continue to use init.d scripts with systemd, it is also possible to
launch Spring Boot applications by using systemd ‘service’ scripts.
Assuming that you have a Spring Boot application installed in /var/myapp, to install a Spring Boot
application as a systemd service, create a script named myapp.service and place it in
/etc/systemd/system directory. The following script offers an example:
384
[Unit]
Description=myapp
After=syslog.target
[Service]
User=myapp
ExecStart=/var/myapp/myapp.jar
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
Remember to change the Description, User, and ExecStart fields for your
IMPORTANT
application.
The ExecStart field does not declare the script action command, which means that
NOTE
the run command is used by default.
Note that, unlike when running as an init.d service, the user that runs the application, the PID file,
and the console log file are managed by systemd itself and therefore must be configured by using
appropriate fields in the ‘service’ script. Consult the service unit configuration man page for more
details.
To flag the application to start automatically on system boot, use the following command:
The default embedded startup script written by the Maven or Gradle plugin can be customized in a
number of ways. For most people, using the default script along with a few customizations is
usually enough. If you find you cannot customize something that you need to, use the
embeddedLaunchScript option to write your own file entirely.
It often makes sense to customize elements of the start script as it is written into the jar file. For
example, init.d scripts can provide a “description”. Since you know the description up front (and it
need not change), you may as well provide it when the jar is generated.
To customize written elements, use the embeddedLaunchScriptProperties option of the Spring Boot
Maven plugin or the properties property of the Spring Boot Gradle plugin’s launchScript.
The following property substitutions are supported with the default script:
385
Name Description Gradle default Maven default
mode The script mode. auto auto
386
Name Description Gradle default Maven default
pidFilen Default value for the name
ame of the PID file in PID_FOLDER.
Only valid for an init.d
service
useStart Whether the start-stop- true true
StopDaem daemon command, when it is
on
available, should be used to
control the process
stopWait Default value for 60 60
Time STOP_WAIT_TIME in seconds.
Only valid for an init.d
service
For items of the script that need to be customized after the jar has been written, you can use
environment variables or a config file.
The following environment properties are supported with the default script:
Variable Description
MODE The “mode” of operation. The default depends on the way the jar was built but is
usually auto (meaning it tries to guess if it is an init script by checking if it is a
symlink in a directory called init.d). You can explicitly set it to service so that the
stop|start|status|restart commands work or to run if you want to run the script in
the foreground.
RUN_AS_USER The user that will be used to run the application. When not set, the user that owns
the jar file will be used.
USE_START_ST Whether the start-stop-daemon command, when it is available, should be used to
OP_DAEMON control the process. Defaults to true.
PID_FOLDER The root name of the pid folder (/var/run by default).
LOG_FOLDER The name of the folder in which to put log files (/var/log by default).
CONF_FOLDER The name of the folder from which to read .conf files (same folder as jar-file by
default).
LOG_FILENAME The name of the log file in the LOG_FOLDER (<appname>.log by default).
APP_NAME The name of the app. If the jar is run from a symlink, the script guesses the app
name. If it is not a symlink or you want to explicitly set the app name, this can be
useful.
RUN_ARGS The arguments to pass to the program (the Spring Boot app).
JAVA_HOME The location of the java executable is discovered by using the PATH by default, but
you can set it explicitly if there is an executable file at $JAVA_HOME/bin/java.
387
Variable Description
JAVA_OPTS Options that are passed to the JVM when it is launched.
JARFILE The explicit location of the jar file, in case the script is being used to launch a jar
that it is not actually embedded.
DEBUG If not empty, sets the -x flag on the shell process, allowing you to see the logic in the
script.
STOP_WAIT_TI The time in seconds to wait when stopping the application before forcing a
ME shutdown (60 by default).
The PID_FOLDER, LOG_FOLDER, and LOG_FILENAME variables are only valid for an init.d
NOTE service. For systemd, the equivalent customizations are made by using the ‘service’
script. See the service unit configuration man page for more details.
With the exception of JARFILE and APP_NAME, the settings listed in the preceding section can be
configured by using a .conf file. The file is expected to be next to the jar file and have the same
name but suffixed with .conf rather than .jar. For example, a jar named /var/myapp/myapp.jar uses
the configuration file named /var/myapp/myapp.conf, as shown in the following example:
myapp.conf
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder
If you do not like having the config file next to the jar file, you can set a CONF_FOLDER
TIP
environment variable to customize the location of the config file.
To learn about securing this file appropriately, see the guidelines for securing an init.d service.
A (separately maintained sample) describes step-by-step how you can create a Windows service for
your Spring Boot application.
The next section goes on to cover the Spring Boot CLI, or you can jump ahead to read about build
tool plugins.
388
Chapter 15. Spring Boot CLI
The Spring Boot CLI is a command line tool that you can use if you want to quickly develop a Spring
application. It lets you run Groovy scripts, which means that you have a familiar Java-like syntax
without so much boilerplate code. You can also bootstrap a new project or write your own
command for it.
$ spring
usage: spring [--help] [--version]
<command> [<args>]
You can type spring help to get more details about any of the supported commands, as shown in the
following example:
389
$ spring help run
spring run - Run a spring groovy script
Option Description
------ -----------
--autoconfigure [Boolean] Add autoconfigure compiler
transformations (default: true)
--classpath, -cp Additional classpath entries
--no-guess-dependencies Do not attempt to guess dependencies
--no-guess-imports Do not attempt to guess imports
-q, --quiet Quiet logging
-v, --verbose Verbose logging of dependency
resolution
--watch Watch the specified file for changes
The version command provides a quick way to check which version of Spring Boot you are using, as
follows:
$ spring version
Spring CLI v3.0.0-SNAPSHOT
You can compile and run Groovy source code by using the run command. The Spring Boot CLI is
completely self-contained, so you do not need any external Groovy installation.
The following example shows a “hello world” web application written in Groovy:
hello.groovy
@RestController
class WebApplication {
@RequestMapping("/")
String home() {
"Hello World!"
}
390
To pass command-line arguments to the application, use -- to separate the commands from the
“spring” command arguments, as shown in the following example:
To set JVM command line arguments, you can use the JAVA_OPTS environment variable, as shown in
the following example:
When setting JAVA_OPTS on Microsoft Windows, make sure to quote the entire
NOTE instruction, such as set "JAVA_OPTS=-Xms256m -Xmx2048m". Doing so ensures the
values are properly passed to the process.
Standard Groovy includes a @Grab annotation, which lets you declare dependencies on third-party
libraries. This useful technique lets Groovy download jars in the same way as Maven or Gradle
would but without requiring you to use a build tool.
Spring Boot extends this technique further and tries to deduce which libraries to “grab” based on
your code. For example, since the WebApplication code shown previously uses @RestController
annotations, Spring Boot grabs "Tomcat" and "Spring MVC".
Items Grabs
391
Deduced “grab” Coordinates
Spring Boot extends Groovy’s standard @Grab support by letting you specify a dependency without a
group or version (for example, @Grab('freemarker')). Doing so consults Spring Boot’s default
dependency metadata to deduce the artifact’s group and version.
The default metadata is tied to the version of the CLI that you use. It changes only
when you move to a new version of the CLI, putting you in control of when the
NOTE versions of your dependencies may change. A table showing the dependencies and
their versions that are included in the default metadata can be found in the
appendix.
To help reduce the size of your Groovy code, several import statements are automatically included.
Notice how the preceding example refers to @Component, @RestController, and @RequestMapping
without needing to use fully-qualified names or import statements.
Many Spring annotations work without using import statements. Try running your
TIP
application to see what fails before adding imports.
Unlike the equivalent Java application, you do not need to include a public static void
main(String[] args) method with your Groovy scripts. A SpringApplication is automatically created,
with your compiled code acting as the source.
By default, the CLI uses the dependency management declared in spring-boot-dependencies when
resolving @Grab dependencies. Additional dependency management, which overrides the default
dependency management, can be configured by using the @DependencyManagementBom annotation. The
annotation’s value should specify the coordinates (groupId:artifactId:version) of one or more
Maven BOMs.
@DependencyManagementBom("com.example.custom-bom:1.0.0")
When you specify multiple BOMs, they are applied in the order in which you declare them, as
shown in the following example:
392
@DependencyManagementBom([
"com.example.custom-bom:1.0.0",
"com.example.another-bom:1.0.0"])
The preceding example indicates that the dependency management in another-bom overrides the
dependency management in custom-bom.
You can use @DependencyManagementBom anywhere that you can use @Grab. However, to ensure
consistent ordering of the dependency management, you can use @DependencyManagementBom at most
once in your application.
You can use “shell globbing” with all commands that accept file input. Doing so lets you use
multiple files from a single directory, as shown in the following example:
You can use the jar command to package your application into a self-contained executable jar file,
as shown in the following example:
The resulting jar contains the classes produced by compiling the application and all of the
application’s dependencies so that it can then be run by using java -jar. The jar file also contains
entries from the application’s classpath. You can add and remove explicit paths to the jar by using
--include and --exclude. Both are comma-separated, and both accept prefixes, in the form of “+”
and “-”, to signify that they should be removed from the defaults. The default includes are as
follows:
Type spring help jar on the command line for more information.
The init command lets you create a new project by using start.spring.io without leaving the shell,
as shown in the following example:
393
$ spring init --dependencies=web,data-jpa my-project
Using service at https://start.spring.io
Project extracted to '/Users/developer/example/my-project'
The preceding example creates a my-project directory with a Maven-based project that uses spring-
boot-starter-web and spring-boot-starter-data-jpa. You can list the capabilities of the service by
using the --list flag, as shown in the following example:
Available dependencies:
-----------------------
actuator - Actuator: Production ready features to help you monitor and manage your
application
...
web - Web: Support for full-stack web development, including Tomcat and spring-webmvc
websocket - Websocket: Support for WebSocket development
ws - WS: Support for Spring Web Services
...
The init command supports many options. See the help output for more details. For instance, the
following command creates a Gradle project that uses Java 8 and war packaging:
Spring Boot includes command-line completion scripts for the BASH and zsh shells. If you do not
use either of these shells (perhaps you are a Windows user), you can use the shell command to
launch an integrated shell, as shown in the following example:
394
$ spring shell
Spring Boot (v3.0.0-SNAPSHOT)
Hit TAB to complete. Type \'help' and hit RETURN for help, and \'exit' to quit.
From inside the embedded shell, you can run other commands directly:
$ version
Spring CLI v3.0.0-SNAPSHOT
The embedded shell supports ANSI color output as well as tab completion. If you need to run a
native command, you can use the ! prefix. To exit the embedded shell, press ctrl-c.
You can add extensions to the CLI by using the install command. The command takes one or more
sets of artifact coordinates in the format group:artifact:version, as shown in the following
example:
In addition to installing the artifacts identified by the coordinates you supply, all of the artifacts'
dependencies are also installed.
To uninstall a dependency, use the uninstall command. As with the install command, it takes one
or more sets of artifact coordinates in the format of group:artifact:version, as shown in the
following example:
It uninstalls the artifacts identified by the coordinates you supply and their dependencies.
To uninstall all additional dependencies, you can use the --all option, as shown in the following
example:
395
@Configuration(proxyBeanMethods = false)
class Application implements CommandLineRunner {
@Autowired
SharedService service
@Override
void run(String... args) {
println service.message
}
import my.company.SharedService
beans {
service(SharedService) {
message = "Hello World"
}
}
You can mix class declarations with beans{} in the same file as long as they stay at the top level, or,
if you prefer, you can put the beans DSL in a separate file.
• Offline
• Mirrors
• Servers
• Proxies
• Profiles
◦ Activation
◦ Repositories
• Active profiles
396
If you find that you reach the limit of the CLI tool, you probably want to look at converting your
application to a full Gradle or Maven built “Groovy project”. The next section covers Spring Boot’s
"Build tool plugins", which you can use with Gradle or Maven.
397
Chapter 16. Build Tool Plugins
Spring Boot provides build tool plugins for Maven and Gradle. The plugins offer a variety of
features, including the packaging of executable jars. This section provides more details on both
plugins as well as some help should you need to extend an unsupported build system. If you are
just getting started, you might want to read “Build Systems” from the “Developing with Spring Boot”
section first.
• API
• API
<project xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="myapp" default="build">
...
</project>
You need to remember to start Ant using the -lib option, as shown in the following example:
398
The “Using Spring Boot” section includes a more complete example of using Apache
TIP
Ant with spring-boot-antlib.
Once the spring-boot-antlib namespace has been declared, the following additional tasks are
available:
You can use the exejar task to create a Spring Boot executable jar. The following attributes are
supported by the task:
Element Description
resources One or more Resource Collections describing a set of Resources that should be
added to the content of the created jar file.
lib One or more Resource Collections that should be added to the set of jar
libraries that make up the runtime dependency classpath of the application.
Examples
Specify start-class
<spring-boot:exejar destfile="target/my-application.jar"
classes="target/classes" start-class="com.example.MyApplication">
<resources>
<fileset dir="src/main/resources" />
</resources>
<lib>
<fileset dir="lib" />
</lib>
</spring-boot:exejar>
399
Detect start-class
The findmainclass task is used internally by exejar to locate a class declaring a main. If necessary,
you can also use this task directly in your build. The following attributes are supported:
Examples
The Spring Boot Maven and Gradle plugins both make use of spring-boot-loader-tools to actually
generate jars. If you need to, you may use this library directly.
400
16.4.1. Repackaging Archives
When repackaging an archive, you can include references to dependency files by using the
org.springframework.boot.loader.tools.Libraries interface. We do not provide any concrete
implementations of Libraries here as they are usually build-system-specific.
If you do not use Repackager.setMainClass() to specify a main class, the repackager uses ASM to
read class files and tries to find a suitable class with a public static void main(String[] args)
method. An exception is thrown if more than one candidate is found.
401
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.springframework.boot.loader.tools.Library;
import org.springframework.boot.loader.tools.LibraryCallback;
import org.springframework.boot.loader.tools.LibraryScope;
import org.springframework.boot.loader.tools.Repackager;
402
Chapter 17. “How-to” Guides
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.
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.
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
If you need access to the BeanFactory or the Environment, your FailureAnalyzer can
NOTE
implement BeanFactoryAware or EnvironmentAware respectively.
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.
403
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 *AutoConfiguration and read their sources. Pay special attention to the
@Conditional* annotations to find out what features they enable and when. Add --debug to the
command line or a System property -Ddebug to get a log on the console of all the auto-
configuration decisions that were made in your app. In a running application with actuator
enabled, look at the conditions endpoint (/actuator/conditions or the JMX equivalent) for the
same information.
• Look for classes that are @ConfigurationProperties (such as ServerProperties) and read from
there the available external configuration options. The @ConfigurationProperties annotation has
a name attribute that acts as a prefix to external properties. Thus, ServerProperties has
prefix="server" and its configuration properties are server.port, server.address, and others. In
a running application with actuator enabled, look at the configprops endpoint.
• Look for uses of the bind method on the Binder to pull configuration values explicitly out of the
Environment in a relaxed manner. It is often used with a prefix.
• Look for @ConditionalOnExpression annotations that switch features on and off in response to
SpEL expressions, normally evaluated with placeholders resolved from the Environment.
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:
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostP
rocessor
404
The implementation can load arbitrary files and add them to the Environment. For instance, the
following example loads a YAML configuration file from the classpath:
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;
@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);
}
The Environment has 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
TIP the environment. The preceding example adds the custom-resource property 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.
405
While using @PropertySource on your @SpringBootApplication may seem to be a
convenient way to load a custom resource in the Environment, we do not
recommend it. Such property sources are not added to the Environment until the
CAUTION
application context is being refreshed. This is too late to configure certain
properties such as logging.* and spring.main.* which are read before refresh
begins.
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.
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.
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.
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@
406
Yaml
app:
encoding: "@project.build.sourceEncoding@"
java:
version: "@java.version@"
Only production configuration is filtered that way (in other words, no filtering is
NOTE
applied on src/test/resources).
If you enable the addResources flag, the spring-boot:run goal can add
src/main/resources directly to the classpath (for hot reloading purposes). Doing so
TIP circumvents the resource filtering and this feature. Instead, you can use the exec:java
goal 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:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<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>
407
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:
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}
Yaml
app:
name: "${name}"
description: "${description}"
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=off
Yaml
spring:
main:
web-application-type: "none"
banner-mode: "off"
408
Then 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:
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
import org.springframework.boot.Banner;
import org.springframework.boot.builder.SpringApplicationBuilder;
Properties
spring.main.sources=com.example.MyDatabaseConfig,com.example.MyJmsConfig
spring.main.banner-mode=console
409
Yaml
spring:
main:
sources: "com.example.MyDatabaseConfig,com.example.MyJmsConfig"
banner-mode: "console"
The actual application will show the banner (as overridden by configuration) and uses three
sources for the ApplicationContext. The application sources are:
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:
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 ‘.yml’ extension are also added to
the list.
Spring Boot logs the configuration files that are loaded at the DEBUG level and the candidates it has
not found at TRACE level.
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}
410
Yaml
server:
port: "${port:8080}"
If you inherit from the spring-boot-starter-parent POM, the default filter token of the
maven-resources-plugins has been changed from ${*} to @ (that is, @maven.token@
TIP 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 other delimiters.
In this specific case, the port binding works in a PaaS environment such as Heroku
or Cloud Foundry. In those two platforms, the PORT environment variable is set
NOTE
automatically and Spring can bind to capitalized synonyms for Environment
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:
spring:
application:
name: "cruncher"
datasource:
driver-class-name: "com.mysql.jdbc.Driver"
url: "jdbc:mysql://localhost/test"
server:
port: 9000
Create a file called application.yml 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.
spring.application.name=cruncher
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/test
server.port=9000
See “Working with YAML” in the ‘Spring Boot features’ section for more information about YAML.
411
17.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:
In Spring Boot, you can also set the active profile in application.properties, as shown in the
following example:
Properties
spring.profiles.active=production
Yaml
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 “Profiles” in the “Spring Boot features” section for more information.
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=dev
Yaml
spring:
profiles:
default: "dev"
412
See “Profiles” in the “Spring Boot features” section for more information.
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.
Properties
server.port=9000
#---
spring.config.activate.on-profile=development
server.port=9001
#---
spring.config.activate.on-profile=production
server.port=0
Yaml
server:
port: 9000
---
spring:
config:
activate:
on-profile: "development"
server:
port: 9001
---
spring:
config:
activate:
on-profile: "production"
server:
port: 0
In 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.
The documents are merged in the order in which they are encountered. Later
NOTE
values override earlier values.
413
17.2.9. Discover Built-in Options for External Properties
Spring Boot binds external properties from application.properties (or .yml 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".
• For servlet stack applications, the spring-boot-starter-web includes Tomcat by including spring-
boot-starter-tomcat, but you can use spring-boot-starter-jetty or spring-boot-starter-
undertow instead.
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:
414
<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>
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
NOTE
does support servlet 4.0, override the jetty.version property rather than the
servlet-api.version property.
The following Gradle example configures the necessary dependencies and a module replacement to
use Undertow in place of Reactor Netty for Spring WebFlux:
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")
}
}
}
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
415
shown in the following example:
Properties
spring.main.web-application-type=none
Yaml
spring:
main:
web-application-type: "none"
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.
To scan for a free port (using OS natives to prevent clashes) use server.port=0.
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.
416
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class MyWebIntegrationTests {
@LocalServerPort
int port;
// ...
HTTP response compression is supported by Jetty, Tomcat, and Undertow. It can be enabled in
application.properties, as follows:
Properties
server.compression.enabled=true
Yaml
server:
compression:
enabled: true
By 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/html
• text/xml
• text/plain
• text/css
• text/javascript
• application/javascript
417
• application/json
• application/xml
SSL can be configured declaratively by setting the various server.ssl.* properties, typically in
application.properties or application.yml. The following example shows setting SSL properties in
application.properties:
Properties
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret
Yaml
server:
port: 8443
ssl:
key-store: "classpath:keystore.jks"
key-store-password: "secret"
key-password: "another-secret"
Using 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.
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. 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.
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.
418
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:
This error is not fatal, and the application still starts with HTTP/1.1 SSL support.
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).
As of Undertow 1.4.0+, both h2 and h2c are supported on JDK 8 without any additional
dependencies.
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.yml 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.*
419
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):
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
}
Spring Boot uses that infrastructure internally to auto-configure the server. Auto-
configured WebServerFactoryCustomizer beans have an order of 0 and will be
NOTE
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.
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.
420
17.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:
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.
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.
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:
421
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;
}
@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.
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)
Yaml
server:
tomcat:
basedir: "my-tomcat"
accesslog:
enabled: true
pattern: "%t %a %r %s (%D ms)"
422
The default location for logs is a logs directory relative to the Tomcat base directory.
By default, the logs directory is a temporary directory, so you may want to fix
NOTE Tomcat’s base directory or use an absolute path for the logs. In the preceding
example, the logs are available in my-tomcat/logs relative 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)
Yaml
server:
undertow:
accesslog:
enabled: true
pattern: "%t %a %r %s (%D ms)"
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.
Properties
server.jetty.accesslog.enabled=true
server.jetty.accesslog.filename=/var/log/jetty-access.log
Yaml
server:
jetty:
accesslog:
enabled: true
filename: "/var/log/jetty-access.log"
By default, logs are redirected to System.err. For more details, see the Jetty documentation.
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.
423
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. You can register it as a
servlet filter in your application by setting server.forward-headers-strategy is set to FRAMEWORK.
If you are using Tomcat and terminating SSL at the proxy, server.tomcat.redirect-
TIP context-root should be set to false. This allows the X-Forwarded-Proto header to be
honored before any redirects are performed.
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-header
Yaml
server:
tomcat:
remoteip:
remote-ip-header: "x-your-remote-ip-header"
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, as shown in the
following example:
Properties
server.tomcat.remoteip.internal-proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}
424
Yaml
server:
tomcat:
remoteip:
internal-proxies: "192\\.168\\.\\d{1,3}\\.\\d{1,3}"
You can trust all proxies by setting the internal-proxies to empty (but do not do so
NOTE
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.
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>
sslConnectorCustomizer() {
return (tomcat) ->
tomcat.addAdditionalTomcatConnectors(createConnectorConnector());
}
425
17.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:
If 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:
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()));
}
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=true
426
Yaml
server:
tomcat:
mbeanregistry:
enabled: true
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);
}
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:
427
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();
}
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.
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:
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();
}
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.
428
17.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:
<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:
import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class MyThing {
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:
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
To get the server to render XML instead of JSON, you might have to send an Accept:
NOTE
text/xml header (or use a browser).
Spring MVC (client and server side) uses HttpMessageConverters to negotiate content conversion in
429
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
• SerializationFeature.WRITE_DATES_AS_TIMESTAMPS is 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:
430
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.
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.
Spring Boot embraces the servlet 5 jakarta.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.
431
It is recommended to use the container’s built-in support for multipart uploads
NOTE rather than introducing an additional dependency such as Apache Commons File
Upload.
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=/mypath
Yaml
spring:
mvc:
servlet:
path: "/mypath"
If 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.
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.
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.
432
• An InternalResourceViewResolver named ‘defaultViewResolver’. This one locates physical
resources that can be rendered by using the DefaultServlet (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 through spring.mvc.view.prefix and
spring.mvc.view.suffix). You can override it by providing a bean of the same type.
• If you use Groovy templates (actually, if groovy-templates is on your classpath), you also have a
GroovyMarkupViewResolver named ‘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). The prefix and suffix have
default values of ‘classpath:/templates/’ and ‘.tpl’, respectively. You can override
GroovyMarkupViewResolver by providing a bean of the same name.
• WebMvcAutoConfiguration
• ThymeleafAutoConfiguration
• FreeMarkerAutoConfiguration
• GroovyTemplateAutoConfiguration
433
17.5. HTTP Clients
Spring Boot offers a number of starters that work with HTTP clients. This section answers questions
related to using them.
The exact details of the proxy configuration depend on the underlying client request factory that is
being used.
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);
}
434
Note the use of ReactorResourceFactory for the connection provider and event loop
TIP resources. This ensures efficient sharing of resources for the server receiving requests
and the client making requests.
17.6. 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:
<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=error
Yaml
logging:
level:
org.springframework.web: "debug"
org.hibernate: "error"
You 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.
435
17.6.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.
The Logback documentation has a dedicated section that covers configuration in some
TIP
detail.
Spring Boot provides a number of logback configurations that be included from your own
configuration. These includes are designed to allow certain common Spring Boot conventions to be
re-applied.
• defaults.xml - Provides conversion rules, pattern properties and common logger configurations.
In addition, a legacy base.xml file is provided for compatibility with earlier versions of Spring Boot.
Your logback configuration file can also make use of System properties that the LoggingSystem takes
care of creating for you:
• ${LOG_PATH}: Whether logging.file.path (representing a directory for log files to live in) was set
in Boot’s external configuration.
436
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.
Spring extensions are not supported with Groovy configuration. Any logback-
NOTE
spring.groovy files will not be detected.
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:
Properties
logging.file.name=myapplication.log
Yaml
logging:
file:
name: "myapplication.log"
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.
437
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:
<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:
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")
}
}
}
The Log4j starters gather together the dependencies for common logging
NOTE requirements (such as having Tomcat use java.util.logging but configuring the
output using Log4j 2).
438
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:
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.
To configure your own DataSource, define a @Bean of that type in your configuration. Spring Boot
reuses your DataSource anywhere one is required, including database initialization. If you need to
externalize some settings, you can bind your DataSource to the environment (see “Third-party
Configuration”).
439
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "app.datasource")
public SomeDataSource dataSource() {
return new SomeDataSource();
}
The following example shows how to define a data source by setting properties:
Properties
app.datasource.url=jdbc:h2:mem:mydb
app.datasource.username=sa
app.datasource.pool-size=30
Yaml
app:
datasource:
url: "jdbc:h2:mem:mydb"
username: "sa"
pool-size: 30
Assuming that SomeDataSource has regular JavaBean properties for the URL, the username, and the
pool size, these settings are bound automatically before the DataSource is made available to other
components.
Spring Boot also provides a utility builder class, called 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 is available on the classpath. It also auto-detects the driver based on the JDBC URL.
The following example shows how to create a data source by using a DataSourceBuilder:
440
import javax.sql.DataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {
@Bean
@ConfigurationProperties("app.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
To run an app with that DataSource, all you need 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.
The following example shows how to define a JDBC data source by setting properties:
Properties
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
Yaml
app:
datasource:
url: "jdbc:mysql://localhost/test"
username: "dbuser"
password: "dbpass"
pool-size: 30
However, there is a catch. 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
(because the DataSource interface exposes no properties). Also, if you happen to have Hikari on the
classpath, this basic setup does not work, because Hikari has no url property (but does have a
jdbcUrl property). In that case, you must rewrite your configuration as follows:
441
Properties
app.datasource.jdbc-url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
Yaml
app:
datasource:
jdbc-url: "jdbc:mysql://localhost/test"
username: "dbuser"
password: "dbpass"
pool-size: 30
You can fix that by forcing the connection pool to use and return a dedicated implementation
rather than DataSource. You cannot change the implementation at runtime, but the list of options
will be explicit.
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {
@Bean
@ConfigurationProperties("app.datasource")
public HikariDataSource dataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
You can even go further by leveraging what DataSourceProperties does for you — that is, by
providing a default embedded database with a sensible username and password if no URL is
provided. You can easily initialize a DataSourceBuilder from the state of any DataSourceProperties
object, so you could also inject the DataSource that Spring Boot creates automatically. However, that
would split your configuration into 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, as shown in the following
example:
442
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {
@Bean
@Primary
@ConfigurationProperties("app.datasource")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties("app.datasource.configuration")
public HikariDataSource dataSource(DataSourceProperties properties) {
return
properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
This setup puts you in sync 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 app.datasource.configuration
sub namespace. Because DataSourceProperties is taking care of the url/jdbcUrl translation for you,
you can configure it as follows:
Properties
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.configuration.maximum-pool-size=30
Yaml
app:
datasource:
url: "jdbc:mysql://localhost/test"
username: "dbuser"
password: "dbpass"
configuration:
maximum-pool-size: 30
443
Spring Boot will expose Hikari-specific settings to spring.datasource.hikari. This
TIP example uses a more generic configuration sub namespace as the example does not
support multiple datasource implementations.
See “Configure a DataSource” in the “Spring Boot features” section and the
DataSourceAutoConfiguration class for more details.
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 instances as @Primary, because
various auto-configurations down the road expect to be able to get one by type.
If you create your own DataSource, the auto-configuration backs off. In the following example, we
provide the exact same feature set as the auto-configuration provides on the primary data source:
444
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration(proxyBeanMethods = false)
public class MyDataSourcesConfiguration {
@Bean
@Primary
@ConfigurationProperties("app.datasource.first")
public DataSourceProperties firstDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@Primary
@ConfigurationProperties("app.datasource.first.configuration")
public HikariDataSource firstDataSource(DataSourceProperties
firstDataSourceProperties) {
return
firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).b
uild();
}
@Bean
@ConfigurationProperties("app.datasource.second")
public BasicDataSource secondDataSource() {
return DataSourceBuilder.create().type(BasicDataSource.class).build();
}
Both data sources are also bound for advanced customizations. For instance, you could configure
them as follows:
445
Properties
app.datasource.first.url=jdbc:mysql://localhost/first
app.datasource.first.username=dbuser
app.datasource.first.password=dbpass
app.datasource.first.configuration.maximum-pool-size=30
app.datasource.second.url=jdbc:mysql://localhost/second
app.datasource.second.username=dbuser
app.datasource.second.password=dbpass
app.datasource.second.max-total=30
Yaml
app:
datasource:
first:
url: "jdbc:mysql://localhost/first"
username: "dbuser"
password: "dbpass"
configuration:
maximum-pool-size: 30
second:
url: "jdbc:mysql://localhost/second"
username: "dbuser"
password: "dbpass"
max-total: 30
You can apply the same concept to the secondary DataSource as well, as shown in the following
example:
446
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration(proxyBeanMethods = false)
public class MyCompleteDataSourcesConfiguration {
@Bean
@Primary
@ConfigurationProperties("app.datasource.first")
public DataSourceProperties firstDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@Primary
@ConfigurationProperties("app.datasource.first.configuration")
public HikariDataSource firstDataSource(DataSourceProperties
firstDataSourceProperties) {
return
firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).b
uild();
}
@Bean
@ConfigurationProperties("app.datasource.second")
public DataSourceProperties secondDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties("app.datasource.second.configuration")
public BasicDataSource secondDataSource(
@Qualifier("secondDataSourceProperties") DataSourceProperties
secondDataSourceProperties) {
return
secondDataSourceProperties.initializeDataSourceBuilder().type(BasicDataSource.class).b
uild();
}
The preceding example configures two data sources on custom namespaces with the same logic as
Spring Boot would use in auto-configuration. Note that each configuration sub namespace provides
447
advanced settings based on the chosen implementation.
Spring Data can create implementations of @Repository interfaces of various flavors. Spring Boot
handles 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 need is to put the right Spring Data dependencies on your classpath.
There is a spring-boot-starter-data-jpa for JPA, spring-boot-starter-data-mongodb for Mongodb,
and various other starters for supported technologies. To get started, create some repository
interfaces to handle your @Entity objects.
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).
For more about Spring Data, see the Spring Data project page.
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, as
shown in the following example:
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@EntityScan(basePackageClasses = City.class)
public class MyApplication {
// ...
Spring Data JPA already provides some vendor-independent configuration options (such as those
for SQL logging), and Spring Boot exposes those options and a few more for Hibernate as external
configuration properties. Some of them are automatically detected according to the context so you
should not have to set them.
448
The dialect to use is detected by the JPA provider. If you prefer to set the dialect yourself, set the
spring.jpa.database-platform property.
The most common options to set are shown in the following example:
Properties
spring.jpa.hibernate.naming.physical-strategy=com.example.MyPhysicalNamingStrategy
spring.jpa.show-sql=true
Yaml
spring:
jpa:
hibernate:
naming:
physical-strategy: "com.example.MyPhysicalNamingStrategy"
show-sql: true
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.
Hibernate uses two different naming strategies to map names from the object model to the
corresponding database names. The fully qualified class name of the physical and the implicit
strategy implementations can be configured by setting the spring.jpa.hibernate.naming.physical-
strategy and spring.jpa.hibernate.naming.implicit-strategy properties, respectively. Alternatively,
if ImplicitNamingStrategy or PhysicalNamingStrategy beans are available in the application context,
Hibernate will be automatically configured to use them.
By default, Spring Boot configures the physical naming strategy with SpringPhysicalNamingStrategy.
This implementation provides the same table structure as Hibernate 4: all dots are replaced by
underscores and camel casing is replaced by underscores as well. Additionally, by default, all table
names are generated in lower case. For example, a TelephoneNumber entity is mapped to the
449
telephone_number table. If your schema requires mixed-case identifiers, define a custom
SpringPhysicalNamingStrategy bean, as shown in the following example:
import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyHibernateConfiguration {
@Bean
public CamelCaseToUnderscoresNamingStrategy caseSensitivePhysicalNamingStrategy()
{
return new CamelCaseToUnderscoresNamingStrategy() {
@Override
protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) {
return false;
}
};
}
If you prefer to use Hibernate 5’s default instead, set the following property:
spring.jpa.hibernate.naming.physical-
strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
450
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
class MyHibernateConfiguration {
@Bean
PhysicalNamingStrategyStandardImpl caseSensitivePhysicalNamingStrategy() {
return new PhysicalNamingStrategyStandardImpl();
}
Hibernate second-level cache can be configured for a range of cache providers. Rather than
configuring Hibernate to lookup the cache provider again, it is better to provide the one that is
available in the context whenever possible.
To do this with JCache, first make sure that org.hibernate:hibernate-jcache is available on the
classpath. Then, add a HibernatePropertiesCustomizer bean as shown in the following example:
import org.hibernate.cache.jcache.ConfigSettings;
import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyHibernateSecondLevelCacheConfiguration {
@Bean
public HibernatePropertiesCustomizer
hibernateSecondLevelCacheCustomizer(JCacheCacheManager cacheManager) {
return (properties) -> properties.put(ConfigSettings.CACHE_MANAGER,
cacheManager.getCacheManager());
}
This customizer will configure Hibernate to use the same CacheManager as the one that the
application uses. It is also possible to use separate CacheManager instances. For details, see the
Hibernate user guide.
451
17.7.8. Use Dependency Injection in Hibernate Components
By default, Spring Boot registers a BeanContainer implementation that uses the BeanFactory so that
converters and entity listeners can use regular dependency injection.
You can disable or tune this behavior by registering a HibernatePropertiesCustomizer that removes
or changes the hibernate.resource.beans.container property.
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 in the
presence of a bean of that type.
If you need to use JPA against multiple data sources, you likely need one EntityManagerFactory per
data source. The LocalContainerEntityManagerFactoryBean from Spring ORM allows you to configure
an EntityManagerFactory for your needs. You can also reuse JpaProperties to bind settings for each
EntityManagerFactory, as shown in the following example:
452
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
@Configuration(proxyBeanMethods = false)
public class MyEntityManagerFactoryConfiguration {
@Bean
@ConfigurationProperties("app.jpa.first")
public JpaProperties firstJpaProperties() {
return new JpaProperties();
}
@Bean
public LocalContainerEntityManagerFactoryBean firstEntityManagerFactory(DataSource
firstDataSource,
JpaProperties firstJpaProperties) {
EntityManagerFactoryBuilder builder =
createEntityManagerFactoryBuilder(firstJpaProperties);
return
builder.dataSource(firstDataSource).packages(Order.class).persistenceUnit("firstDs").b
uild();
}
private EntityManagerFactoryBuilder
createEntityManagerFactoryBuilder(JpaProperties jpaProperties) {
JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(jpaProperties);
return new EntityManagerFactoryBuilder(jpaVendorAdapter,
jpaProperties.getProperties(), null);
}
453
When you create a bean for LocalContainerEntityManagerFactoryBean yourself, any
customization that was applied during the creation of the auto-configured
LocalContainerEntityManagerFactoryBean is lost. For example, in case of Hibernate,
any properties under the spring.jpa.hibernate prefix will not be automatically
NOTE
applied to your LocalContainerEntityManagerFactoryBean. If you were relying on
these properties for configuring things like the naming strategy or the DDL mode,
you will need to explicitly configure that when creating the
LocalContainerEntityManagerFactoryBean bean.
You should provide a similar configuration for any additional data sources for which you need JPA
access. To complete the picture, you need to configure a JpaTransactionManager for each
EntityManagerFactory as well. Alternatively, you might be able to use a JTA transaction manager that
spans both.
If you use Spring Data, you need to configure @EnableJpaRepositories accordingly, as shown in the
following examples:
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = Order.class, entityManagerFactoryRef =
"firstEntityManagerFactory")
public class OrderConfiguration {
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = Customer.class, entityManagerFactoryRef =
"secondEntityManagerFactory")
public class CustomerConfiguration {
Spring Boot will not search for or use a META-INF/persistence.xml by default. If you prefer to use a
traditional persistence.xml, you need to define your own @Bean of type
LocalEntityManagerFactoryBean (with an ID of ‘entityManagerFactory’) and set the persistence unit
name there.
454
17.7.12. Use Spring Data JPA and Mongo Repositories
Spring Data JPA and Spring Data Mongo can both automatically create Repository implementations
for you. If they are both present on the classpath, you might have to do some extra configuration to
tell Spring Boot which repositories to create. The most explicit way to do that is to use the standard
Spring Data @EnableJpaRepositories and @EnableMongoRepositories annotations and provide the
location of your Repository interfaces.
The same obstacle and the same features exist for other auto-configured Spring Data repository
types (Elasticsearch, Solr, and others). To work with them, change the names of the annotations and
flags accordingly.
Spring Data provides web support that simplifies the use of Spring Data repositories in a web
application. Spring Boot provides properties in the spring.data.web namespace for customizing its
configuration. Note that if you are using Spring Data REST, you must use the properties in the
spring.data.rest namespace instead.
Spring Data REST can expose the Repository implementations as REST endpoints for you, provided
Spring MVC has been enabled for the application.
Spring Boot exposes a set of useful properties (from the spring.data.rest namespace) that
customize the RepositoryRestConfiguration. If you need to provide additional customization, you
should use a RepositoryRestConfigurer bean.
If you want to configure a component that JPA uses, then you need to ensure that the component is
initialized before JPA. When the component is auto-configured, Spring Boot takes care of this for
you. For example, when Flyway is auto-configured, Hibernate is configured to depend upon Flyway
so that Flyway has a chance to initialize the database before Hibernate tries to use it.
455
import jakarta.persistence.EntityManagerFactory;
import
org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryDependsOnPostProces
sor;
import org.springframework.stereotype.Component;
/**
* {@link EntityManagerFactoryDependsOnPostProcessor} that ensures that
* {@link EntityManagerFactory} beans depend on the {@code elasticsearchClient} bean.
*/
@Component
public class ElasticsearchEntityManagerFactoryDependsOnPostProcessor
extends EntityManagerFactoryDependsOnPostProcessor {
public ElasticsearchEntityManagerFactoryDependsOnPostProcessor() {
super("elasticsearchClient");
}
If you need to use jOOQ with multiple data sources, you should create your own DSLContext for each
one. See JooqAutoConfiguration for more details.
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.
You can set spring.jpa.hibernate.ddl-auto explicitly and the standard Hibernate property values
456
are none, validate, update, create, and create-drop. Spring Boot chooses a default value for you
based on whether it thinks your database is embedded. It defaults to create-drop if no schema
manager has been detected or none in all other cases. An embedded database is detected by looking
at the Connection type and JDBC url. hsqldb, h2, and derby are candidates, and others are not. Be
careful when switching from in-memory to a ‘real’ database that you do not 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.
You can output the schema creation by enabling the org.hibernate.SQL logger. This
NOTE
is done for you automatically if you enable the debug mode.
In addition, a file named import.sql in the root of the classpath is 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 is probably not something you
want to be on the classpath in production. It is a Hibernate feature (and has nothing to do with
Spring).
Spring Boot can automatically create the schema (DDL scripts) of your JDBC DataSource or R2DBC
ConnectionFactory and initialize it (DML scripts). It loads SQL from the standard root classpath
locations: schema.sql and data.sql, respectively. In addition, Spring Boot processes the schema-
${platform}.sql and data-${platform}.sql files (if present), where platform is the value of
spring.sql.init.platform. This allows you to switch to database-specific scripts if necessary. For
example, you might choose to set it to the vendor name of the database (hsqldb, h2, oracle, mysql,
postgresql, and so on). By default, SQL database initialization is only performed when using an
embedded in-memory database. To always initialize an SQL database, irrespective of its type, set
spring.sql.init.mode to always. Similarly, to disable initialization, set spring.sql.init.mode to never.
By default, Spring Boot enables the fail-fast feature of its script-based database initializer. This
means that, if the scripts cause exceptions, the application fails to start. You can tune that behavior
by setting spring.sql.init.continue-on-error.
If you are using a Higher-level Database Migration Tool, like Flyway or Liquibase, you should use
them alone to create and initialize the schema. Using the basic schema.sql and data.sql scripts
alongside Flyway or Liquibase is not recommended and support will be removed in a future
release.
457
17.8.4. Initialize a Spring Batch Database
If you use Spring Batch, it comes pre-packaged with SQL initialization scripts for most popular
database platforms. Spring Boot can detect your database type and execute those scripts on startup.
If you use an embedded database, this happens by default. You can also enable it for any database
type, as shown in the following example:
Properties
spring.batch.jdbc.initialize-schema=always
Yaml
spring:
batch:
jdbc:
initialize-schema: "always"
You can also switch off the initialization explicitly by setting spring.batch.jdbc.initialize-schema to
never.
Spring Boot supports two higher-level migration tools: Flyway and Liquibase.
Typically, migrations are scripts in the form V<VERSION>__<NAME>.sql (with <VERSION> an underscore-
separated version, such as ‘1’ or ‘2_1’). By default, they are in a directory called
classpath:db/migration, but you can modify that location by setting spring.flyway.locations. This is
a comma-separated list of one or more classpath: or filesystem: locations. For example, the
following configuration would search for scripts in both the default classpath location and the
/opt/migration directory:
Properties
spring.flyway.locations=classpath:db/migration,filesystem:/opt/migration
Yaml
spring:
flyway:
locations: "classpath:db/migration,filesystem:/opt/migration"
You can also add a special {vendor} placeholder to use vendor-specific scripts. Assume the
458
following:
Properties
spring.flyway.locations=classpath:db/migration/{vendor}
Yaml
spring:
flyway:
locations: "classpath:db/migration/{vendor}"
Rather than using db/migration, the preceding configuration sets the directory to use according to
the type of the database (such as db/migration/mysql for MySQL). The list of supported databases is
available in DatabaseDriver.
Migrations can also be written in Java. Flyway will be auto-configured with any beans that
implement JavaMigration.
FlywayProperties provides most of Flyway’s settings and a small set of additional properties that can
be used to disable the migrations or switch off the location checking. If you need more control over
the configuration, consider registering a FlywayConfigurationCustomizer bean.
Spring Boot calls Flyway.migrate() to perform the database migration. If you would like more
control, provide a @Bean that implements FlywayMigrationStrategy.
Flyway supports SQL and Java callbacks. To use SQL-based callbacks, place the callback scripts in
the classpath:db/migration directory. To use Java-based callbacks, create one or more beans that
implement Callback. Any such beans are automatically registered with Flyway. They can be ordered
by using @Order or by implementing Ordered. Beans that implement the deprecated FlywayCallback
interface can also be detected, however they cannot be used alongside Callback beans.
By default, Flyway autowires the (@Primary) DataSource in your context and uses that for migrations.
If you like to use a different DataSource, you can create one and mark its @Bean as @FlywayDataSource.
If you do so and want two data sources, remember to create another one and mark it as @Primary.
Alternatively, you can use Flyway’s native DataSource by setting spring.flyway.[url,user,password]
in external properties. Setting either spring.flyway.url or spring.flyway.user is sufficient to cause
Flyway to use its own DataSource. If any of the three properties has not been set, the value of its
equivalent spring.datasource property will be used.
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 are run only when your application starts for
testing. Also, you can use profile-specific configuration to customize spring.flyway.locations so that
certain migrations run only when a particular profile is active. For example, in application-
dev.properties, you might specify the following setting:
459
Properties
spring.flyway.locations=classpath:/db/migration,classpath:/dev/db/migration
Yaml
spring:
flyway:
locations: "classpath:/db/migration,classpath:/dev/db/migration"
With that setup, migrations in dev/db/migration run only when the dev profile is active.
By default, the master change log is read from db/changelog/db.changelog-master.yaml, but you can
change the location by setting spring.liquibase.change-log. In addition to YAML, Liquibase also
supports JSON, XML, and SQL change log formats.
By default, Liquibase autowires the (@Primary) DataSource in your context and uses that for
migrations. If you need to use a different DataSource, you can create one and mark its @Bean as
@LiquibaseDataSource. If you do so and you want two data sources, remember to create another one
and mark it as @Primary. Alternatively, you can use Liquibase’s native DataSource by setting
spring.liquibase.[driver-class-name,url,user,password] in external properties. Setting either
spring.liquibase.url or spring.liquibase.user is sufficient to cause Liquibase to use its own
DataSource. If any of the three properties has not been set, the value of its equivalent
spring.datasource property will be used.
See LiquibaseProperties for details about available settings such as contexts, the default schema,
and others.
460
initialize the database and require the database to have been initialized.
Spring Boot will automatically detect beans of the following types that initialize an SQL database:
• DataSourceScriptDatabaseInitializer
• EntityManagerFactory
• Flyway
• FlywayMigrationInitializer
• R2dbcScriptDatabaseInitializer
• SpringLiquibase
If you are using a third-party starter for a database initialization library, it may provide a detector
such that beans of other types are also detected automatically. To have other beans be detected,
register an implementation of DatabaseInitializerDetector in META-INF/spring-factories.
Spring Boot will automatically detect beans of the following types that depends upon database
initialization:
• DSLContext (jOOQ)
• JdbcOperations
• NamedParameterJdbcOperations
If you are using a third-party starter data access library, it may provide a detector such that beans
of other types are also detected automatically. To have other beans be detected, register an
implementation of DependsOnDatabaseInitializationDetector in META-INF/spring-factories.
Alternatively, annotate the bean’s class or its @Bean method with @DependsOnDatabaseInitialization.
17.9. Messaging
Spring Boot offers a number of starters to support messaging. This section answers questions that
arise from using messaging with Spring Boot.
If your JMS broker does not support transacted sessions, you have to disable the support of
transactions altogether. If you create your own JmsListenerContainerFactory, there is nothing to do,
since, by default it cannot be transacted. If you want to use the
DefaultJmsListenerContainerFactoryConfigurer to reuse Spring Boot’s default, you can disable
transacted sessions, as follows:
461
import jakarta.jms.ConnectionFactory;
import
org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigure
r;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
@Configuration(proxyBeanMethods = false)
public class MyJmsConfiguration {
@Bean
public DefaultJmsListenerContainerFactory
jmsListenerContainerFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory listenerFactory = new
DefaultJmsListenerContainerFactory();
configurer.configure(listenerFactory, connectionFactory);
listenerFactory.setTransactionManager(null);
listenerFactory.setSessionTransacted(false);
return listenerFactory;
}
The preceding example overrides the default factory, and it should be applied to any other factory
that your application defines, if any.
By default, batch applications require a DataSource to store job details. Spring Batch expects a single
DataSource by default. To have it use a DataSource other than the application’s main DataSource,
declare a DataSource bean, annotating its @Bean method with @BatchDataSource. If you do so and want
two data sources, remember to mark the other one @Primary. To take greater control, implement
BatchConfigurer. See The Javadoc of @EnableBatchProcessing for more details.
For more info about Spring Batch, see the Spring Batch project page.
462
By default, it executes all Jobs in the application context on startup (see
JobLauncherApplicationRunner for details). You can narrow down to a specific job or jobs by
specifying spring.batch.job.names (which takes a comma-separated list of job name patterns).
Spring Boot converts any command line argument starting with -- to a property to add to the
Environment, see accessing command line properties. This should not be used to pass arguments to
batch jobs. To specify batch arguments on the command line, use the regular format (that is
without --), as shown in the following example:
If you specify a property of the Environment on the command line, it is ignored by the job. Consider
the following command:
Spring Batch requires a data store for the Job repository. If you use Spring Boot, you must use an
actual database. Note that it can be an in-memory database, see Configuring a Job Repository.
17.11. Actuator
Spring Boot includes the Spring Boot Actuator. This section answers questions that often arise from
its use.
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.server.port. To
listen on a completely different network address (such as when you have an internal network for
management and an external one for user applications), you can also set management.server.address
to a valid IP address to which the server is able to bind.
For more detail, see the ManagementServerProperties source code and “Customizing the Management
Server Port” in the “Production-ready features” section.
Spring Boot installs a ‘whitelabel’ error page that you see in a browser client if you encounter a
server error (machine clients consuming JSON and other media types should see a sensible
463
response with the right error code).
Overriding the error page with your own depends on the templating technology that you use. For
example, if you use Thymeleaf, you can add an error.html template. If you use FreeMarker, you can
add an error.ftlh template. In general, you need a View that resolves with a name of error 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 named error would
be one way of doing that. See ErrorMvcAutoConfiguration for more options.
See also the section on “Error Handling” for details of how to register handlers in the servlet
container.
Information returned by the env and configprops endpoints can be somewhat sensitive so keys
matching certain patterns are sanitized by default (that is their values are replaced by ******).
Spring Boot uses sensible defaults for such keys: any key ending with the word "password", "secret",
"key", "token", "vcap_services", "sun.java.command" is entirely sanitized. Additionally, any key that
holds the word credentials (configured as a regular expression, that is *credentials.*) as part of
the key is also entirely sanitized.
Furthermore, Spring Boot sanitizes the sensitive portion of URI-like values for keys with one of the
following endings:
• address
• addresses
• uri
• uris
• url
• urls
The default patterns used by the env and configprops endpoints can be replaced using
management.endpoint.env.keys-to-sanitize and management.endpoint.configprops.keys-to-sanitize
respectively. Alternatively, additional patterns can be configured using
management.endpoint.env.additional-keys-to-sanitize and
management.endpoint.configprops.additional-keys-to-sanitize.
464
17.11.4. Map Health Indicators to Micrometer Metrics
Spring Boot health indicators return a Status type to indicate the overall system health. If you want
to monitor or alert on levels of health for a particular application, you can export these statuses as
metrics with Micrometer. By default, the status codes “UP”, “DOWN”, “OUT_OF_SERVICE” and
“UNKNOWN” are used by Spring Boot. To export these, you will need to convert these states to some
set of numbers so that they can be used with a Micrometer Gauge.
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.health.Status;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyHealthMetricsExportConfiguration {
17.12. Security
This section addresses questions about security when working with Spring Boot, including
questions that arise from using Spring Security with Spring Boot.
For more about Spring Security, see the Spring Security project page.
465
17.12.1. Switch off the Spring Boot Security Configuration
The easiest way to add user accounts is to provide your own UserDetailsService bean.
Ensuring that all your main endpoints are only available over HTTPS is an important chore for any
application. If you use Tomcat as a servlet container, then Spring Boot adds 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, as shown in the following example:
Properties
server.tomcat.remoteip.remote-ip-header=x-forwarded-for
server.tomcat.remoteip.protocol-header=x-forwarded-proto
Yaml
server:
tomcat:
remoteip:
remote-ip-header: "x-forwarded-for"
protocol-header: "x-forwarded-proto"
(The presence of either of those properties switches on the valve. Alternatively, you can add the
RemoteIpValve by customizing the TomcatServletWebServerFactory using a WebServerFactoryCustomizer
bean.)
To configure Spring Security to require a secure channel for all (or some) requests, consider adding
your own SecurityFilterChain bean that adds the following HttpSecurity configuration:
466
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class MySecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception
{
// Customize the application security ...
http.requiresChannel().anyRequest().requiresSecure();
return http.build();
}
There are several options for hot reloading. The recommended approach is to use 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 (such as template
caching). Devtools works by monitoring the classpath for changes. This means that static resource
changes must be "built" for the change to take effect. By default, this happens automatically in
Eclipse when you save your changes. In IntelliJ IDEA, the Make Project command triggers the
necessary build. Due to the default restart exclusions, changes to static resources do not trigger a
restart of your application. They do, 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 allow hot-swapping of Java
class changes).
Finally, the 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.
Most of the templating technologies supported by Spring Boot include a configuration option to
disable caching (described later in this document). If you use the spring-boot-devtools module,
these properties are automatically configured for you at development time.
467
Thymeleaf Templates
If you use Thymeleaf, set spring.thymeleaf.cache to false. See ThymeleafAutoConfiguration for other
Thymeleaf customization options.
FreeMarker Templates
Groovy Templates
The spring-boot-devtools module includes support for automatic application restarts. While not as
fast as technologies such as JRebel it is usually significantly faster than a “cold start”. You should
probably give it a try before investigating some of the more complex reload options discussed later
in this document.
Many modern IDEs (Eclipse, IDEA, and others) support hot swapping of bytecode. Consequently, if
you make a change that does not affect class or method signatures, it should reload cleanly with no
side effects.
17.14. Testing
Spring Boot includes a number of testing utilities and support classes as well as a dedicated starter
that provides common test dependencies. This section answers common questions about testing.
Spring Security provides support for running tests as a specific user. For example, the test in the
snippet below will run with an authenticated user that has the ADMIN role.
468
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
@WebMvcTest(UserController.class)
class MySecurityTests {
@Autowired
private MockMvc mvc;
@Test
@WithMockUser(roles = "ADMIN")
void requestProtectedUrlWithUser() throws Exception {
this.mvc.perform(get("/"));
}
Spring Security provides comprehensive integration with Spring MVC Test and this can also be used
when testing controllers using the @WebMvcTest slice and MockMvc.
For additional details on Spring Security’s testing support, see Spring Security’s reference
documentation.
The Testcontainers library provides a way to manage services running inside Docker containers. It
integrates with JUnit, allowing you to write a test class that can start up a container before any of
the tests run. Testcontainers is especially useful for writing integration tests that talk to a real
backend service such as MySQL, MongoDB, Cassandra and others. Testcontainers can be used in a
Spring Boot test as follows:
469
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@Testcontainers
class MyIntegrationTests {
@Container
static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:4.2");
@Test
void myTest() {
// ...
}
This will start up a docker container running Neo4j (if Docker is running locally) before any of the
tests are run. In most cases, you will need to configure the application using details from the
running container, such as container IP or port.
This can be done with a static @DynamicPropertySource method that allows adding dynamic property
values to the Spring Environment.
470
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
@SpringBootTest
@Testcontainers
class MyIntegrationTests {
@Container
static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:4.2");
@Test
void myTest() {
// ...
}
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
}
The above configuration allows Neo4j-related beans in the application to communicate with Neo4j
running inside the Testcontainers-managed Docker container.
17.15. Build
Spring Boot includes build plugins for Maven and Gradle. This section answers common questions
about these plugins.
Both the Maven plugin and the Gradle plugin allow generating build information containing the
coordinates, name, and version of the project. The plugins can also be configured to add additional
properties through configuration. When such a file is present, Spring Boot auto-configures a
BuildProperties bean.
To generate build information with Maven, add an execution for the build-info goal, as shown in
the following example:
471
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.0.0-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
TIP See the Spring Boot Maven Plugin documentation for more details.
springBoot {
buildInfo()
}
TIP See the Spring Boot Gradle Plugin documentation for more details.
Both Maven and Gradle allow generating 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. To use it, add the following declaration for the Git Commit Id Plugin to your
POM:
<build>
<plugins>
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Gradle users can achieve the same result by using the gradle-git-properties plugin, as shown in the
472
following example:
plugins {
id "com.gorylenko.gradle-git-properties" version "2.3.2"
}
Both the Maven and Gradle plugins allow the properties that are included in git.properties to be
configured.
The commit time in git.properties is expected to match the following format: yyyy-MM-
dd’T’HH:mm:ssZ. This is the default format for both plugins listed above. Using this
TIP
format lets the time be parsed into a Date and its format, when serialized to JSON, to
be controlled by Jackson’s date serialization configuration settings.
The spring-boot-dependencies POM manages the versions of common dependencies. The Spring
Boot plugins for Maven and Gradle allow these managed dependency versions to be customized
using build properties.
Each Spring Boot release is designed and tested against this specific set of
WARNING
third-party dependencies. Overriding versions may cause compatibility issues.
To override dependency versions with Maven, see this section of the Maven plugin’s
documentation.
To override dependency versions in Gradle, see this section of the Gradle plugin’s documentation.
The spring-boot-maven-plugin can be used to create an executable “fat” JAR. If you use the spring-
boot-starter-parent POM, you can declare the plugin and your jars are repackaged as follows:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
If you do not use the parent POM, you can still use the plugin. However, you must additionally add
an <executions> section, as follows:
473
<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>
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 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 a dependency.
To configure a classifier of exec in Maven, you can use the following configuration:
474
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
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 when the executable jar first runs. Such nested jars are written beneath
the temporary directory identified by the java.io.tmpdir system property.
Care should be taken to ensure that your operating system is configured so that
WARNING it will not delete the jars that have been unpacked to the temporary directory
while the application is still running.
For example, to indicate that JRuby should be flagged for unpacking by using the Maven Plugin, you
would add the following configuration:
<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>
475
17.15.7. Create a Non-executable JAR with Exclusions
Often, if you have an executable and a non-executable jar as two separate build products, the
executable version has additional configuration files that are not needed in a library jar. For
example, the application.yml configuration file might be excluded from the non-executable JAR.
In Maven, the executable jar must be the main artifact and you can add a classified jar for the
library, as follows:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>lib</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>lib</classifier>
<excludes>
<exclude>application.yml</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
To attach a remote debugger to a Spring Boot application that was started with Maven, you can use
the jvmArguments property of the maven plugin.
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:
476
1. 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.
2. 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.
3. Add the provided (embedded container) dependencies in a nested BOOT-INF/lib directory for a
jar or WEB-INF/lib-provided for a war. Remember not to compress the entries in the archive.
4. Add the spring-boot-loader classes at the root of the archive (so that the Main-Class is available).
5. Use the appropriate launcher (such as JarLauncher for a jar file) as a Main-Class attribute in the
manifest and specify the other properties it needs as manifest entries — principally, by setting a
Start-Class property.
The following example shows how to build an executable archive with Ant:
477
17.16.1. Create a Deployable War File
Because Spring WebFlux does not strictly depend on the servlet API and
WARNING applications are deployed by default on an embedded Reactor Netty server,
War deployment is not supported for WebFlux applications.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return application.sources(MyApplication.class);
}
The next step is to update your build configuration such that your project produces a war file
rather than a jar file. If you use Maven and spring-boot-starter-parent (which configures Maven’s
war plugin for you), all you need to do is to modify pom.xml to change the packaging to war, as
follows:
<packaging>war</packaging>
If you use Gradle, you need to modify build.gradle to apply the war plugin to the project, as follows:
The final step in the process is to ensure that the embedded servlet container does not interfere
with the servlet container to which the war file is deployed. To do so, you need to mark the
embedded servlet container dependency as being provided.
478
If you use Maven, the following example marks the servlet container (Tomcat, in this case) as being
provided:
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- ... -->
</dependencies>
If you use Gradle, the following example marks the servlet container (Tomcat, in this case) as being
provided:
dependencies {
// ...
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
// ...
}
If you use the Spring Boot build tools, marking the embedded servlet container dependency as
provided produces 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 by using java -jar on the command line.
To convert an existing non-web Spring application to a Spring Boot application, replace 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 or jar. See the Getting
Started Guide on Converting a jar to a war.
479
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class MyApplication 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 do not need to override this method.
return application;
}
Remember that, whatever you put in the sources is merely a Spring ApplicationContext. 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 before you need to do that.
Static resources can be moved to /public (or /static or /resources or /META-INF/resources) in the
classpath root. The same applies to messages.properties (which Spring Boot automatically detects 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 (for instance, using other servlets or filters), you may
need to add some configuration to your Application context, by replacing those elements from the
web.xml, as follows:
• A @Bean of type Filter or FilterRegistrationBean behaves similarly (as a <filter/> and <filter-
mapping/>).
Once the war file is working, you can make it executable by adding a main method to your
Application, as shown in the following example:
480
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
import org.springframework.boot.Banner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import
org.springframework.boot.web.servlet.support.SpringBootServletInitialize
r;
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
@Override
NOTE
protected SpringApplicationBuilder
configure(SpringApplicationBuilder builder) {
return customizerBuilder(builder);
}
All of these should be amenable to translation, but each might require slightly different techniques.
Servlet 3.0+ applications might translate pretty easily if they already use the Spring Servlet 3.0+
481
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 (for example, if it uses AbstractDispatcherServletInitializer) then you might be
able to combine all your context sources into a single SpringApplication. The main complication you
might encounter is if combining does not work and you need to maintain the context hierarchy. See
the entry on building a hierarchy for examples. An existing parent context that contains web-
specific features usually needs 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 Spring Boot
applications, and the previously mentioned guidance may help. However, you may yet encounter
problems. In that case, we suggest asking questions on Stack Overflow with a tag of spring-boot.
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).
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.WebApplicationInitializer;
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer implements
WebApplicationInitializer {
If you use Logback, you also need to tell WebLogic to prefer the packaged version rather than the
version that was pre-installed with the server. You can do so by adding a WEB-INF/weblogic.xml file
with the following contents:
482
<?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>
483
Appendices
484
Appendix A: Common Application
Properties
Various properties can be specified inside your application.properties file, inside your
application.yml file, or as command line switches. This appendix provides a list of common Spring
Boot properties and references to the underlying classes that consume them.
Spring Boot provides various conversion mechanism with advanced value formatting,
TIP
make sure to review the properties conversion section.
Property contributions can come from additional jar files on your classpath, so you
NOTE should not consider this an exhaustive list. Also, you can define your own
properties.
485
Name Description Default Value
486
Name Description Default Value
487
Name Description Default Value
488
Name Description Default Value
489
Name Description Default Value
490
Name Description Default Value
spring.pid.fail-on-write-error Fails if
ApplicationPidFileWriter is
used but it cannot write the
PID file.
491
Name Description Default Value
492
Name Description Default Value
493
Name Description Default Value
494
Name Description Default Value
495
Name Description Default Value
496
Name Description Default Value
497
Name Description Default Value
498
Name Description Default Value
spring.data.cassandra.connection.conn 5s
ection-timeout
499
Name Description Default Value
500
Name Description Default Value
spring.data.elasticsearch.client.reac [localhost:9200]
tive.endpoints
501
Name Description Default Value
502
Name Description Default Value
503
Name Description Default Value
505
Name Description Default Value
spring.datasource.initialization-mode embedded
507
Name Description Default Value
509
Name Description Default Value
spring.elasticsearch.rest.uris [http://localhost:9200]
511
Name Description Default Value
spring.jpa.defer-datasource- false
initialization
512
Name Description Default Value
513
Name Description Default Value
514
Name Description Default Value
515
Name Description Default Value
516
Name Description Default Value
517
Name Description Default Value
518
Name Description Default Value
519
Name Description Default Value
520
Name Description Default Value
spring.jta.atomikos.connectionfactory Vendor-specific
.xa-connection-factory-class-name implementation of
XAConnectionFactory.
spring.jta.atomikos.connectionfactory Vendor-specific XA
.xa-properties properties.
521
Name Description Default Value
spring.jta.atomikos.datasource.xa- Vendor-specific
data-source-class-name implementation of
XAConnectionFactory.
spring.jta.atomikos.datasource.xa- Vendor-specific XA
properties properties.
522
Name Description Default Value
523
Name Description Default Value
524
Name Description Default Value
525
Name Description Default Value
526
Name Description Default Value
527
Name Description Default Value
528
Name Description Default Value
529
Name Description Default Value
530
Name Description Default Value
531
Name Description Default Value
532
Name Description Default Value
533
Name Description Default Value
534
Name Description Default Value
535
Name Description Default Value
536
Name Description Default Value
537
Name Description Default Value
spring.kafka.producer.acks Number of
acknowledgments the
producer requires the leader
to have received before
considering a request
complete.
538
Name Description Default Value
539
Name Description Default Value
540
Name Description Default Value
541
Name Description Default Value
542
Name Description Default Value
543
Name Description Default Value
544
Name Description Default Value
545
Name Description Default Value
546
Name Description Default Value
547
Name Description Default Value
548
Name Description Default Value
549
Name Description Default Value
550
Name Description Default Value
551
Name Description Default Value
552
Name Description Default Value
553
Name Description Default Value
554
Name Description Default Value
555
Name Description Default Value
spring.webflux.session.timeout 30m
556
Name Description Default Value
557
Name Description Default Value
spring.groovy.template.configuration. See
auto-escape GroovyMarkupConfigurer
spring.groovy.template.configuration.
auto-indent
spring.groovy.template.configuration.
auto-indent-string
spring.groovy.template.configuration.
auto-new-line
spring.groovy.template.configuration.
base-template-class
spring.groovy.template.configuration.
cache-templates
spring.groovy.template.configuration.
declaration-encoding
spring.groovy.template.configuration.
expand-empty-elements
spring.groovy.template.configuration.
locale
spring.groovy.template.configuration.
new-line-string
spring.groovy.template.configuration.
resource-loader-path
spring.groovy.template.configuration.
use-double-quotes
558
Name Description Default Value
559
Name Description Default Value
560
Name Description Default Value
561
Name Description Default Value
562
Name Description Default Value
563
Name Description Default Value
564
Name Description Default Value
server.servlet.encoding.charset
server.servlet.encoding.force
server.servlet.encoding.force-request
server.servlet.encoding.force-
response
server.servlet.encoding.mapping.*
565
Name Description Default Value
server.servlet.session.cookie.comment
server.servlet.session.cookie.domain
server.servlet.session.cookie.http-
only
server.servlet.session.cookie.max-age
server.servlet.session.cookie.name
server.servlet.session.cookie.path
server.servlet.session.cookie.same-
site
server.servlet.session.cookie.secure
566
Name Description Default Value
567
Name Description Default Value
568
Name Description Default Value
569
Name Description Default Value
570
Name Description Default Value
571
Name Description Default Value
572
Name Description Default Value
server.undertow.options.server.*
server.undertow.options.socket.*
573
A.12. Security Properties
Name Description Default Value
574
A.13. RSocket Properties
Name Description Default Value
spring.rsocket.server.ssl.ciphers
spring.rsocket.server.ssl.client-auth
spring.rsocket.server.ssl.enabled
spring.rsocket.server.ssl.enabled-
protocols
spring.rsocket.server.ssl.key-alias
spring.rsocket.server.ssl.key-
password
spring.rsocket.server.ssl.key-store
spring.rsocket.server.ssl.key-store-
password
spring.rsocket.server.ssl.key-store-
provider
spring.rsocket.server.ssl.key-store-
type
spring.rsocket.server.ssl.protocol
spring.rsocket.server.ssl.trust-store
spring.rsocket.server.ssl.trust-
store-password
spring.rsocket.server.ssl.trust-
store-provider
spring.rsocket.server.ssl.trust-
store-type
575
A.14. Actuator Properties
Name Description Default Value
576
Name Description Default Value
577
Name Description Default Value
578
Name Description Default Value
579
Name Description Default Value
580
Name Description Default Value
581
Name Description Default Value
582
Name Description Default Value
management.metrics.data.repository.au true
totime.enabled
management.metrics.data.repository.au
totime.percentiles
management.metrics.data.repository.au false
totime.percentiles-histogram
583
Name Description Default Value
584
Name Description Default Value
585
Name Description Default Value
586
Name Description Default Value
587
Name Description Default Value
588
Name Description Default Value
589
Name Description Default Value
590
Name Description Default Value
591
Name Description Default Value
592
Name Description Default Value
593
Name Description Default Value
594
Name Description Default Value
595
Name Description Default Value
596
Name Description Default Value
597
Name Description Default Value
598
Name Description Default Value
management.metrics.export.wavefront.s 1s
ender.flush-interval
management.metrics.export.wavefront.s 50000
ender.max-queue-size
management.metrics.export.wavefront.s
ender.message-size
599
Name Description Default Value
600
Name Description Default Value
601
Name Description Default Value
602
Name Description Default Value
603
Name Description Default Value
604
Appendix B: Configuration Metadata
Spring Boot jars include metadata files that provide details of all supported configuration
properties. The files are designed to let IDE developers offer contextual help and “code completion”
as users are working with application.properties or application.yml files.
The majority of the metadata file is generated automatically at compile time by processing all items
annotated with @ConfigurationProperties. However, it is possible to write part of the metadata
manually for corner cases or more advanced use cases.
{"groups": [
{
"name": "server",
"type": "org.springframework.boot.autoconfigure.web.ServerProperties",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},
{
"name": "spring.jpa.hibernate",
"type":
"org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate",
"sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties",
"sourceMethod": "getHibernate()"
}
...
],"properties": [
{
"name": "server.port",
"type": "java.lang.Integer",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},
{
"name": "server.address",
"type": "java.net.InetAddress",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},
{
"name": "spring.jpa.hibernate.ddl-auto",
"type": "java.lang.String",
"description": "DDL mode. This is actually a shortcut for the
\"hibernate.hbm2ddl.auto\" property.",
"sourceType":
"org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate"
}
605
...
],"hints": [
{
"name": "spring.jpa.hibernate.ddl-auto",
"values": [
{
"value": "none",
"description": "Disable DDL handling."
},
{
"value": "validate",
"description": "Validate the schema, make no changes to the database."
},
{
"value": "update",
"description": "Update the schema if necessary."
},
{
"value": "create",
"description": "Create the schema and destroy previous data."
},
{
"value": "create-drop",
"description": "Create and then destroy the schema at the end of the
session."
}
]
}
]}
Each “property” is a configuration item that the user specifies with a given value. For example,
server.port and server.address might be specified in your application.properties/application.yaml,
as follows:
Properties
server.port=9090
server.address=127.0.0.1
Yaml
server:
port: 9090
address: 127.0.0.1
The “groups” are higher level items that do not themselves specify a value but instead provide a
contextual grouping for properties. For example, the server.port and server.address properties are
part of the server group.
606
It is not required that every “property” has a “group”. Some properties might exist
NOTE
in their own right.
Finally, “hints” are additional information used to assist the user in configuring a given property.
For example, when a developer is configuring the spring.jpa.hibernate.ddl-auto property, a tool
can use the hints to offer some auto-completion help for the none, validate, update, create, and
create-drop values.
The JSON object contained in the groups array can contain the attributes shown in the following
table:
The JSON object contained in the properties array can contain the attributes described in the
following table:
607
Name Type Purpose
name String The full name of the property. Names are in lower-case period-
separated form (for example, server.address). This attribute is
mandatory.
type String The full signature of the data type of the property (for example,
java.lang.String) but also a full generic type (such as
java.util.Map<java.lang.String,com.example.MyEnum>). You can
use this attribute to guide the user as to the types of values that
they can enter. For consistency, the type of a primitive is
specified by using its wrapper counterpart (for example, boolean
becomes java.lang.Boolean). Note that this class may be a
complex type that gets converted from a String as values are
bound. If the type is not known, it may be omitted.
description String A short description of the property that can be displayed to users.
If no description is available, it may be omitted. It is
recommended that descriptions be short paragraphs, with the
first line providing a concise summary. The last line in the
description should end with a period (.).
sourceType String The class name of the source that contributed this property. For
example, if the property were from a class annotated with
@ConfigurationProperties, this attribute would contain the fully
qualified name of that class. If the source type is unknown, it
may be omitted.
defaultValue Object The default value, which is used if the property is not specified. If
the type of the property is an array, it can be an array of value(s).
If the default value is unknown, it may be omitted.
deprecation Deprecation Specify whether the property is deprecated. If the field is not
deprecated or if that information is not known, it may be
omitted. The next table offers more detail about the deprecation
attribute.
The JSON object contained in the deprecation attribute of each properties element can contain the
following attributes:
608
Name Type Purpose
reason String A short description of the reason why the property was
deprecated. If no reason is available, it may be omitted. It is
recommended that descriptions be short paragraphs, with the
first line providing a concise summary. The last line in the
description should end with a period (.).
replacement String The full name of the property that replaces this deprecated
property. If there is no replacement for this property, it may be
omitted.
Prior to Spring Boot 1.3, a single deprecated boolean attribute can be used instead of
the deprecation element. This is still supported in a deprecated fashion and should
NOTE
no longer be used. If no reason and replacement are available, an empty
deprecation object should be set.
609
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
@ConfigurationProperties("my.app")
public class MyProperties {
@Deprecated
@DeprecatedConfigurationProperty(replacement = "my.app.name")
public String getTarget() {
return this.name;
}
@Deprecated
public void setTarget(String target) {
this.name = target;
}
There is no way to set a level. warning is always assumed, since code is still handling
NOTE
the property.
The preceding code makes sure that the deprecated property still works (delegating to the name
property behind the scenes). Once the getTarget and setTarget methods can be removed from your
public API, the automatic deprecation hint in the metadata goes away as well. If you want to keep a
hint, adding manual metadata with an error deprecation level ensures that users are still informed
about that property. Doing so is particularly useful when a replacement is provided.
The JSON object contained in the hints array can contain the attributes shown in the following
table:
610
Name Type Purpose
name String The full name of the property to which this hint refers. Names
are in lower-case period-separated form (such as
spring.mvc.servlet.path). If the property refers to a map (such as
system.contexts), the hint either applies to the keys of the map
(system.contexts.keys) or the values (system.contexts.values) of
the map. This attribute is mandatory.
values ValueHint[] A list of valid values as defined by the ValueHint object (described
in the next table). Each entry defines the value and may have a
description.
providers ValueProvider[ A list of providers as defined by the ValueProvider object
] (described later in this document). Each entry defines the name
of the provider and its parameters, if any.
The JSON object contained in the values attribute of each hint element can contain the attributes
described in the following table:
The JSON object contained in the providers attribute of each hint element can contain the attributes
described in the following table:
Objects with the same “property” and “group” name can appear multiple times within a metadata
file. For example, you could bind two separate classes to the same prefix, with each having
potentially overlapping property names. While the same names appearing in the metadata multiple
times should not be common, consumers of metadata should take care to ensure that they support
it.
611
B.2. Providing Manual Hints
To improve the user experience and further assist the user in configuring a given property, you can
provide additional metadata that:
• Associates a provider, to attach a well defined semantic to a property, so that a tool can discover
the list of potential values based on the project’s context.
The name attribute of each hint refers to the name of a property. In the initial example shown earlier,
we provide five values for the spring.jpa.hibernate.ddl-auto property: none, validate, update,
create, and create-drop. Each value may have a description as well.
If your property is of type Map, you can provide hints for both the keys and the values (but not for
the map itself). The special .keys and .values suffixes must refer to the keys and the values,
respectively.
Assume a my.contexts maps magic String values to an integer, as shown in the following example:
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my")
public class MyProperties {
The magic values are (in this example) are sample1 and sample2. In order to offer additional content
assistance for the keys, you could add the following JSON to the manual metadata of the module:
612
{"hints": [
{
"name": "my.contexts.keys",
"values": [
{
"value": "sample1"
},
{
"value": "sample2"
}
]
}
]}
We recommend that you use an Enum for those two values instead. If your IDE supports
TIP
it, this is by far the most effective approach to auto-completion.
Providers are a powerful way to attach semantics to a property. In this section, we define the
official providers that you can use for your own hints. However, your favorite IDE may implement
some of these or none of them. Also, it could eventually provide its own.
As this is a new feature, IDE vendors must catch up with how it works. Adoption
NOTE
times naturally vary.
Name Description
any Permits any additional value to be provided.
class-reference Auto-completes the classes available in the project. Usually
constrained by a base class that is specified by the target
parameter.
handle-as Handles the property as if it were defined by the type defined by
the mandatory target parameter.
logger-name Auto-completes valid logger names and logger groups. Typically,
package and class names available in the current project can be
auto-completed as well as defined groups.
spring-bean-reference Auto-completes the available bean names in the current project.
Usually constrained by a base class that is specified by the target
parameter.
spring-profile-name Auto-completes the available Spring profile names in the project.
613
Only one provider can be active for a given property, but you can specify several
providers if they can all manage the property in some way. Make sure to place the
TIP most powerful provider first, as the IDE must use the first one in the JSON section that
it can handle. If no provider for a given property is supported, no special content
assistance is provided, either.
Any
The special any provider value permits any additional values to be provided. Regular value
validation based on the property type should be applied if this is supported.
This provider is typically used if you have a list of values and any extra values should still be
considered as valid.
The following example offers on and off as auto-completion values for system.state:
{"hints": [
{
"name": "system.state",
"values": [
{
"value": "on"
},
{
"value": "off"
}
],
"providers": [
{
"name": "any"
}
]
}
]}
Note that, in the preceding example, any other value is also allowed.
Class Reference
The class-reference provider auto-completes classes available in the project. This provider
supports the following parameters:
614
Parameter Type Default value Description
target String none The fully qualified name of the class that should
(Class) be assignable to the chosen value. Typically used
to filter out-non candidate classes. Note that this
information can be provided by the type itself by
exposing a class with the appropriate upper
bound.
concrete boolean true Specify whether only concrete classes are to be
considered as valid candidates.
{"hints": [
{
"name": "server.servlet.jsp.class-name",
"providers": [
{
"name": "class-reference",
"parameters": {
"target": "jakarta.servlet.http.HttpServlet"
}
}
]
}
]}
Handle As
The handle-as provider lets you substitute the type of the property to a more high-level type. This
typically happens when the property has a java.lang.String type, because you do not want your
configuration classes to rely on classes that may not be on the classpath. This provider supports the
following parameters:
• Any java.lang.Enum: Lists the possible values for the property. (We recommend defining the
property with the Enum type, as no further hint should be required for the IDE to auto-complete
the values)
615
text/plain)
If multiple values can be provided, use a Collection or Array type to teach the IDE
TIP
about it.
{"hints": [
{
"name": "spring.liquibase.change-log",
"providers": [
{
"name": "handle-as",
"parameters": {
"target": "org.springframework.core.io.Resource"
}
}
]
}
]}
Logger Name
The logger-name provider auto-completes valid logger names and logger groups. Typically,
package and class names available in the current project can be auto-completed. If groups are
enabled (default) and if a custom logger group is identified in the configuration, auto-completion
for it should be provided. Specific frameworks may have extra magic logger names that can be
supported as well.
Since a logger name can be any arbitrary name, this provider should allow any value but could
highlight valid package and class names that are not available in the project’s classpath.
The following metadata snippet corresponds to the standard logging.level property. Keys are
logger names, and values correspond to the standard log levels or any custom level. As Spring Boot
defines a few logger groups out-of-the-box, dedicated value hints have been added for those.
616
{"hints": [
{
"name": "logging.level.keys",
"values": [
{
"value": "root",
"description": "Root logger used to assign the default logging level."
},
{
"value": "sql",
"description": "SQL logging group including Hibernate SQL logger."
},
{
"value": "web",
"description": "Web logging group including codecs."
}
],
"providers": [
{
"name": "logger-name"
}
]
},
{
"name": "logging.level.values",
"values": [
{
"value": "trace"
},
{
"value": "debug"
},
{
"value": "info"
},
{
"value": "warn"
},
{
"value": "error"
},
{
"value": "fatal"
},
{
"value": "off"
}
],
"providers": [
{
617
"name": "any"
}
]
}
]}
The spring-bean-reference provider auto-completes the beans that are defined in the
configuration of the current project. This provider supports the following parameters:
The following metadata snippet corresponds to the standard spring.jmx.server property that
defines the name of the MBeanServer bean to use:
{"hints": [
{
"name": "spring.jmx.server",
"providers": [
{
"name": "spring-bean-reference",
"parameters": {
"target": "javax.management.MBeanServer"
}
}
]
}
]}
The binder is not aware of the metadata. If you provide that hint, you still need to
NOTE transform the bean name into an actual Bean reference using by the
ApplicationContext.
The spring-profile-name provider auto-completes the Spring profiles that are defined in the
configuration of the current project.
The following metadata snippet corresponds to the standard spring.profiles.active property that
defines the name of the Spring profile(s) to enable:
618
{"hints": [
{
"name": "spring.profiles.active",
"providers": [
{
"name": "spring-profile-name"
}
]
}
]}
With Maven the dependency should be declared as optional, as shown in the following example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
}
compileJava.inputs.files(processResources)
This dependency ensures that the additional metadata is available when the annotation processor
runs during compilation.
619
If you are using AspectJ in your project, you need to make sure that the annotation
processor runs only once. There are several ways to do this. With Maven, you can
configure the maven-apt-plugin explicitly and add the dependency to the annotation
processor only there. You could also let the AspectJ plugin run all the processing
and disable annotation processing in the maven-compiler-plugin configuration, as
follows:
NOTE
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<proc>none</proc>
</configuration>
</plugin>
The processor picks up both classes and methods that are annotated with @ConfigurationProperties.
If the class is also annotated with @ConstructorBinding, a single constructor is expected and one
property is created per constructor parameter. Otherwise, properties are discovered through the
presence of standard getters and setters with special handling for collection and map types (that is
detected even if only a getter is present). The annotation processor also supports the use of the
@Data, @Value, @Getter, and @Setter lombok annotations.
620
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.server")
public class MyServerProperties {
/**
* Name of the server.
*/
private String name;
/**
* IP address to listen to.
*/
private String ip = "127.0.0.1";
/**
* Port to listener to.
*/
private int port = 9797;
This exposes three properties where my.server.name has no default and my.server.ip and
my.server.port defaults to "127.0.0.1" and 9797 respectively. The Javadoc on fields is used to
621
populate the description attribute. For instance, the description of my.server.ip is "IP address to
listen to.".
You should only use plain text with @ConfigurationProperties field Javadoc, since
NOTE
they are not processed before being added to the JSON.
The annotation processor applies a number of heuristics to extract the default value from the
source model. Default values have to be provided statically. In particular, do not refer to a constant
defined in another class. Also, the annotation processor cannot auto-detect default values for Enums
and Collectionss.
For cases where the default value could not be detected, manual metadata should be provided.
Consider the following example:
622
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.messaging")
public class MyMessagingProperties {
SIMPLE, DIRECT
}
In order to document default values for properties in the class above, you could add the following
content to the manual metadata of the module:
623
{"properties": [
{
"name": "my.messaging.addresses",
"defaultValue": ["a", "b"]
},
{
"name": "my.messaging.container-type",
"defaultValue": "simple"
}
]}
Only the name of the property is required to document additional metadata for
NOTE
existing properties.
Nested Properties
The annotation processor automatically considers inner classes as nested properties. Rather than
documenting the ip and port at the root of the namespace, we could create a sub-namespace for it.
Consider the updated example:
624
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.server")
public class MyServerProperties {
}
625
The preceding example produces metadata information for my.server.name, my.server.host.ip, and
my.server.host.port properties. You can use the @NestedConfigurationProperty annotation on a field
to indicate that a regular (non-inner) class should be treated as if it were nested.
This has no effect on collections and maps, as those types are automatically identified,
TIP
and a single metadata property is generated for each of them.
Spring Boot’s configuration file handling is quite flexible, and it is often the case that properties
may exist that are not bound to a @ConfigurationProperties bean. You may also need to tune some
attributes of an existing key. To support such cases and let you provide custom "hints", the
annotation processor automatically merges items from META-INF/additional-spring-configuration-
metadata.json into the main metadata file.
If you refer to a property that has been detected automatically, the description, default value, and
deprecation information are overridden, if specified. If the manual property declaration is not
identified in the current module, it is added as a new property.
626
Appendix C: Auto-configuration Classes
This appendix contains details of all of the auto-configuration classes provided by Spring Boot, with
links to documentation and source code. Remember to also look at the conditions report in your
application for more details of which features are switched on. (To do so, start the app with --debug
or -Ddebug or, in an Actuator application, use the conditions endpoint).
C.1. spring-boot-autoconfigure
The following auto-configuration classes are from the spring-boot-autoconfigure module:
627
Configuration Class Links
EmbeddedMongoAutoConfiguration javadoc
EmbeddedWebServerFactoryCustomizerAutoConfiguration javadoc
ErrorMvcAutoConfiguration javadoc
ErrorWebFluxAutoConfiguration javadoc
FlywayAutoConfiguration javadoc
FreeMarkerAutoConfiguration javadoc
GroovyTemplateAutoConfiguration javadoc
GsonAutoConfiguration javadoc
HazelcastAutoConfiguration javadoc
HazelcastJpaDependencyAutoConfiguration javadoc
HibernateJpaAutoConfiguration javadoc
HttpEncodingAutoConfiguration javadoc
HttpHandlerAutoConfiguration javadoc
HttpMessageConvertersAutoConfiguration javadoc
HypermediaAutoConfiguration javadoc
InfluxDbAutoConfiguration javadoc
IntegrationAutoConfiguration javadoc
JacksonAutoConfiguration javadoc
JdbcRepositoriesAutoConfiguration javadoc
JdbcTemplateAutoConfiguration javadoc
JmsAutoConfiguration javadoc
JmxAutoConfiguration javadoc
JndiConnectionFactoryAutoConfiguration javadoc
JndiDataSourceAutoConfiguration javadoc
JooqAutoConfiguration javadoc
JpaRepositoriesAutoConfiguration javadoc
JsonbAutoConfiguration javadoc
JtaAutoConfiguration javadoc
KafkaAutoConfiguration javadoc
LdapAutoConfiguration javadoc
LdapRepositoriesAutoConfiguration javadoc
LifecycleAutoConfiguration javadoc
LiquibaseAutoConfiguration javadoc
628
Configuration Class Links
MailSenderAutoConfiguration javadoc
MailSenderValidatorAutoConfiguration javadoc
MessageSourceAutoConfiguration javadoc
MongoAutoConfiguration javadoc
MongoDataAutoConfiguration javadoc
MongoReactiveAutoConfiguration javadoc
MongoReactiveDataAutoConfiguration javadoc
MongoReactiveRepositoriesAutoConfiguration javadoc
MongoRepositoriesAutoConfiguration javadoc
MultipartAutoConfiguration javadoc
MustacheAutoConfiguration javadoc
Neo4jAutoConfiguration javadoc
Neo4jDataAutoConfiguration javadoc
Neo4jReactiveDataAutoConfiguration javadoc
Neo4jReactiveRepositoriesAutoConfiguration javadoc
Neo4jRepositoriesAutoConfiguration javadoc
NettyAutoConfiguration javadoc
OAuth2ClientAutoConfiguration javadoc
OAuth2ResourceServerAutoConfiguration javadoc
PersistenceExceptionTranslationAutoConfiguration javadoc
ProjectInfoAutoConfiguration javadoc
PropertyPlaceholderAutoConfiguration javadoc
QuartzAutoConfiguration javadoc
R2dbcAutoConfiguration javadoc
R2dbcDataAutoConfiguration javadoc
R2dbcRepositoriesAutoConfiguration javadoc
R2dbcTransactionManagerAutoConfiguration javadoc
RSocketMessagingAutoConfiguration javadoc
RSocketRequesterAutoConfiguration javadoc
RSocketSecurityAutoConfiguration javadoc
RSocketServerAutoConfiguration javadoc
RSocketStrategiesAutoConfiguration javadoc
RabbitAutoConfiguration javadoc
629
Configuration Class Links
ReactiveElasticsearchRepositoriesAutoConfiguration javadoc
ReactiveElasticsearchRestClientAutoConfiguration javadoc
ReactiveMultipartAutoConfiguration javadoc
ReactiveOAuth2ClientAutoConfiguration javadoc
ReactiveOAuth2ResourceServerAutoConfiguration javadoc
ReactiveSecurityAutoConfiguration javadoc
ReactiveUserDetailsServiceAutoConfiguration javadoc
ReactiveWebServerFactoryAutoConfiguration javadoc
RedisAutoConfiguration javadoc
RedisReactiveAutoConfiguration javadoc
RedisRepositoriesAutoConfiguration javadoc
RepositoryRestMvcAutoConfiguration javadoc
RestTemplateAutoConfiguration javadoc
Saml2RelyingPartyAutoConfiguration javadoc
SecurityAutoConfiguration javadoc
SecurityFilterAutoConfiguration javadoc
SendGridAutoConfiguration javadoc
ServletWebServerFactoryAutoConfiguration javadoc
SessionAutoConfiguration javadoc
SolrAutoConfiguration javadoc
SpringApplicationAdminJmxAutoConfiguration javadoc
SpringDataWebAutoConfiguration javadoc
SqlInitializationAutoConfiguration javadoc
TaskExecutionAutoConfiguration javadoc
TaskSchedulingAutoConfiguration javadoc
ThymeleafAutoConfiguration javadoc
TransactionAutoConfiguration javadoc
UserDetailsServiceAutoConfiguration javadoc
ValidationAutoConfiguration javadoc
WebClientAutoConfiguration javadoc
WebFluxAutoConfiguration javadoc
WebMvcAutoConfiguration javadoc
WebServiceTemplateAutoConfiguration javadoc
630
Configuration Class Links
WebServicesAutoConfiguration javadoc
WebSessionIdResolverAutoConfiguration javadoc
WebSocketMessagingAutoConfiguration javadoc
WebSocketReactiveAutoConfiguration javadoc
WebSocketServletAutoConfiguration javadoc
XADataSourceAutoConfiguration javadoc
C.2. spring-boot-actuator-autoconfigure
The following auto-configuration classes are from the spring-boot-actuator-autoconfigure module:
631
Configuration Class Links
DynatraceMetricsExportAutoConfiguration javadoc
ElasticMetricsExportAutoConfiguration javadoc
ElasticSearchReactiveHealthContributorAutoConfiguration javadoc
ElasticSearchRestHealthContributorAutoConfiguration javadoc
EndpointAutoConfiguration javadoc
EnvironmentEndpointAutoConfiguration javadoc
FlywayEndpointAutoConfiguration javadoc
GangliaMetricsExportAutoConfiguration javadoc
GraphiteMetricsExportAutoConfiguration javadoc
HazelcastHealthContributorAutoConfiguration javadoc
HealthContributorAutoConfiguration javadoc
HealthEndpointAutoConfiguration javadoc
HeapDumpWebEndpointAutoConfiguration javadoc
HttpClientMetricsAutoConfiguration javadoc
HttpTraceAutoConfiguration javadoc
HttpTraceEndpointAutoConfiguration javadoc
HumioMetricsExportAutoConfiguration javadoc
InfluxDbHealthContributorAutoConfiguration javadoc
InfluxMetricsExportAutoConfiguration javadoc
InfoContributorAutoConfiguration javadoc
InfoEndpointAutoConfiguration javadoc
IntegrationGraphEndpointAutoConfiguration javadoc
JettyMetricsAutoConfiguration javadoc
JmsHealthContributorAutoConfiguration javadoc
JmxEndpointAutoConfiguration javadoc
JmxMetricsExportAutoConfiguration javadoc
JvmMetricsAutoConfiguration javadoc
KafkaMetricsAutoConfiguration javadoc
KairosMetricsExportAutoConfiguration javadoc
LdapHealthContributorAutoConfiguration javadoc
LettuceMetricsAutoConfiguration javadoc
LiquibaseEndpointAutoConfiguration javadoc
Log4J2MetricsAutoConfiguration javadoc
632
Configuration Class Links
LogFileWebEndpointAutoConfiguration javadoc
LogbackMetricsAutoConfiguration javadoc
LoggersEndpointAutoConfiguration javadoc
MailHealthContributorAutoConfiguration javadoc
ManagementContextAutoConfiguration javadoc
ManagementWebSecurityAutoConfiguration javadoc
MappingsEndpointAutoConfiguration javadoc
MetricsAutoConfiguration javadoc
MetricsEndpointAutoConfiguration javadoc
MongoHealthContributorAutoConfiguration javadoc
MongoMetricsAutoConfiguration javadoc
MongoReactiveHealthContributorAutoConfiguration javadoc
Neo4jHealthContributorAutoConfiguration javadoc
NewRelicMetricsExportAutoConfiguration javadoc
PrometheusMetricsExportAutoConfiguration javadoc
QuartzEndpointAutoConfiguration javadoc
RabbitHealthContributorAutoConfiguration javadoc
RabbitMetricsAutoConfiguration javadoc
ReactiveCloudFoundryActuatorAutoConfiguration javadoc
ReactiveManagementContextAutoConfiguration javadoc
ReactiveManagementWebSecurityAutoConfiguration javadoc
RedisHealthContributorAutoConfiguration javadoc
RedisReactiveHealthContributorAutoConfiguration javadoc
RepositoryMetricsAutoConfiguration javadoc
ScheduledTasksEndpointAutoConfiguration javadoc
ServletManagementContextAutoConfiguration javadoc
SessionsEndpointAutoConfiguration javadoc
ShutdownEndpointAutoConfiguration javadoc
SignalFxMetricsExportAutoConfiguration javadoc
SimpleMetricsExportAutoConfiguration javadoc
SolrHealthContributorAutoConfiguration javadoc
StackdriverMetricsExportAutoConfiguration javadoc
StartupEndpointAutoConfiguration javadoc
633
Configuration Class Links
StartupTimeMetricsListenerAutoConfiguration javadoc
StatsdMetricsExportAutoConfiguration javadoc
SystemMetricsAutoConfiguration javadoc
TaskExecutorMetricsAutoConfiguration javadoc
ThreadDumpEndpointAutoConfiguration javadoc
TomcatMetricsAutoConfiguration javadoc
WavefrontMetricsExportAutoConfiguration javadoc
WebEndpointAutoConfiguration javadoc
WebFluxMetricsAutoConfiguration javadoc
WebMvcMetricsAutoConfiguration javadoc
634
Appendix D: Test Auto-configuration
Annotations
This appendix describes the @…Test auto-configuration annotations that Spring Boot provides to
test slices of your application.
@DataJdbcTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.data.jd
bc.JdbcRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.flyway.
FlywayAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Da
taSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Da
taSourceTransactionManagerAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Jd
bcTemplateAutoConfiguration
org.springframework.boot.autoconfigure.liquiba
se.LiquibaseAutoConfiguration
org.springframework.boot.autoconfigure.sql.ini
t.SqlInitializationAutoConfiguration
org.springframework.boot.autoconfigure.transac
tion.TransactionAutoConfiguration
org.springframework.boot.test.autoconfigure.jd
bc.TestDatabaseAutoConfiguration
635
Test slice Imported auto-configuration
@DataJpaTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.data.jp
a.JpaRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.flyway.
FlywayAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Da
taSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Da
taSourceTransactionManagerAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Jd
bcTemplateAutoConfiguration
org.springframework.boot.autoconfigure.liquiba
se.LiquibaseAutoConfiguration
org.springframework.boot.autoconfigure.orm.jpa
.HibernateJpaAutoConfiguration
org.springframework.boot.autoconfigure.sql.ini
t.SqlInitializationAutoConfiguration
org.springframework.boot.autoconfigure.transac
tion.TransactionAutoConfiguration
org.springframework.boot.test.autoconfigure.jd
bc.TestDatabaseAutoConfiguration
org.springframework.boot.test.autoconfigure.or
m.jpa.TestEntityManagerAutoConfiguration
@DataLdapTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.data.ld
ap.LdapRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.ldap.Ld
apAutoConfiguration
org.springframework.boot.autoconfigure.ldap.em
bedded.EmbeddedLdapAutoConfiguration
636
Test slice Imported auto-configuration
@DataMongoTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.data.mo
ngo.MongoDataAutoConfiguration
org.springframework.boot.autoconfigure.data.mo
ngo.MongoReactiveDataAutoConfiguration
org.springframework.boot.autoconfigure.data.mo
ngo.MongoReactiveRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.mo
ngo.MongoRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.mongo.M
ongoAutoConfiguration
org.springframework.boot.autoconfigure.mongo.M
ongoReactiveAutoConfiguration
org.springframework.boot.autoconfigure.mongo.e
mbedded.EmbeddedMongoAutoConfiguration
org.springframework.boot.autoconfigure.transac
tion.TransactionAutoConfiguration
@DataNeo4jTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.data.ne
o4j.Neo4jDataAutoConfiguration
org.springframework.boot.autoconfigure.data.ne
o4j.Neo4jReactiveDataAutoConfiguration
org.springframework.boot.autoconfigure.data.ne
o4j.Neo4jReactiveRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.ne
o4j.Neo4jRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.neo4j.N
eo4jAutoConfiguration
org.springframework.boot.autoconfigure.transac
tion.TransactionAutoConfiguration
@DataR2dbcTest org.springframework.boot.autoconfigure.data.r2
dbc.R2dbcDataAutoConfiguration
org.springframework.boot.autoconfigure.data.r2
dbc.R2dbcRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.flyway.
FlywayAutoConfiguration
org.springframework.boot.autoconfigure.liquiba
se.LiquibaseAutoConfiguration
org.springframework.boot.autoconfigure.r2dbc.R
2dbcAutoConfiguration
org.springframework.boot.autoconfigure.r2dbc.R
2dbcTransactionManagerAutoConfiguration
org.springframework.boot.autoconfigure.sql.ini
t.SqlInitializationAutoConfiguration
org.springframework.boot.autoconfigure.transac
tion.TransactionAutoConfiguration
637
Test slice Imported auto-configuration
@DataRedisTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.data.re
dis.RedisAutoConfiguration
org.springframework.boot.autoconfigure.data.re
dis.RedisReactiveAutoConfiguration
org.springframework.boot.autoconfigure.data.re
dis.RedisRepositoriesAutoConfiguration
@JdbcTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.flyway.
FlywayAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Da
taSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Da
taSourceTransactionManagerAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Jd
bcTemplateAutoConfiguration
org.springframework.boot.autoconfigure.liquiba
se.LiquibaseAutoConfiguration
org.springframework.boot.autoconfigure.sql.ini
t.SqlInitializationAutoConfiguration
org.springframework.boot.autoconfigure.transac
tion.TransactionAutoConfiguration
org.springframework.boot.test.autoconfigure.jd
bc.TestDatabaseAutoConfiguration
@JooqTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.flyway.
FlywayAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Da
taSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.Da
taSourceTransactionManagerAutoConfiguration
org.springframework.boot.autoconfigure.jooq.Jo
oqAutoConfiguration
org.springframework.boot.autoconfigure.liquiba
se.LiquibaseAutoConfiguration
org.springframework.boot.autoconfigure.sql.ini
t.SqlInitializationAutoConfiguration
org.springframework.boot.autoconfigure.transac
tion.TransactionAutoConfiguration
638
Test slice Imported auto-configuration
@JsonTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.gson.Gs
onAutoConfiguration
org.springframework.boot.autoconfigure.jackson
.JacksonAutoConfiguration
org.springframework.boot.autoconfigure.jsonb.J
sonbAutoConfiguration
org.springframework.boot.test.autoconfigure.js
on.JsonTestersAutoConfiguration
@RestClientTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.gson.Gs
onAutoConfiguration
org.springframework.boot.autoconfigure.http.Ht
tpMessageConvertersAutoConfiguration
org.springframework.boot.autoconfigure.http.co
dec.CodecsAutoConfiguration
org.springframework.boot.autoconfigure.jackson
.JacksonAutoConfiguration
org.springframework.boot.autoconfigure.jsonb.J
sonbAutoConfiguration
org.springframework.boot.autoconfigure.web.cli
ent.RestTemplateAutoConfiguration
org.springframework.boot.autoconfigure.web.rea
ctive.function.client.WebClientAutoConfigurati
on
org.springframework.boot.test.autoconfigure.we
b.client.MockRestServiceServerAutoConfiguratio
n
org.springframework.boot.test.autoconfigure.we
b.client.WebClientRestTemplateAutoConfiguratio
n
639
Test slice Imported auto-configuration
@WebFluxTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.context
.MessageSourceAutoConfiguration
org.springframework.boot.autoconfigure.freemar
ker.FreeMarkerAutoConfiguration
org.springframework.boot.autoconfigure.gson.Gs
onAutoConfiguration
org.springframework.boot.autoconfigure.http.co
dec.CodecsAutoConfiguration
org.springframework.boot.autoconfigure.jackson
.JacksonAutoConfiguration
org.springframework.boot.autoconfigure.jsonb.J
sonbAutoConfiguration
org.springframework.boot.autoconfigure.mustach
e.MustacheAutoConfiguration
org.springframework.boot.autoconfigure.securit
y.oauth2.client.reactive.ReactiveOAuth2ClientA
utoConfiguration
org.springframework.boot.autoconfigure.securit
y.oauth2.resource.reactive.ReactiveOAuth2Resou
rceServerAutoConfiguration
org.springframework.boot.autoconfigure.securit
y.reactive.ReactiveSecurityAutoConfiguration
org.springframework.boot.autoconfigure.securit
y.reactive.ReactiveUserDetailsServiceAutoConfi
guration
org.springframework.boot.autoconfigure.thymele
af.ThymeleafAutoConfiguration
org.springframework.boot.autoconfigure.validat
ion.ValidationAutoConfiguration
org.springframework.boot.autoconfigure.web.rea
ctive.WebFluxAutoConfiguration
org.springframework.boot.autoconfigure.web.rea
ctive.error.ErrorWebFluxAutoConfiguration
org.springframework.boot.test.autoconfigure.we
b.reactive.WebTestClientAutoConfiguration
640
Test slice Imported auto-configuration
@WebMvcTest org.springframework.boot.autoconfigure.cache.C
acheAutoConfiguration
org.springframework.boot.autoconfigure.context
.MessageSourceAutoConfiguration
org.springframework.boot.autoconfigure.data.we
b.SpringDataWebAutoConfiguration
org.springframework.boot.autoconfigure.freemar
ker.FreeMarkerAutoConfiguration
org.springframework.boot.autoconfigure.groovy.
template.GroovyTemplateAutoConfiguration
org.springframework.boot.autoconfigure.gson.Gs
onAutoConfiguration
org.springframework.boot.autoconfigure.hateoas
.HypermediaAutoConfiguration
org.springframework.boot.autoconfigure.http.Ht
tpMessageConvertersAutoConfiguration
org.springframework.boot.autoconfigure.jackson
.JacksonAutoConfiguration
org.springframework.boot.autoconfigure.jsonb.J
sonbAutoConfiguration
org.springframework.boot.autoconfigure.mustach
e.MustacheAutoConfiguration
org.springframework.boot.autoconfigure.securit
y.oauth2.client.servlet.OAuth2ClientAutoConfig
uration
org.springframework.boot.autoconfigure.securit
y.oauth2.resource.servlet.OAuth2ResourceServer
AutoConfiguration
org.springframework.boot.autoconfigure.securit
y.servlet.SecurityAutoConfiguration
org.springframework.boot.autoconfigure.securit
y.servlet.SecurityFilterAutoConfiguration
org.springframework.boot.autoconfigure.securit
y.servlet.UserDetailsServiceAutoConfiguration
org.springframework.boot.autoconfigure.task.Ta
skExecutionAutoConfiguration
org.springframework.boot.autoconfigure.thymele
af.ThymeleafAutoConfiguration
org.springframework.boot.autoconfigure.validat
ion.ValidationAutoConfiguration
org.springframework.boot.autoconfigure.web.ser
vlet.HttpEncodingAutoConfiguration
org.springframework.boot.autoconfigure.web.ser
vlet.WebMvcAutoConfiguration
org.springframework.boot.autoconfigure.web.ser
vlet.error.ErrorMvcAutoConfiguration
org.springframework.boot.test.autoconfigure.we
b.reactive.WebTestClientAutoConfiguration
org.springframework.boot.test.autoconfigure.we
b.servlet.MockMvcAutoConfiguration
org.springframework.boot.test.autoconfigure.we
b.servlet.MockMvcSecurityConfiguration
org.springframework.boot.test.autoconfigure.we
b.servlet.MockMvcWebClientAutoConfiguration 641
Test slice Imported auto-configuration
@WebServiceClientTest org.springframework.boot.test.autoconfigure.we
org.springframework.boot.autoconfigure.cache.C
b.servlet.MockMvcWebDriverAutoConfiguration
acheAutoConfiguration
org.springframework.boot.autoconfigure.webserv
ices.client.WebServiceTemplateAutoConfiguratio
n
org.springframework.boot.test.autoconfigure.we
bservices.client.MockWebServiceServerAutoConfi
guration
org.springframework.boot.test.autoconfigure.we
bservices.client.WebServiceClientTemplateAutoC
onfiguration
@WebServiceServerTest org.springframework.boot.autoconfigure.webserv
ices.WebServicesAutoConfiguration
org.springframework.boot.test.autoconfigure.we
bservices.server.MockWebServiceClientAutoConfi
guration
642
Appendix E: The Executable Jar Format
The spring-boot-loader modules lets Spring Boot support executable jar and war files. If you use the
Maven plugin or the Gradle plugin, executable jars are automatically generated, and you generally
do not need to know the details of how they work.
If you need to create executable jars from a different build system or if you are just curious about
the underlying technology, this appendix provides some background.
To solve this problem, many developers use “shaded” jars. A shaded jar packages all classes, from
all jars, into a single “uber jar”. The problem with shaded jars is that it becomes hard to see which
libraries are actually in your application. It can also be problematic if the same filename is used
(but with different content) in multiple jars. Spring Boot takes a different approach and lets you
actually nest jars directly.
Spring Boot Loader-compatible jar files should be structured in the following way:
example.jar
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-BOOT-INF
+-classes
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
+-dependency1.jar
+-dependency2.jar
643
E.1.2. The Executable War File Structure
Spring Boot Loader-compatible war files should be structured in the following way:
example.war
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-WEB-INF
+-classes
| +-com
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
| +-dependency1.jar
| +-dependency2.jar
+-lib-provided
+-servlet-api.jar
+-dependency3.jar
Dependencies should be placed in a nested WEB-INF/lib directory. Any dependencies that are
required when running embedded but are not required when deploying to a traditional web
container should be placed in WEB-INF/lib-provided.
Spring Boot Loader-compatible jar and war archives can include additional index files under the
BOOT-INF/ directory. A classpath.idx file can be provided for both jars and wars, and it provides the
ordering that jars should be added to the classpath. The layers.idx file can be used only for jars,
and it allows a jar to be split into logical layers for Docker/OCI image creation.
Index files follow a YAML compatible syntax so that they can be easily parsed by third-party tools.
These files, however, are not parsed internally as YAML and they must be written in exactly the
formats described below in order to be used.
The classpath index file can be provided in BOOT-INF/classpath.idx. It provides a list of jar names
(including the directory) in the order that they should be added to the classpath. Each line must
start with dash space ("-·") and names must be in double quotes.
644
example.jar
|
+-META-INF
| +-...
+-BOOT-INF
+-classes
| +...
+-lib
+-dependency1.jar
+-dependency2.jar
- "BOOT-INF/lib/dependency2.jar"
- "BOOT-INF/lib/dependency1.jar"
The layers index file can be provided in BOOT-INF/layers.idx. It provides a list of layers and the
parts of the jar that should be contained within them. Layers are written in the order that they
should be added to the Docker/OCI image. Layers names are written as quoted strings prefixed with
dash space ("-·") and with a colon (":") suffix. Layer content is either a file or directory name
written as a quoted string prefixed by space space dash space ("··-·"). A directory name ends with
/, a file name does not. When a directory name is used it means that all files inside that directory
are in the same layer.
- "dependencies":
- "BOOT-INF/lib/dependency1.jar"
- "BOOT-INF/lib/dependency2.jar"
- "application":
- "BOOT-INF/classes/"
- "META-INF/"
645
myapp.jar
+-------------------+-------------------------+
| /BOOT-INF/classes | /BOOT-INF/lib/mylib.jar |
|+-----------------+||+-----------+----------+|
|| A.class ||| B.class | C.class ||
|+-----------------+||+-----------+----------+|
+-------------------+-------------------------+
^ ^ ^
0063 3452 3980
The preceding example shows how A.class can be found in /BOOT-INF/classes in myapp.jar at
position 0063. B.class from the nested jar can actually be found in myapp.jar at position 3452, and
C.class is at position 3980.
Armed with this information, we can load specific nested entries by seeking to the appropriate part
of the outer jar. We do not need to unpack the archive, and we do not need to read all entry data
into memory.
Spring Boot Loader strives to remain compatible with existing code and libraries.
org.springframework.boot.loader.jar.JarFile extends from java.util.jar.JarFile and should work
as a drop-in replacement. The getURL() method returns a URL that opens a connection compatible
with java.net.JarURLConnection and can be used with Java’s URLClassLoader.
There are three launcher subclasses (JarLauncher, WarLauncher, and PropertiesLauncher). Their
purpose is to load resources (.class files and so on) from nested jar files or war files in directories
(as opposed to those explicitly on the classpath). In the case of JarLauncher and WarLauncher, the
nested paths are fixed. JarLauncher looks in BOOT-INF/lib/, and WarLauncher looks in WEB-INF/lib/
and WEB-INF/lib-provided/. You can add extra jars in those locations if you want more. The
PropertiesLauncher looks in BOOT-INF/lib/ in your application archive by default. You can add
additional locations by setting an environment variable called LOADER_PATH or loader.path in
loader.properties (which is a comma-separated list of directories, archives, or directories within
archives).
You need to specify an appropriate Launcher as the Main-Class attribute of META-INF/MANIFEST.MF. The
actual class that you want to launch (that is, the class that contains a main method) should be
specified in the Start-Class attribute.
The following example shows a typical MANIFEST.MF for an executable jar file:
646
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.mycompany.project.MyApplication
Main-Class: org.springframework.boot.loader.WarLauncher
Start-Class: com.mycompany.project.MyApplication
You need not specify Class-Path entries in your manifest file. The classpath is
NOTE
deduced from the nested jars.
Key Purpose
loader.path Comma-separated Classpath, such as
lib,${HOME}/app/lib. Earlier entries take
precedence, like a regular -classpath on the
javac command line.
loader.home Used to resolve relative paths in loader.path. For
example, given loader.path=lib, then
${loader.home}/lib is a classpath location (along
with all jar files in that directory). This property
is also used to locate a loader.properties file, as
in the following example /opt/app It defaults to
${user.dir}.
loader.args Default arguments for the main method (space
separated).
loader.main Name of main class to launch (for example,
com.app.Application).
loader.config.name Name of properties file (for example, launcher).
It defaults to loader.
loader.config.location Path to properties file (for example,
classpath:loader.properties). It defaults to
loader.properties.
loader.system Boolean flag to indicate that all properties
should be added to System properties. It defaults
to false.
647
When specified as environment variables or manifest entries, the following names should be used:
Build plugins automatically move the Main-Class attribute to Start-Class when the fat
TIP jar is built. If you use that, specify the name of the class to launch by using the Main-
Class attribute and leaving out Start-Class.
• loader.properties is searched for in loader.home, then in the root of the classpath, and then in
classpath:/BOOT-INF/classes. The first location where a file with that name exists is used.
• loader.home is the directory location of an additional properties file (overriding the default) only
when loader.config.location is not specified.
• loader.path can contain directories (which are scanned recursively for jar and zip files), archive
paths, a directory within an archive that is scanned for jar files (for example,
dependencies.jar!/lib), or wildcard patterns (for the default JVM behavior). Archive paths can
be relative to loader.home or anywhere in the file system with a jar:file: prefix.
• loader.path (if empty) defaults to BOOT-INF/lib (meaning a local directory or a nested one if
running from an archive). Because of this, PropertiesLauncher behaves the same as JarLauncher
when no additional configuration is provided.
• loader.path can not be used to configure the location of loader.properties (the classpath used to
search for the latter is the JVM classpath when PropertiesLauncher is launched).
• Placeholder replacement is done from System and environment variables plus the properties
file itself on all values before use.
• The search order for properties (where it makes sense to look in more than one place) is
environment variables, system properties, loader.properties, the exploded archive manifest,
and the archive manifest.
• Zip entry compression: The ZipEntry for a nested jar must be saved by using the ZipEntry.STORED
method. This is required so that we can seek directly to individual content within the nested jar.
The content of the nested jar file itself can still be compressed, as can any other entries in the
outer jar.
648
• System classLoader: Launched applications should use Thread.getContextClassLoader() when
loading classes (most libraries and frameworks do so by default). Trying to load nested jar
classes with ClassLoader.getSystemClassLoader() fails. java.util.Logging always uses the system
classloader. For this reason, you should consider a different logging implementation.
• JarClassLoader
• OneJar
649
Appendix F: Dependency Versions
This appendix provides details of the dependencies that are managed by Spring Boot.
650
Group ID Artifact ID Version
com.fasterxml.jackson.dataform jackson-dataformat-protobuf 2.13.1
at
com.fasterxml.jackson.dataform jackson-dataformat-smile 2.13.1
at
com.fasterxml.jackson.dataform jackson-dataformat-toml 2.13.1
at
com.fasterxml.jackson.dataform jackson-dataformat-xml 2.13.1
at
com.fasterxml.jackson.dataform jackson-dataformat-yaml 2.13.1
at
com.fasterxml.jackson.datatype jackson-datatype-eclipse- 2.13.1
collections
com.fasterxml.jackson.datatype jackson-datatype-guava 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-hibernate4 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-hibernate5 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-hibernate5- 2.13.1
jakarta
com.fasterxml.jackson.datatype jackson-datatype-hppc 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-jakarta-jsonp 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-jaxrs 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-jdk8 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-joda 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-joda-money 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-json-org 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-jsr310 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-jsr353 2.13.1
com.fasterxml.jackson.datatype jackson-datatype-pcollections 2.13.1
com.fasterxml.jackson.jakarta. jackson-jakarta-rs-base 2.13.1
rs
com.fasterxml.jackson.jakarta. jackson-jakarta-rs-cbor- 2.13.1
rs provider
com.fasterxml.jackson.jakarta. jackson-jakarta-rs-json- 2.13.1
rs provider
com.fasterxml.jackson.jakarta. jackson-jakarta-rs-smile- 2.13.1
rs provider
com.fasterxml.jackson.jakarta. jackson-jakarta-rs-xml- 2.13.1
rs provider
com.fasterxml.jackson.jakarta. jackson-jakarta-rs-yaml- 2.13.1
rs provider
com.fasterxml.jackson.jaxrs jackson-jaxrs-base 2.13.1
com.fasterxml.jackson.jaxrs jackson-jaxrs-cbor-provider 2.13.1
com.fasterxml.jackson.jaxrs jackson-jaxrs-json-provider 2.13.1
651
Group ID Artifact ID Version
com.fasterxml.jackson.jaxrs jackson-jaxrs-smile-provider 2.13.1
com.fasterxml.jackson.jaxrs jackson-jaxrs-xml-provider 2.13.1
com.fasterxml.jackson.jaxrs jackson-jaxrs-yaml-provider 2.13.1
com.fasterxml.jackson.jr jackson-jr-all 2.13.1
com.fasterxml.jackson.jr jackson-jr-annotation-support 2.13.1
com.fasterxml.jackson.jr jackson-jr-objects 2.13.1
com.fasterxml.jackson.jr jackson-jr-retrofit2 2.13.1
com.fasterxml.jackson.jr jackson-jr-stree 2.13.1
com.fasterxml.jackson.module jackson-module-afterburner 2.13.1
com.fasterxml.jackson.module jackson-module-blackbird 2.13.1
com.fasterxml.jackson.module jackson-module-guice 2.13.1
com.fasterxml.jackson.module jackson-module-jakarta- 2.13.1
xmlbind-annotations
com.fasterxml.jackson.module jackson-module-jaxb- 2.13.1
annotations
com.fasterxml.jackson.module jackson-module-jsonSchema 2.13.1
com.fasterxml.jackson.module jackson-module-kotlin 2.13.1
com.fasterxml.jackson.module jackson-module-mrbean 2.13.1
com.fasterxml.jackson.module jackson-module-no-ctor-deser 2.13.1
com.fasterxml.jackson.module jackson-module-osgi 2.13.1
com.fasterxml.jackson.module jackson-module-parameter-names 2.13.1
com.fasterxml.jackson.module jackson-module-paranamer 2.13.1
com.fasterxml.jackson.module jackson-module-scala_2.11 2.13.1
com.fasterxml.jackson.module jackson-module-scala_2.12 2.13.1
com.fasterxml.jackson.module jackson-module-scala_2.13 2.13.1
com.fasterxml.jackson.module jackson-module-scala_3 2.13.1
com.github.ben-manes.caffeine caffeine 3.0.5
com.github.ben-manes.caffeine guava 3.0.5
com.github.ben-manes.caffeine jcache 3.0.5
com.github.ben-manes.caffeine simulator 3.0.5
com.github.mxab.thymeleaf.extr thymeleaf-extras-data- 2.0.1
as attribute
com.google.appengine appengine-api-1.0-sdk 1.9.93
com.google.cloud cloud-spanner-r2dbc 1.1.0
com.google.code.gson gson 2.8.9
com.h2database h2 1.4.200
com.hazelcast hazelcast 5.0.2
com.hazelcast hazelcast-hibernate52 2.2.1
com.hazelcast hazelcast-hibernate53 2.2.1
652
Group ID Artifact ID Version
com.hazelcast hazelcast-spring 5.0.2
com.ibm.db2 jcc 11.5.7.0
com.jayway.jsonpath json-path 2.6.0
com.jayway.jsonpath json-path-assert 2.6.0
com.microsoft.sqlserver mssql-jdbc 9.4.1.jre8
com.oracle.database.ha ons 21.4.0.0.1
com.oracle.database.ha simplefan 21.4.0.0.1
com.oracle.database.jdbc ojdbc11 21.4.0.0.1
com.oracle.database.jdbc ojdbc11-production 21.4.0.0.1
com.oracle.database.jdbc ojdbc8 21.4.0.0.1
com.oracle.database.jdbc ojdbc8-production 21.4.0.0.1
com.oracle.database.jdbc rsi 21.4.0.0.1
com.oracle.database.jdbc ucp 21.4.0.0.1
com.oracle.database.jdbc ucp11 21.4.0.0.1
com.oracle.database.jdbc.debug ojdbc11-debug 21.4.0.0.1
com.oracle.database.jdbc.debug ojdbc11-observability-debug 21.4.0.0.1
com.oracle.database.jdbc.debug ojdbc11_g 21.4.0.0.1
com.oracle.database.jdbc.debug ojdbc11dms_g 21.4.0.0.1
com.oracle.database.jdbc.debug ojdbc8-debug 21.4.0.0.1
com.oracle.database.jdbc.debug ojdbc8-observability-debug 21.4.0.0.1
com.oracle.database.jdbc.debug ojdbc8_g 21.4.0.0.1
com.oracle.database.jdbc.debug ojdbc8dms_g 21.4.0.0.1
com.oracle.database.nls orai18n 21.4.0.0.1
com.oracle.database.observabil dms 21.4.0.0.1
ity
com.oracle.database.observabil ojdbc11-observability 21.4.0.0.1
ity
com.oracle.database.observabil ojdbc11dms 21.4.0.0.1
ity
com.oracle.database.observabil ojdbc8-observability 21.4.0.0.1
ity
com.oracle.database.observabil ojdbc8dms 21.4.0.0.1
ity
com.oracle.database.r2dbc oracle-r2dbc 0.1.0
com.oracle.database.security oraclepki 21.4.0.0.1
com.oracle.database.security osdt_cert 21.4.0.0.1
com.oracle.database.security osdt_core 21.4.0.0.1
com.oracle.database.xml xdb 21.4.0.0.1
com.oracle.database.xml xmlparserv2 21.4.0.0.1
com.querydsl querydsl-apt 5.0.0
653
Group ID Artifact ID Version
com.querydsl querydsl-codegen 5.0.0
com.querydsl querydsl-codegen-utils 5.0.0
com.querydsl querydsl-collections 5.0.0
com.querydsl querydsl-core 5.0.0
com.querydsl querydsl-guava 5.0.0
com.querydsl querydsl-hibernate-search 5.0.0
com.querydsl querydsl-jdo 5.0.0
com.querydsl querydsl-jpa 5.0.0
com.querydsl querydsl-jpa-codegen 5.0.0
com.querydsl querydsl-kotlin 5.0.0
com.querydsl querydsl-kotlin-codegen 5.0.0
com.querydsl querydsl-lucene3 5.0.0
com.querydsl querydsl-lucene4 5.0.0
com.querydsl querydsl-lucene5 5.0.0
com.querydsl querydsl-mongodb 5.0.0
com.querydsl querydsl-scala 5.0.0
com.querydsl querydsl-spatial 5.0.0
com.querydsl querydsl-sql 5.0.0
com.querydsl querydsl-sql-codegen 5.0.0
com.querydsl querydsl-sql-spatial 5.0.0
com.querydsl querydsl-sql-spring 5.0.0
com.rabbitmq amqp-client 5.14.1
com.rabbitmq stream-client 0.4.0
com.samskivert jmustache 1.15
com.sendgrid sendgrid-java 4.8.2
com.squareup.okhttp3 logging-interceptor 3.14.9
com.squareup.okhttp3 mockwebserver 3.14.9
com.squareup.okhttp3 okcurl 3.14.9
com.squareup.okhttp3 okhttp 3.14.9
com.squareup.okhttp3 okhttp-dnsoverhttps 3.14.9
com.squareup.okhttp3 okhttp-sse 3.14.9
com.squareup.okhttp3 okhttp-testing-support 3.14.9
com.squareup.okhttp3 okhttp-tls 3.14.9
com.squareup.okhttp3 okhttp-urlconnection 3.14.9
com.sun.activation jakarta.activation 2.0.1
com.sun.mail jakarta.mail 2.0.1
com.sun.xml.messaging.saaj saaj-impl 2.0.1
com.unboundid unboundid-ldapsdk 4.0.14
654
Group ID Artifact ID Version
com.zaxxer HikariCP 5.0.1
commons-codec commons-codec 1.15
commons-pool commons-pool 1.6
de.flapdoodle.embed de.flapdoodle.embed.mongo 3.2.8
dev.miku r2dbc-mysql 0.8.2.RELEASE
io.dropwizard.metrics metrics-annotation 4.2.7
io.dropwizard.metrics metrics-caffeine 4.2.7
io.dropwizard.metrics metrics-caffeine3 4.2.7
io.dropwizard.metrics metrics-collectd 4.2.7
io.dropwizard.metrics metrics-core 4.2.7
io.dropwizard.metrics metrics-ehcache 4.2.7
io.dropwizard.metrics metrics-graphite 4.2.7
io.dropwizard.metrics metrics-healthchecks 4.2.7
io.dropwizard.metrics metrics-httpasyncclient 4.2.7
io.dropwizard.metrics metrics-httpclient 4.2.7
io.dropwizard.metrics metrics-httpclient5 4.2.7
io.dropwizard.metrics metrics-jakarta-servlet 4.2.7
io.dropwizard.metrics metrics-jakarta-servlets 4.2.7
io.dropwizard.metrics metrics-jcache 4.2.7
io.dropwizard.metrics metrics-jdbi 4.2.7
io.dropwizard.metrics metrics-jdbi3 4.2.7
io.dropwizard.metrics metrics-jersey2 4.2.7
io.dropwizard.metrics metrics-jersey3 4.2.7
io.dropwizard.metrics metrics-jetty10 4.2.7
io.dropwizard.metrics metrics-jetty11 4.2.7
io.dropwizard.metrics metrics-jetty9 4.2.7
io.dropwizard.metrics metrics-jmx 4.2.7
io.dropwizard.metrics metrics-json 4.2.7
io.dropwizard.metrics metrics-jvm 4.2.7
io.dropwizard.metrics metrics-log4j2 4.2.7
io.dropwizard.metrics metrics-logback 4.2.7
io.dropwizard.metrics metrics-servlet 4.2.7
io.dropwizard.metrics metrics-servlets 4.2.7
io.lettuce lettuce-core 6.1.6.RELEASE
io.micrometer micrometer-core 2.0.0-M1
io.micrometer micrometer-registry-appoptics 2.0.0-M1
io.micrometer micrometer-registry-atlas 2.0.0-M1
io.micrometer micrometer-registry-azure- 2.0.0-M1
monitor
655
Group ID Artifact ID Version
io.micrometer micrometer-registry-cloudwatch 2.0.0-M1
io.micrometer micrometer-registry- 2.0.0-M1
cloudwatch2
io.micrometer micrometer-registry-datadog 2.0.0-M1
io.micrometer micrometer-registry-dynatrace 2.0.0-M1
io.micrometer micrometer-registry-elastic 2.0.0-M1
io.micrometer micrometer-registry-ganglia 2.0.0-M1
io.micrometer micrometer-registry-graphite 2.0.0-M1
io.micrometer micrometer-registry-health 2.0.0-M1
io.micrometer micrometer-registry-humio 2.0.0-M1
io.micrometer micrometer-registry-influx 2.0.0-M1
io.micrometer micrometer-registry-jmx 2.0.0-M1
io.micrometer micrometer-registry-kairos 2.0.0-M1
io.micrometer micrometer-registry-new-relic 2.0.0-M1
io.micrometer micrometer-registry-opentsdb 2.0.0-M1
io.micrometer micrometer-registry-prometheus 2.0.0-M1
io.micrometer micrometer-registry-signalfx 2.0.0-M1
io.micrometer micrometer-registry- 2.0.0-M1
stackdriver
io.micrometer micrometer-registry-statsd 2.0.0-M1
io.micrometer micrometer-registry-wavefront 2.0.0-M1
io.micrometer micrometer-test 2.0.0-M1
io.netty netty-all 4.1.73.Final
io.netty netty-buffer 4.1.73.Final
io.netty netty-codec 4.1.73.Final
io.netty netty-codec-dns 4.1.73.Final
io.netty netty-codec-haproxy 4.1.73.Final
io.netty netty-codec-http 4.1.73.Final
io.netty netty-codec-http2 4.1.73.Final
io.netty netty-codec-memcache 4.1.73.Final
io.netty netty-codec-mqtt 4.1.73.Final
io.netty netty-codec-redis 4.1.73.Final
io.netty netty-codec-smtp 4.1.73.Final
io.netty netty-codec-socks 4.1.73.Final
io.netty netty-codec-stomp 4.1.73.Final
io.netty netty-codec-xml 4.1.73.Final
io.netty netty-common 4.1.73.Final
io.netty netty-dev-tools 4.1.73.Final
io.netty netty-example 4.1.73.Final
656
Group ID Artifact ID Version
io.netty netty-handler 4.1.73.Final
io.netty netty-handler-proxy 4.1.73.Final
io.netty netty-resolver 4.1.73.Final
io.netty netty-resolver-dns 4.1.73.Final
io.netty netty-resolver-dns-classes- 4.1.73.Final
macos
io.netty netty-resolver-dns-native- 4.1.73.Final
macos
io.netty netty-tcnative 2.0.46.Final
io.netty netty-tcnative-boringssl- 2.0.46.Final
static
io.netty netty-tcnative-classes 2.0.46.Final
io.netty netty-transport 4.1.73.Final
io.netty netty-transport-classes-epoll 4.1.73.Final
io.netty netty-transport-classes-kqueue 4.1.73.Final
io.netty netty-transport-native-epoll 4.1.73.Final
io.netty netty-transport-native-kqueue 4.1.73.Final
io.netty netty-transport-native-unix- 4.1.73.Final
common
io.netty netty-transport-rxtx 4.1.73.Final
io.netty netty-transport-sctp 4.1.73.Final
io.netty netty-transport-udt 4.1.73.Final
io.projectreactor reactor-core 3.4.14
io.projectreactor reactor-test 3.4.14
io.projectreactor reactor-tools 3.4.14
io.projectreactor.addons reactor-adapter 3.4.6
io.projectreactor.addons reactor-extra 3.4.6
io.projectreactor.addons reactor-pool 0.2.7
io.projectreactor.kafka reactor-kafka 1.3.9
io.projectreactor.kotlin reactor-kotlin-extensions 1.1.5
io.projectreactor.netty reactor-netty 1.0.15
io.projectreactor.netty reactor-netty-core 1.0.15
io.projectreactor.netty reactor-netty-http 1.0.15
io.projectreactor.netty reactor-netty-http-brave 1.0.15
io.projectreactor.rabbitmq reactor-rabbitmq 1.5.4
io.prometheus simpleclient 0.14.1
io.prometheus simpleclient_caffeine 0.14.1
io.prometheus simpleclient_common 0.14.1
io.prometheus simpleclient_dropwizard 0.14.1
io.prometheus simpleclient_graphite_bridge 0.14.1
657
Group ID Artifact ID Version
io.prometheus simpleclient_guava 0.14.1
io.prometheus simpleclient_hibernate 0.14.1
io.prometheus simpleclient_hotspot 0.14.1
io.prometheus simpleclient_httpserver 0.14.1
io.prometheus simpleclient_jetty 0.14.1
io.prometheus simpleclient_jetty_jdk8 0.14.1
io.prometheus simpleclient_log4j 0.14.1
io.prometheus simpleclient_log4j2 0.14.1
io.prometheus simpleclient_logback 0.14.1
io.prometheus simpleclient_pushgateway 0.14.1
io.prometheus simpleclient_servlet 0.14.1
io.prometheus simpleclient_servlet_jakarta 0.14.1
io.prometheus simpleclient_spring_boot 0.14.1
io.prometheus simpleclient_spring_web 0.14.1
io.prometheus simpleclient_tracer_otel 0.14.1
io.prometheus simpleclient_tracer_otel_agent 0.14.1
io.prometheus simpleclient_vertx 0.14.1
io.r2dbc r2dbc-h2 0.8.5.RELEASE
io.r2dbc r2dbc-mssql 0.8.8.RELEASE
io.r2dbc r2dbc-pool 0.8.8.RELEASE
io.r2dbc r2dbc-postgresql 0.8.11.RELEASE
io.r2dbc r2dbc-proxy 0.8.8.RELEASE
io.r2dbc r2dbc-spi 0.8.6.RELEASE
io.reactivex rxjava 1.3.8
io.reactivex rxjava-reactive-streams 1.2.1
io.reactivex.rxjava2 rxjava 2.2.21
io.rest-assured json-path 4.5.0
io.rest-assured json-schema-validator 4.5.0
io.rest-assured rest-assured 4.5.0
io.rest-assured scala-support 4.5.0
io.rest-assured spring-mock-mvc 4.5.0
io.rest-assured spring-web-test-client 4.5.0
io.rest-assured xml-path 4.5.0
io.rsocket rsocket-core 1.1.1
io.rsocket rsocket-load-balancer 1.1.1
io.rsocket rsocket-micrometer 1.1.1
io.rsocket rsocket-test 1.1.1
io.rsocket rsocket-transport-local 1.1.1
658
Group ID Artifact ID Version
io.rsocket rsocket-transport-netty 1.1.1
io.spring.gradle dependency-management-plugin 1.0.11.RELEASE
io.undertow undertow-core 2.2.14.Final
io.undertow undertow-servlet-jakarta 2.2.14.Final
io.undertow undertow-websockets-jsr- 2.2.14.Final
jakarta
jakarta.activation jakarta.activation-api 2.0.1
jakarta.annotation jakarta.annotation-api 2.0.0
jakarta.jms jakarta.jms-api 3.0.0
jakarta.json jakarta.json-api 2.0.1
jakarta.json.bind jakarta.json.bind-api 2.0.0
jakarta.mail jakarta.mail-api 2.0.1
jakarta.management.j2ee jakarta.management.j2ee-api 1.1.4
jakarta.persistence jakarta.persistence-api 3.0.0
jakarta.servlet jakarta.servlet-api 5.0.0
jakarta.servlet.jsp.jstl jakarta.servlet.jsp.jstl-api 2.0.0
jakarta.transaction jakarta.transaction-api 2.0.0
jakarta.validation jakarta.validation-api 3.0.1
jakarta.websocket jakarta.websocket-api 2.0.0
jakarta.ws.rs jakarta.ws.rs-api 3.0.0
jakarta.xml.bind jakarta.xml.bind-api 3.0.1
jakarta.xml.soap jakarta.xml.soap-api 2.0.1
jakarta.xml.ws jakarta.xml.ws-api 3.0.1
javax.cache cache-api 1.1.1
javax.money money-api 1.1
javax.servlet javax.servlet-api 4.0.1
javax.servlet jstl 1.2
jaxen jaxen 1.2.0
junit junit 4.13.2
mysql mysql-connector-java 8.0.28
net.bytebuddy byte-buddy 1.12.7
net.bytebuddy byte-buddy-agent 1.12.7
net.minidev json-smart 2.4.7
net.sourceforge.htmlunit htmlunit 2.56.0
net.sourceforge.jtds jtds 1.3.1
net.sourceforge.nekohtml nekohtml 1.9.22
nz.net.ultraq.thymeleaf thymeleaf-layout-dialect 3.0.0
org.apache.activemq artemis-amqp-protocol 2.20.0
org.apache.activemq artemis-commons 2.20.0
659
Group ID Artifact ID Version
org.apache.activemq artemis-core-client 2.20.0
org.apache.activemq artemis-jakarta-client 2.20.0
org.apache.activemq artemis-jakarta-server 2.20.0
org.apache.activemq artemis-journal 2.20.0
org.apache.activemq artemis-selector 2.20.0
org.apache.activemq artemis-server 2.20.0
org.apache.activemq artemis-service-extensions 2.20.0
org.apache.commons commons-dbcp2 2.9.0
org.apache.commons commons-lang3 3.12.0
org.apache.commons commons-pool2 2.11.1
org.apache.derby derby 10.15.2.0
org.apache.derby derbyclient 10.15.2.0
org.apache.derby derbyshared 10.15.2.0
org.apache.derby derbytools 10.15.2.0
org.apache.httpcomponents fluent-hc 4.5.13
org.apache.httpcomponents httpasyncclient 4.1.5
org.apache.httpcomponents httpclient 4.5.13
org.apache.httpcomponents httpclient-cache 4.5.13
org.apache.httpcomponents httpclient-osgi 4.5.13
org.apache.httpcomponents httpclient-win 4.5.13
org.apache.httpcomponents httpcore 4.4.15
org.apache.httpcomponents httpcore-nio 4.4.15
org.apache.httpcomponents httpmime 4.5.13
org.apache.httpcomponents.clie httpclient5 5.1.2
nt5
org.apache.httpcomponents.clie httpclient5-cache 5.1.2
nt5
org.apache.httpcomponents.clie httpclient5-fluent 5.1.2
nt5
org.apache.httpcomponents.clie httpclient5-win 5.1.2
nt5
org.apache.httpcomponents.core httpcore5 5.1.3
5
org.apache.httpcomponents.core httpcore5-h2 5.1.3
5
org.apache.httpcomponents.core httpcore5-reactive 5.1.3
5
org.apache.kafka connect-api 3.0.0
org.apache.kafka connect-basic-auth-extension 3.0.0
org.apache.kafka connect-file 3.0.0
org.apache.kafka connect-json 3.0.0
660
Group ID Artifact ID Version
org.apache.kafka connect-runtime 3.0.0
org.apache.kafka connect-transforms 3.0.0
org.apache.kafka kafka-clients 3.0.0
org.apache.kafka kafka-log4j-appender 3.0.0
org.apache.kafka kafka-metadata 3.0.0
org.apache.kafka kafka-streams 3.0.0
org.apache.kafka kafka-streams-scala_2.12 3.0.0
org.apache.kafka kafka-streams-scala_2.13 3.0.0
org.apache.kafka kafka-streams-test-utils 3.0.0
org.apache.kafka kafka-tools 3.0.0
org.apache.kafka kafka_2.12 3.0.0
org.apache.kafka kafka_2.13 3.0.0
org.apache.logging.log4j log4j-1.2-api 2.17.1
org.apache.logging.log4j log4j-api 2.17.1
org.apache.logging.log4j log4j-appserver 2.17.1
org.apache.logging.log4j log4j-cassandra 2.17.1
org.apache.logging.log4j log4j-core 2.17.1
org.apache.logging.log4j log4j-couchdb 2.17.1
org.apache.logging.log4j log4j-docker 2.17.1
org.apache.logging.log4j log4j-flume-ng 2.17.1
org.apache.logging.log4j log4j-iostreams 2.17.1
org.apache.logging.log4j log4j-jcl 2.17.1
org.apache.logging.log4j log4j-jmx-gui 2.17.1
org.apache.logging.log4j log4j-jpa 2.17.1
org.apache.logging.log4j log4j-jpl 2.17.1
org.apache.logging.log4j log4j-jul 2.17.1
org.apache.logging.log4j log4j-kubernetes 2.17.1
org.apache.logging.log4j log4j-layout-template-json 2.17.1
org.apache.logging.log4j log4j-liquibase 2.17.1
org.apache.logging.log4j log4j-mongodb3 2.17.1
org.apache.logging.log4j log4j-mongodb4 2.17.1
org.apache.logging.log4j log4j-slf4j-impl 2.17.1
org.apache.logging.log4j log4j-slf4j18-impl 2.17.1
org.apache.logging.log4j log4j-spring-boot 2.17.1
org.apache.logging.log4j log4j-spring-cloud-config- 2.17.1
client
org.apache.logging.log4j log4j-taglib 2.17.1
org.apache.logging.log4j log4j-to-slf4j 2.17.1
org.apache.logging.log4j log4j-web 2.17.1
661
Group ID Artifact ID Version
org.apache.solr solr-analysis-extras 8.11.1
org.apache.solr solr-analytics 8.11.1
org.apache.solr solr-cell 8.11.1
org.apache.solr solr-core 8.11.1
org.apache.solr solr-dataimporthandler 8.11.1
org.apache.solr solr-dataimporthandler-extras 8.11.1
org.apache.solr solr-gcs-repository 8.11.1
org.apache.solr solr-jaegertracer-configurator 8.11.1
org.apache.solr solr-langid 8.11.1
org.apache.solr solr-ltr 8.11.1
org.apache.solr solr-prometheus-exporter 8.11.1
org.apache.solr solr-s3-repository 8.11.1
org.apache.solr solr-solrj 8.11.1
org.apache.solr solr-test-framework 8.11.1
org.apache.solr solr-velocity 8.11.1
org.apache.tomcat tomcat-annotations-api 10.0.16
org.apache.tomcat tomcat-jdbc 10.0.16
org.apache.tomcat tomcat-jsp-api 10.0.16
org.apache.tomcat.embed tomcat-embed-core 10.0.16
org.apache.tomcat.embed tomcat-embed-el 10.0.16
org.apache.tomcat.embed tomcat-embed-jasper 10.0.16
org.apache.tomcat.embed tomcat-embed-websocket 10.0.16
org.aspectj aspectjrt 1.9.7
org.aspectj aspectjtools 1.9.7
org.aspectj aspectjweaver 1.9.7
org.assertj assertj-core 3.22.0
org.awaitility awaitility 4.1.1
org.awaitility awaitility-groovy 4.1.1
org.awaitility awaitility-kotlin 4.1.1
org.awaitility awaitility-scala 4.1.1
org.codehaus.groovy groovy 3.0.9
org.codehaus.groovy groovy-ant 3.0.9
org.codehaus.groovy groovy-astbuilder 3.0.9
org.codehaus.groovy groovy-bsf 3.0.9
org.codehaus.groovy groovy-cli-commons 3.0.9
org.codehaus.groovy groovy-cli-picocli 3.0.9
org.codehaus.groovy groovy-console 3.0.9
org.codehaus.groovy groovy-datetime 3.0.9
662
Group ID Artifact ID Version
org.codehaus.groovy groovy-dateutil 3.0.9
org.codehaus.groovy groovy-docgenerator 3.0.9
org.codehaus.groovy groovy-groovydoc 3.0.9
org.codehaus.groovy groovy-groovysh 3.0.9
org.codehaus.groovy groovy-jaxb 3.0.9
org.codehaus.groovy groovy-jmx 3.0.9
org.codehaus.groovy groovy-json 3.0.9
org.codehaus.groovy groovy-jsr223 3.0.9
org.codehaus.groovy groovy-macro 3.0.9
org.codehaus.groovy groovy-nio 3.0.9
org.codehaus.groovy groovy-servlet 3.0.9
org.codehaus.groovy groovy-sql 3.0.9
org.codehaus.groovy groovy-swing 3.0.9
org.codehaus.groovy groovy-templates 3.0.9
org.codehaus.groovy groovy-test 3.0.9
org.codehaus.groovy groovy-test-junit5 3.0.9
org.codehaus.groovy groovy-testng 3.0.9
org.codehaus.groovy groovy-xml 3.0.9
org.codehaus.groovy groovy-yaml 3.0.9
org.codehaus.janino commons-compiler 3.1.6
org.codehaus.janino commons-compiler-jdk 3.1.6
org.codehaus.janino janino 3.1.6
org.eclipse yasson 2.0.4
org.eclipse.jetty apache-jsp 11.0.7
org.eclipse.jetty glassfish-jstl 11.0.7
org.eclipse.jetty infinispan-common 11.0.7
org.eclipse.jetty infinispan-embedded-query 11.0.7
org.eclipse.jetty infinispan-remote-query 11.0.7
org.eclipse.jetty jetty-alpn-client 11.0.7
org.eclipse.jetty jetty-alpn-conscrypt-client 11.0.7
org.eclipse.jetty jetty-alpn-conscrypt-server 11.0.7
org.eclipse.jetty jetty-alpn-java-client 11.0.7
org.eclipse.jetty jetty-alpn-java-server 11.0.7
org.eclipse.jetty jetty-alpn-server 11.0.7
org.eclipse.jetty jetty-annotations 11.0.7
org.eclipse.jetty jetty-ant 11.0.7
org.eclipse.jetty jetty-cdi 10.0.3-SNAPSHOT
org.eclipse.jetty jetty-client 11.0.7
663
Group ID Artifact ID Version
org.eclipse.jetty jetty-deploy 11.0.7
org.eclipse.jetty jetty-hazelcast 11.0.7
org.eclipse.jetty jetty-home 11.0.7
org.eclipse.jetty jetty-http 11.0.7
org.eclipse.jetty jetty-http-spi 11.0.7
org.eclipse.jetty jetty-io 11.0.7
org.eclipse.jetty jetty-jaas 11.0.7
org.eclipse.jetty jetty-jaspi 11.0.7
org.eclipse.jetty jetty-jmx 11.0.7
org.eclipse.jetty jetty-jndi 11.0.7
org.eclipse.jetty jetty-nosql 11.0.7
org.eclipse.jetty jetty-openid 11.0.7
org.eclipse.jetty jetty-plus 11.0.7
org.eclipse.jetty jetty-proxy 11.0.7
org.eclipse.jetty jetty-quickstart 11.0.7
org.eclipse.jetty jetty-reactive-httpclient 3.0.4
org.eclipse.jetty jetty-rewrite 11.0.7
org.eclipse.jetty jetty-security 11.0.7
org.eclipse.jetty jetty-server 11.0.7
org.eclipse.jetty jetty-servlet 11.0.7
org.eclipse.jetty jetty-servlets 11.0.7
org.eclipse.jetty jetty-unixsocket-client 11.0.7
org.eclipse.jetty jetty-unixsocket-common 11.0.7
org.eclipse.jetty jetty-unixsocket-server 11.0.7
org.eclipse.jetty jetty-util 11.0.7
org.eclipse.jetty jetty-util-ajax 11.0.7
org.eclipse.jetty jetty-webapp 11.0.7
org.eclipse.jetty jetty-xml 11.0.7
org.eclipse.jetty.fcgi fcgi-client 11.0.7
org.eclipse.jetty.fcgi fcgi-server 11.0.7
org.eclipse.jetty.gcloud jetty-gcloud-session-manager 11.0.7
org.eclipse.jetty.http2 http2-client 11.0.7
org.eclipse.jetty.http2 http2-common 11.0.7
org.eclipse.jetty.http2 http2-hpack 11.0.7
org.eclipse.jetty.http2 http2-http-client-transport 11.0.7
org.eclipse.jetty.http2 http2-server 11.0.7
org.eclipse.jetty.memcached jetty-memcached-sessions 11.0.7
org.eclipse.jetty.osgi jetty-httpservice 11.0.7
664
Group ID Artifact ID Version
org.eclipse.jetty.osgi jetty-osgi-boot 11.0.7
org.eclipse.jetty.osgi jetty-osgi-boot-jsp 11.0.7
org.eclipse.jetty.osgi jetty-osgi-boot-warurl 11.0.7
org.eclipse.jetty.websocket websocket-core-client 11.0.7
org.eclipse.jetty.websocket websocket-core-common 11.0.7
org.eclipse.jetty.websocket websocket-core-server 11.0.7
org.eclipse.jetty.websocket websocket-jakarta-client 11.0.7
org.eclipse.jetty.websocket websocket-jakarta-common 11.0.7
org.eclipse.jetty.websocket websocket-jakarta-server 11.0.7
org.eclipse.jetty.websocket websocket-jetty-api 11.0.7
org.eclipse.jetty.websocket websocket-jetty-client 11.0.7
org.eclipse.jetty.websocket websocket-jetty-common 11.0.7
org.eclipse.jetty.websocket websocket-jetty-server 11.0.7
org.eclipse.jetty.websocket websocket-servlet 11.0.7
org.elasticsearch elasticsearch 7.16.2
org.elasticsearch.client elasticsearch-rest-client 7.16.2
org.elasticsearch.client elasticsearch-rest-client- 7.16.2
sniffer
org.elasticsearch.client elasticsearch-rest-high-level- 7.16.2
client
org.elasticsearch.client transport 7.16.2
org.elasticsearch.distribution elasticsearch 7.16.2
.integ-test-zip
org.elasticsearch.plugin transport-netty4-client 7.16.2
org.firebirdsql.jdbc jaybird 4.0.5.java8
org.firebirdsql.jdbc jaybird-jdk18 4.0.5.java8
org.flywaydb flyway-core 8.4.2
org.flywaydb flyway-firebird 8.4.2
org.flywaydb flyway-mysql 8.4.2
org.flywaydb flyway-sqlserver 8.4.2
org.freemarker freemarker 2.3.31
org.glassfish jakarta.el 4.0.2
org.glassfish.jaxb codemodel 3.0.2
org.glassfish.jaxb codemodel-annotation-compiler 3.0.2
org.glassfish.jaxb jaxb-jxc 3.0.2
org.glassfish.jaxb jaxb-runtime 3.0.2
org.glassfish.jaxb jaxb-xjc 3.0.2
org.glassfish.jaxb txw2 3.0.2
org.glassfish.jaxb txwc2 3.0.2
665
Group ID Artifact ID Version
org.glassfish.jaxb xsom 3.0.2
org.glassfish.web jakarta.servlet.jsp.jstl 2.0.0
org.hamcrest hamcrest 2.2
org.hamcrest hamcrest-core 2.2
org.hamcrest hamcrest-library 2.2
org.hibernate hibernate-c3p0 5.6.4.Final
org.hibernate hibernate-core-jakarta 5.6.4.Final
org.hibernate hibernate-ehcache 5.6.4.Final
org.hibernate hibernate-entitymanager 5.6.4.Final
org.hibernate hibernate-envers-jakarta 5.6.4.Final
org.hibernate hibernate-hikaricp 5.6.4.Final
org.hibernate hibernate-java8 5.6.4.Final
org.hibernate hibernate-jcache 5.6.4.Final
org.hibernate hibernate-jpamodelgen-jakarta 5.6.4.Final
org.hibernate hibernate-micrometer 5.6.4.Final
org.hibernate hibernate-proxool 5.6.4.Final
org.hibernate hibernate-spatial 5.6.4.Final
org.hibernate hibernate-testing-jakarta 5.6.4.Final
org.hibernate hibernate-vibur 5.6.4.Final
org.hibernate.validator hibernate-validator 7.0.1.Final
org.hibernate.validator hibernate-validator- 7.0.1.Final
annotation-processor
org.hsqldb hsqldb 2.6.1
org.influxdb influxdb-java 2.22
org.jboss.logging jboss-logging 3.4.3.Final
org.jdom jdom2 2.0.6.1
org.jetbrains.kotlin kotlin-compiler 1.6.0
org.jetbrains.kotlin kotlin-compiler-embeddable 1.6.0
org.jetbrains.kotlin kotlin-daemon-client 1.6.0
org.jetbrains.kotlin kotlin-main-kts 1.6.0
org.jetbrains.kotlin kotlin-osgi-bundle 1.6.0
org.jetbrains.kotlin kotlin-reflect 1.6.0
org.jetbrains.kotlin kotlin-script-runtime 1.6.0
org.jetbrains.kotlin kotlin-script-util 1.6.0
org.jetbrains.kotlin kotlin-scripting-common 1.6.0
org.jetbrains.kotlin kotlin-scripting-ide-services 1.6.0
org.jetbrains.kotlin kotlin-scripting-jvm 1.6.0
org.jetbrains.kotlin kotlin-scripting-jvm-host 1.6.0
org.jetbrains.kotlin kotlin-stdlib 1.6.0
666
Group ID Artifact ID Version
org.jetbrains.kotlin kotlin-stdlib-common 1.6.0
org.jetbrains.kotlin kotlin-stdlib-jdk7 1.6.0
org.jetbrains.kotlin kotlin-stdlib-jdk8 1.6.0
org.jetbrains.kotlin kotlin-stdlib-js 1.6.0
org.jetbrains.kotlin kotlin-test 1.6.0
org.jetbrains.kotlin kotlin-test-annotations-common 1.6.0
org.jetbrains.kotlin kotlin-test-common 1.6.0
org.jetbrains.kotlin kotlin-test-js 1.6.0
org.jetbrains.kotlin kotlin-test-junit 1.6.0
org.jetbrains.kotlin kotlin-test-junit5 1.6.0
org.jetbrains.kotlin kotlin-test-testng 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-android 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-core 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-core-jvm 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-debug 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-guava 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-javafx 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-jdk8 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-jdk9 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-play- 1.6.0
services
org.jetbrains.kotlinx kotlinx-coroutines-reactive 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-reactor 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-rx2 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-rx3 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-slf4j 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-swing 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-test 1.6.0
org.jetbrains.kotlinx kotlinx-coroutines-test-jvm 1.6.0
org.jooq jooq 3.16.2
org.jooq jooq-codegen 3.16.2
org.jooq jooq-kotlin 3.16.2
org.jooq jooq-meta 3.16.2
org.junit.jupiter junit-jupiter 5.8.2
org.junit.jupiter junit-jupiter-api 5.8.2
org.junit.jupiter junit-jupiter-engine 5.8.2
org.junit.jupiter junit-jupiter-migrationsupport 5.8.2
org.junit.jupiter junit-jupiter-params 5.8.2
org.junit.platform junit-platform-commons 1.8.2
667
Group ID Artifact ID Version
org.junit.platform junit-platform-console 1.8.2
org.junit.platform junit-platform-engine 1.8.2
org.junit.platform junit-platform-jfr 1.8.2
org.junit.platform junit-platform-launcher 1.8.2
org.junit.platform junit-platform-reporting 1.8.2
org.junit.platform junit-platform-runner 1.8.2
org.junit.platform junit-platform-suite 1.8.2
org.junit.platform junit-platform-suite-api 1.8.2
org.junit.platform junit-platform-suite-commons 1.8.2
org.junit.platform junit-platform-suite-engine 1.8.2
org.junit.platform junit-platform-testkit 1.8.2
org.junit.vintage junit-vintage-engine 5.8.2
org.jvnet.mimepull mimepull 1.9.15
org.liquibase liquibase-core 4.7.0
org.mariadb r2dbc-mariadb 1.0.3
org.mariadb.jdbc mariadb-java-client 2.7.5
org.mockito mockito-core 4.2.0
org.mockito mockito-inline 4.2.0
org.mockito mockito-junit-jupiter 4.2.0
org.mongodb bson 4.4.1
org.mongodb mongodb-driver-core 4.4.1
org.mongodb mongodb-driver-legacy 4.4.1
org.mongodb mongodb-driver-reactivestreams 4.4.1
org.mongodb mongodb-driver-sync 4.4.1
org.mortbay.jasper apache-el 10.0.7
org.neo4j.driver neo4j-java-driver 4.4.2
org.postgresql postgresql 42.3.1
org.projectlombok lombok 1.18.22
org.quartz-scheduler quartz 2.3.2
org.quartz-scheduler quartz-jobs 2.3.2
org.reactivestreams reactive-streams 1.0.3
org.seleniumhq.selenium htmlunit-driver 3.56.0
org.seleniumhq.selenium selenium-api 4.1.1
org.seleniumhq.selenium selenium-chrome-driver 4.1.1
org.seleniumhq.selenium selenium-edge-driver 4.1.1
org.seleniumhq.selenium selenium-firefox-driver 4.1.1
org.seleniumhq.selenium selenium-ie-driver 4.1.1
org.seleniumhq.selenium selenium-java 4.1.1
668
Group ID Artifact ID Version
org.seleniumhq.selenium selenium-opera-driver 4.1.1
org.seleniumhq.selenium selenium-remote-driver 4.1.1
org.seleniumhq.selenium selenium-safari-driver 4.1.1
org.seleniumhq.selenium selenium-support 4.1.1
org.skyscreamer jsonassert 1.5.0
org.slf4j jcl-over-slf4j 1.7.33
org.slf4j jul-to-slf4j 1.7.33
org.slf4j log4j-over-slf4j 1.7.33
org.slf4j slf4j-api 1.7.33
org.slf4j slf4j-ext 1.7.33
org.slf4j slf4j-jcl 1.7.33
org.slf4j slf4j-jdk14 1.7.33
org.slf4j slf4j-log4j12 1.7.33
org.slf4j slf4j-nop 1.7.33
org.slf4j slf4j-simple 1.7.33
org.springframework spring-aop 6.0.0-M2
org.springframework spring-aspects 6.0.0-M2
org.springframework spring-beans 6.0.0-M2
org.springframework spring-context 6.0.0-M2
org.springframework spring-context-indexer 6.0.0-M2
org.springframework spring-context-support 6.0.0-M2
org.springframework spring-core 6.0.0-M2
org.springframework spring-expression 6.0.0-M2
org.springframework spring-instrument 6.0.0-M2
org.springframework spring-jcl 6.0.0-M2
org.springframework spring-jdbc 6.0.0-M2
org.springframework spring-jms 6.0.0-M2
org.springframework spring-messaging 6.0.0-M2
org.springframework spring-orm 6.0.0-M2
org.springframework spring-oxm 6.0.0-M2
org.springframework spring-r2dbc 6.0.0-M2
org.springframework spring-test 6.0.0-M2
org.springframework spring-tx 6.0.0-M2
org.springframework spring-web 6.0.0-M2
org.springframework spring-webflux 6.0.0-M2
org.springframework spring-webmvc 6.0.0-M2
org.springframework spring-websocket 6.0.0-M2
org.springframework.amqp spring-amqp 3.0.0-M1
669
Group ID Artifact ID Version
org.springframework.amqp spring-rabbit 3.0.0-M1
org.springframework.amqp spring-rabbit-junit 3.0.0-M1
org.springframework.amqp spring-rabbit-stream 3.0.0-M1
org.springframework.amqp spring-rabbit-test 3.0.0-M1
org.springframework.batch spring-batch-core 5.0.0-M1
org.springframework.batch spring-batch-infrastructure 5.0.0-M1
org.springframework.batch spring-batch-integration 5.0.0-M1
org.springframework.batch spring-batch-test 5.0.0-M1
org.springframework.boot spring-boot 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-actuator 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-actuator- 3.0.0-SNAPSHOT
autoconfigure
org.springframework.boot spring-boot-autoconfigure 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-autoconfigure- 3.0.0-SNAPSHOT
processor
org.springframework.boot spring-boot-buildpack-platform 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-configuration- 3.0.0-SNAPSHOT
metadata
org.springframework.boot spring-boot-configuration- 3.0.0-SNAPSHOT
processor
org.springframework.boot spring-boot-devtools 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-jarmode-layertools 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-loader 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-loader-tools 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-properties- 3.0.0-SNAPSHOT
migrator
org.springframework.boot spring-boot-starter 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-activemq 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-actuator 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-amqp 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-aop 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-artemis 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-batch 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-cache 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-data- 3.0.0-SNAPSHOT
cassandra
org.springframework.boot spring-boot-starter-data- 3.0.0-SNAPSHOT
cassandra-reactive
org.springframework.boot spring-boot-starter-data- 3.0.0-SNAPSHOT
couchbase
670
Group ID Artifact ID Version
org.springframework.boot spring-boot-starter-data- 3.0.0-SNAPSHOT
couchbase-reactive
org.springframework.boot spring-boot-starter-data- 3.0.0-SNAPSHOT
elasticsearch
org.springframework.boot spring-boot-starter-data-jdbc 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-data-jpa 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-data-ldap 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-data- 3.0.0-SNAPSHOT
mongodb
org.springframework.boot spring-boot-starter-data- 3.0.0-SNAPSHOT
mongodb-reactive
org.springframework.boot spring-boot-starter-data-neo4j 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-data-r2dbc 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-data-redis 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-data- 3.0.0-SNAPSHOT
redis-reactive
org.springframework.boot spring-boot-starter-data-rest 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-freemarker 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-groovy- 3.0.0-SNAPSHOT
templates
org.springframework.boot spring-boot-starter-hateoas 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter- 3.0.0-SNAPSHOT
integration
org.springframework.boot spring-boot-starter-jdbc 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-jetty 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-jooq 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-json 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-jta- 3.0.0-SNAPSHOT
atomikos
org.springframework.boot spring-boot-starter-log4j2 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-logging 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-mail 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-mustache 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-oauth2- 3.0.0-SNAPSHOT
client
org.springframework.boot spring-boot-starter-oauth2- 3.0.0-SNAPSHOT
resource-server
org.springframework.boot spring-boot-starter-quartz 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-reactor- 3.0.0-SNAPSHOT
netty
org.springframework.boot spring-boot-starter-rsocket 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-security 3.0.0-SNAPSHOT
671
Group ID Artifact ID Version
org.springframework.boot spring-boot-starter-test 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-thymeleaf 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-tomcat 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-undertow 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-validation 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-web 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-web- 3.0.0-SNAPSHOT
services
org.springframework.boot spring-boot-starter-webflux 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-starter-websocket 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-test 3.0.0-SNAPSHOT
org.springframework.boot spring-boot-test-autoconfigure 3.0.0-SNAPSHOT
org.springframework.data spring-data-cassandra 4.0.0-M1
org.springframework.data spring-data-commons 3.0.0-M1
org.springframework.data spring-data-couchbase 5.0.0-M1
org.springframework.data spring-data-elasticsearch 5.0.0-M1
org.springframework.data spring-data-envers 3.0.0-M1
org.springframework.data spring-data-geode 3.0.0-M1
org.springframework.data spring-data-jdbc 3.0.0-M1
org.springframework.data spring-data-jpa 3.0.0-M1
org.springframework.data spring-data-keyvalue 3.0.0-M1
org.springframework.data spring-data-ldap 3.0.0-M1
org.springframework.data spring-data-mongodb 4.0.0-M1
org.springframework.data spring-data-neo4j 7.0.0-M1
org.springframework.data spring-data-r2dbc 3.0.0-M1
org.springframework.data spring-data-redis 3.0.0-M1
org.springframework.data spring-data-relational 3.0.0-M1
org.springframework.data spring-data-rest-core 4.0.0-M1
org.springframework.data spring-data-rest-hal-explorer 4.0.0-M1
org.springframework.data spring-data-rest-webmvc 4.0.0-M1
org.springframework.hateoas spring-hateoas 2.0.0-M1
org.springframework.integratio spring-integration-amqp 6.0.0-M1
n
org.springframework.integratio spring-integration-core 6.0.0-M1
n
org.springframework.integratio spring-integration-event 6.0.0-M1
n
org.springframework.integratio spring-integration-feed 6.0.0-M1
n
672
Group ID Artifact ID Version
org.springframework.integratio spring-integration-file 6.0.0-M1
n
org.springframework.integratio spring-integration-ftp 6.0.0-M1
n
org.springframework.integratio spring-integration-gemfire 6.0.0-M1
n
org.springframework.integratio spring-integration-groovy 6.0.0-M1
n
org.springframework.integratio spring-integration-http 6.0.0-M1
n
org.springframework.integratio spring-integration-ip 6.0.0-M1
n
org.springframework.integratio spring-integration-jdbc 6.0.0-M1
n
org.springframework.integratio spring-integration-jms 6.0.0-M1
n
org.springframework.integratio spring-integration-jmx 6.0.0-M1
n
org.springframework.integratio spring-integration-jpa 6.0.0-M1
n
org.springframework.integratio spring-integration-kafka 6.0.0-M1
n
org.springframework.integratio spring-integration-mail 6.0.0-M1
n
org.springframework.integratio spring-integration-mongodb 6.0.0-M1
n
org.springframework.integratio spring-integration-mqtt 6.0.0-M1
n
org.springframework.integratio spring-integration-r2dbc 6.0.0-M1
n
org.springframework.integratio spring-integration-redis 6.0.0-M1
n
org.springframework.integratio spring-integration-rsocket 6.0.0-M1
n
org.springframework.integratio spring-integration-scripting 6.0.0-M1
n
org.springframework.integratio spring-integration-security 6.0.0-M1
n
org.springframework.integratio spring-integration-sftp 6.0.0-M1
n
org.springframework.integratio spring-integration-stomp 6.0.0-M1
n
org.springframework.integratio spring-integration-stream 6.0.0-M1
n
org.springframework.integratio spring-integration-syslog 6.0.0-M1
n
673
Group ID Artifact ID Version
org.springframework.integratio spring-integration-test 6.0.0-M1
n
org.springframework.integratio spring-integration-test- 6.0.0-M1
n support
org.springframework.integratio spring-integration-webflux 6.0.0-M1
n
org.springframework.integratio spring-integration-websocket 6.0.0-M1
n
org.springframework.integratio spring-integration-ws 6.0.0-M1
n
org.springframework.integratio spring-integration-xml 6.0.0-M1
n
org.springframework.integratio spring-integration-xmpp 6.0.0-M1
n
org.springframework.integratio spring-integration-zeromq 6.0.0-M1
n
org.springframework.integratio spring-integration-zookeeper 6.0.0-M1
n
org.springframework.kafka spring-kafka 3.0.0-M1
org.springframework.kafka spring-kafka-test 3.0.0-M1
org.springframework.ldap spring-ldap-core 3.0.0-M1
org.springframework.ldap spring-ldap-core-tiger 3.0.0-M1
org.springframework.ldap spring-ldap-ldif-batch 3.0.0-M1
org.springframework.ldap spring-ldap-ldif-core 3.0.0-M1
org.springframework.ldap spring-ldap-odm 3.0.0-M1
org.springframework.ldap spring-ldap-test 3.0.0-M1
org.springframework.restdocs spring-restdocs-asciidoctor 3.0.0-SNAPSHOT
org.springframework.restdocs spring-restdocs-core 3.0.0-SNAPSHOT
org.springframework.restdocs spring-restdocs-mockmvc 3.0.0-SNAPSHOT
org.springframework.restdocs spring-restdocs-restassured 3.0.0-SNAPSHOT
org.springframework.restdocs spring-restdocs-webtestclient 3.0.0-SNAPSHOT
org.springframework.retry spring-retry 1.3.1
org.springframework.security spring-security-acl 6.0.0-M1
org.springframework.security spring-security-aspects 6.0.0-M1
org.springframework.security spring-security-config 6.0.0-M1
org.springframework.security spring-security-core 6.0.0-M1
org.springframework.security spring-security-crypto 6.0.0-M1
org.springframework.security spring-security-data 6.0.0-M1
org.springframework.security spring-security-ldap 6.0.0-M1
org.springframework.security spring-security-messaging 6.0.0-M1
org.springframework.security spring-security-oauth2-client 6.0.0-M1
674
Group ID Artifact ID Version
org.springframework.security spring-security-oauth2-core 6.0.0-M1
org.springframework.security spring-security-oauth2-jose 6.0.0-M1
org.springframework.security spring-security-oauth2- 6.0.0-M1
resource-server
org.springframework.security spring-security-openid 6.0.0-M1
org.springframework.security spring-security-rsocket 6.0.0-M1
org.springframework.security spring-security-saml2-service- 6.0.0-M1
provider
org.springframework.security spring-security-taglibs 6.0.0-M1
org.springframework.security spring-security-test 6.0.0-M1
org.springframework.security spring-security-web 6.0.0-M1
org.springframework.session spring-session-core 3.0.0-M1
org.springframework.session spring-session-data-geode 3.0.0-M1
org.springframework.session spring-session-data-mongodb 3.0.0-M1
org.springframework.session spring-session-data-redis 3.0.0-M1
org.springframework.session spring-session-hazelcast 3.0.0-M1
org.springframework.session spring-session-jdbc 3.0.0-M1
org.springframework.ws spring-ws-core 4.0.0-M1
org.springframework.ws spring-ws-security 4.0.0-M1
org.springframework.ws spring-ws-support 4.0.0-M1
org.springframework.ws spring-ws-test 4.0.0-M1
org.springframework.ws spring-xml 4.0.0-M1
org.testcontainers azure 1.16.2
org.testcontainers cassandra 1.16.2
org.testcontainers clickhouse 1.16.2
org.testcontainers cockroachdb 1.16.2
org.testcontainers couchbase 1.16.2
org.testcontainers database-commons 1.16.2
org.testcontainers db2 1.16.2
org.testcontainers dynalite 1.16.2
org.testcontainers elasticsearch 1.16.2
org.testcontainers gcloud 1.16.2
org.testcontainers influxdb 1.16.2
org.testcontainers jdbc 1.16.2
org.testcontainers junit-jupiter 1.16.2
org.testcontainers kafka 1.16.2
org.testcontainers localstack 1.16.2
org.testcontainers mariadb 1.16.2
org.testcontainers mockserver 1.16.2
675
Group ID Artifact ID Version
org.testcontainers mongodb 1.16.2
org.testcontainers mssqlserver 1.16.2
org.testcontainers mysql 1.16.2
org.testcontainers neo4j 1.16.2
org.testcontainers nginx 1.16.2
org.testcontainers oracle-xe 1.16.2
org.testcontainers orientdb 1.16.2
org.testcontainers postgresql 1.16.2
org.testcontainers presto 1.16.2
org.testcontainers pulsar 1.16.2
org.testcontainers r2dbc 1.16.2
org.testcontainers rabbitmq 1.16.2
org.testcontainers selenium 1.16.2
org.testcontainers solr 1.16.2
org.testcontainers spock 1.16.2
org.testcontainers testcontainers 1.16.2
org.testcontainers toxiproxy 1.16.2
org.testcontainers trino 1.16.2
org.testcontainers vault 1.16.2
org.thymeleaf thymeleaf 3.1.0.M1
org.thymeleaf thymeleaf-spring6 3.1.0.M1
org.thymeleaf.extras thymeleaf-extras-java8time 3.0.4.RELEASE
org.thymeleaf.extras thymeleaf-extras- 3.1.0.M1
springsecurity6
org.webjars webjars-locator-core 0.48
org.xerial sqlite-jdbc 3.36.0.3
org.xmlunit xmlunit-assertj 2.8.4
org.xmlunit xmlunit-core 2.8.4
org.xmlunit xmlunit-legacy 2.8.4
org.xmlunit xmlunit-matchers 2.8.4
org.xmlunit xmlunit-placeholders 2.8.4
org.yaml snakeyaml 1.30
redis.clients jedis 3.8.0
wsdl4j wsdl4j 1.6.3
676
You can learn how to customize these versions in your application in the Build Tool Plugins
documentation.
677
Library Version Property
Hibernate Validator hibernate-validator.version
HikariCP hikaricp.version
HSQLDB hsqldb.version
HtmlUnit htmlunit.version
HttpAsyncClient httpasyncclient.version
HttpClient httpclient.version
HttpClient5 httpclient5.version
HttpCore httpcore.version
HttpCore5 httpcore5.version
InfluxDB Java influxdb-java.version
Jackson Bom jackson-bom.version
Jakarta Activation jakarta-activation.version
Jakarta Annotation jakarta-annotation.version
Jakarta JMS jakarta-jms.version
Jakarta Json jakarta-json.version
Jakarta Json Bind jakarta-json-bind.version
Jakarta Mail jakarta-mail.version
Jakarta Management jakarta-management.version
Jakarta Persistence jakarta-persistence.version
Jakarta Servlet jakarta-servlet.version
Jakarta Servlet JSP JSTL jakarta-servlet-jsp-jstl.version
Jakarta Transaction jakarta-transaction.version
Jakarta Validation jakarta-validation.version
Jakarta WebSocket jakarta-websocket.version
Jakarta WS RS jakarta-ws-rs.version
Jakarta XML Bind jakarta-xml-bind.version
Jakarta XML SOAP jakarta-xml-soap.version
Jakarta XML WS jakarta-xml-ws.version
Janino janino.version
Javax Cache javax-cache.version
Javax Money javax-money.version
Jaxen jaxen.version
Jaybird jaybird.version
JBoss Logging jboss-logging.version
JDOM2 jdom2.version
Jedis jedis.version
Jetty jetty.version
Jetty EL jetty-el.version
678
Library Version Property
Jetty Reactive HTTPClient jetty-reactive-httpclient.version
JMustache jmustache.version
jOOQ jooq.version
Json Path json-path.version
Json-smart json-smart.version
JsonAssert jsonassert.version
JSTL jstl.version
JTDS jtds.version
JUnit junit.version
JUnit Jupiter junit-jupiter.version
Kafka kafka.version
Kotlin kotlin.version
Kotlin Coroutines kotlin-coroutines.version
Lettuce lettuce.version
Liquibase liquibase.version
Log4j2 log4j2.version
Logback logback.version
Lombok lombok.version
MariaDB mariadb.version
Maven AntRun Plugin maven-antrun-plugin.version
Maven Assembly Plugin maven-assembly-plugin.version
Maven Clean Plugin maven-clean-plugin.version
Maven Compiler Plugin maven-compiler-plugin.version
Maven Dependency Plugin maven-dependency-plugin.version
Maven Deploy Plugin maven-deploy-plugin.version
Maven Enforcer Plugin maven-enforcer-plugin.version
Maven Failsafe Plugin maven-failsafe-plugin.version
Maven Help Plugin maven-help-plugin.version
Maven Install Plugin maven-install-plugin.version
Maven Invoker Plugin maven-invoker-plugin.version
Maven Jar Plugin maven-jar-plugin.version
Maven Javadoc Plugin maven-javadoc-plugin.version
Maven Resources Plugin maven-resources-plugin.version
Maven Shade Plugin maven-shade-plugin.version
Maven Source Plugin maven-source-plugin.version
Maven Surefire Plugin maven-surefire-plugin.version
Maven War Plugin maven-war-plugin.version
Micrometer micrometer.version
679
Library Version Property
MIMEPull mimepull.version
Mockito mockito.version
MongoDB mongodb.version
MSSQL JDBC mssql-jdbc.version
MySQL mysql.version
NekoHTML nekohtml.version
Neo4j Java Driver neo4j-java-driver.version
Netty netty.version
Netty tcNative netty-tcnative.version
OkHttp3 okhttp3.version
Oracle Database oracle-database.version
Postgresql postgresql.version
Prometheus Client prometheus-client.version
Quartz quartz.version
QueryDSL querydsl.version
R2DBC Bom r2dbc-bom.version
Rabbit AMQP Client rabbit-amqp-client.version
Rabbit Stream Client rabbit-stream-client.version
Reactive Streams reactive-streams.version
Reactor Bom reactor-bom.version
REST Assured rest-assured.version
RSocket rsocket.version
RxJava rxjava.version
RxJava Adapter rxjava-adapter.version
RxJava2 rxjava2.version
SAAJ Impl saaj-impl.version
Selenium selenium.version
Selenium HtmlUnit selenium-htmlunit.version
SendGrid sendgrid.version
Servlet API servlet-api.version
SLF4J slf4j.version
SnakeYAML snakeyaml.version
Solr solr.version
Spring AMQP spring-amqp.version
Spring Batch spring-batch.version
Spring Data Bom spring-data-bom.version
Spring Framework spring-framework.version
Spring HATEOAS spring-hateoas.version
680
Library Version Property
Spring Integration spring-integration.version
Spring Kafka spring-kafka.version
Spring LDAP spring-ldap.version
Spring RESTDocs spring-restdocs.version
Spring Retry spring-retry.version
Spring Security spring-security.version
Spring Session Bom spring-session-bom.version
Spring WS spring-ws.version
SQLite JDBC sqlite-jdbc.version
Sun Mail sun-mail.version
Thymeleaf thymeleaf.version
Thymeleaf Extras Data Attribute thymeleaf-extras-data-attribute.version
Thymeleaf Extras Java8Time thymeleaf-extras-java8time.version
Thymeleaf Extras SpringSecurity thymeleaf-extras-springsecurity.version
Thymeleaf Layout Dialect thymeleaf-layout-dialect.version
Tomcat tomcat.version
UnboundID LDAPSDK unboundid-ldapsdk.version
Undertow undertow.version
Versions Maven Plugin versions-maven-plugin.version
WebJars Locator Core webjars-locator-core.version
WSDL4j wsdl4j.version
XML Maven Plugin xml-maven-plugin.version
XmlUnit2 xmlunit2.version
Yasson yasson.version
681