Skip to content

Latest commit

 

History

History
2455 lines (1879 loc) · 95.1 KB

File metadata and controls

2455 lines (1879 loc) · 95.1 KB

‘How-to’ guides

Spring Boot application

Troubleshoot auto-configuration

The Spring Boot auto-configuration tries its best to ‘do the right thing’, but sometimes things fail and it can be hard to tell why.

There is a really useful AutoConfigurationReport available in any Spring Boot ApplicationContext. You will see it if you enable DEBUG logging output. If you use the spring-boot-actuator there is also an autoconfig endpoint that renders the report in JSON. Use that to debug the application and see what features have been added (and which not) by Spring Boot at runtime.

Many more questions can be answered by looking at the source code and the javadoc. Some rules of thumb:

  • Look for classes called *AutoConfiguration and read their sources, in particular the @Conditional* annotations to find out what features they enable and when. Add --debug to the command line or a System property -Ddebug to get a log on the console of all the autoconfiguration decisions that were made in your app. In a running Actuator app look at the autoconfig endpoint (‘/autoconfig’ or the JMX equivalent) for the same information.

  • Look for classes that are @ConfigurationProperties (e.g. {sc-spring-boot-autoconfigure}/web/ServerProperties.{sc-ext}[ServerProperties]) and read from there the available external configuration options. The @ConfigurationProperties has a name attribute which acts as a prefix to external properties, thus ServerProperties has prefix="server" and its configuration properties are server.port, server.address etc. In a running Actuator app look at the configprops endpoint.

  • Look for use of RelaxedEnvironment to pull configuration values explicitly out of the Environment. It often is used with a prefix.

  • Look for @Value annotations that bind directly to the Environment. This is less flexible than the RelaxedEnvironment approach, but does allow some relaxed binding, specifically for OS environment variables (so CAPITALS_AND_UNDERSCORES are synonyms for period.separated).

  • Look for @ConditionalOnExpression annotations that switch features on and off in response to SpEL expressions, normally evaluated with place-holders resolved from the Environment.

Customize the Environment or ApplicationContext before it starts

A SpringApplication has ApplicationListeners and ApplicationContextInitializers that are used to apply customizations to the context or environment. Spring Boot loads a number of such customizations for use internally from META-INF/spring.factories. There is more than one way to register additional ones:

  • Programmatically per application by calling the addListeners and addInitializers methods on SpringApplication before you run it.

  • Declaratively per application by setting context.initializer.classes or context.listener.classes.

  • Declaratively for all applications by adding a META-INF/spring.factories and packaging a jar file that the applications all use as a library.

The SpringApplication sends some special ApplicationEvents to the listeners (even some before the context is created), and then registers the listeners for events published by the ApplicationContext as well. See spring-boot-features.adoc in the ‘Spring Boot features’ section for a complete list.

Build an ApplicationContext hierarchy (adding a parent or root context)

You can use the ApplicationBuilder class to create parent/child ApplicationContext hierarchies. See spring-boot-features.adoc in the ‘Spring Boot features’ section for more information.

Create a non-web application

Not all Spring applications have to be web applications (or web services). If you want to execute some code in a main method, but also bootstrap a Spring application to set up the infrastructure to use, then it’s easy with the SpringApplication features of Spring Boot. A SpringApplication changes its ApplicationContext class depending on whether it thinks it needs a web application or not. The first thing you can do to help it is to just leave the servlet API dependencies off the classpath. If you can’t do that (e.g. you are running 2 applications from the same code base) then you can explicitly call SpringApplication.setWebEnvironment(false), 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.

Properties & configuration

Externalize the configuration of SpringApplication

A SpringApplication has bean properties (mainly setters) so you can use its Java API as you create the application to modify its behavior. Or you can externalize the configuration using properties in spring.main.*. E.g. in application.properties you might have.

spring.main.web_environment=false
spring.main.show_banner=false

and then the Spring Boot banner will not be printed on startup, and the application will not be a web application.

Note
The example above also demonstrates how flexible binding allows the use of underscores (_) as well as dashes (-) in property names.

Change the location of external properties of an application

By default properties from different sources are added to the Spring Environment in a defined order (see spring-boot-features.adoc in the ‘Spring Boot features’ section for the exact order).

A nice way to augment and modify this is to add @PropertySource annotations to your application sources. Classes passed to the SpringApplication static convenience methods, and those added using setSources() are inspected to see if they have @PropertySources, and if they do, those properties are added to the Environment early enough to be used in all phases of the ApplicationContext lifecycle. Properties added in this way have precedence over any added using the default locations, but have lower priority than system properties, environment variables or the command line.

You can also provide System properties (or environment variables) to change the behavior:

  • spring.config.name (SPRING_CONFIG_NAME), defaults to application as the root of the file name.

  • spring.config.location (SPRING_CONFIG_LOCATION) is the file to load (e.g. a classpath resource or a URL). A separate Environment property source is set up for this document and it can be overridden by system properties, environment variables or the command line.

No matter what you set in the environment, Spring Boot will always load application.properties as described above. If YAML is used then files with the ‘.yml’ extension are also added to the list by default.

See {sc-spring-boot}/context/config/ConfigFileApplicationListener.{sc-ext}[ConfigFileApplicationListener] for more detail.

Use ‘short’ command line arguments

Some people like to use (for example) --port=9000 instead of --server.port=9000 to set configuration properties on the command line. You can easily enable this by using placeholders in application.properties, e.g.

server.port=${port:8080}
Tip
If you are inheriting from the spring-boot-starter-parent POM, the default filter token of the maven-resources-plugins has been changed from ${*} to @ (i.e. @maven.token@ instead of ${maven.token}) to prevent conflicts with Spring-style placeholders. If you have enabled maven filtering for the application.properties directly, you may want to also change the default filter token to use other delimiters.
Note
In this specific case the port binding will work in a PaaS environment like Heroku and Cloud Foundry, since in those two platforms the PORT environment variable is set automatically and Spring can bind to capitalized synonyms for Environment properties.

Use YAML for external properties

YAML is a superset of JSON and as such is a very convenient syntax for storing external properties in a hierarchical format. E.g.

spring:
	application:
		name: cruncher
	datasource:
		driverClassName: com.mysql.jdbc.Driver
		url: jdbc:mysql://localhost/test
server:
	port: 9000

Create a file called application.yml and stick it in the root of your classpath, and also add snakeyaml to your dependencies (Maven coordinates org.yaml:snakeyaml, already included if you use the spring-boot-starter). A YAML file is parsed to a Java Map<String,Object> (like a JSON object), and Spring Boot flattens the map so that it is 1-level deep and has period-separated keys, a lot like people are used to with Properties files in Java.

The example YAML above corresponds to an application.properties file

spring.application.name=cruncher
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/test
server.port=9000

See spring-boot-features.adoc in the ‘Spring Boot features’ section for more information about YAML.

Set the active Spring profiles

The Spring Environment has an API for this, but normally you would set a System profile (spring.profiles.active) or an OS environment variable (SPRING_PROFILES_ACTIVE). E.g. launch your application with a -D argument (remember to put it before the main class or jar archive):

$ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar

In Spring Boot you can also set the active profile in application.properties, e.g.

spring.profiles.active=production

A value set this way is replaced by the System property or environment variable setting, but not by the SpringApplicationBuilder.profiles() method. Thus the latter Java API can be used to augment the profiles without changing the defaults.

See spring-boot-features.adoc in the ‘Spring Boot features’ section for more information.

Change configuration depending on the environment

A YAML file is actually a sequence of documents separated by --- lines, and each document is parsed separately to a flattened map.

If a YAML document contains a spring.profiles key, then the profiles value (comma-separated list of profiles) is fed into the Spring Environment.acceptsProfiles() and if any of those profiles is active that document is included in the final merge (otherwise not).

Example:

server:
	port: 9000
---

spring:
	profiles: development
server:
	port: 9001

---

spring:
	profiles: production
server:
	port: 0

In this example the default port is 9000, but if the Spring profile ‘development’ is active then the port is 9001, and if ‘production’ is active then it is 0.

The YAML documents are merged in the order they are encountered (so later values override earlier ones).

To do the same thing with properties files you can use application-${profile}.properties to specify profile-specific values.

Discover built-in options for external properties

Spring Boot binds external properties from application.properties (or .yml) (and other places) into an application at runtime. There is not (and technically cannot be) an exhaustive list of all supported properties in a single location because contributions can come from additional jar files on your classpath.

A running application with the Actuator features has a configprops endpoint that shows all the bound and bindable properties available through @ConfigurationProperties.

The appendix includes an 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 RelaxedEnvironment.

Embedded servlet containers

Add a Servlet, Filter or ServletContextListener to an application

Servlet, Filter, ServletContextListener and the other listeners supported by the Servlet spec can be added to your application as @Bean definitions. Be very careful that they don’t cause eager initialization of too many other beans because they have to be installed in the container very early in the application lifecycle (e.g. it’s not a good idea to have them depend on your DataSource or JPA configuration). You can work around restrictions like that by initializing them lazily when first used instead of on initialization.

In the case of Filters and Servlets you can also add mappings and init parameters by adding a FilterRegistrationBean or ServletRegistrationBean instead of or as well as the underlying component.

Change the HTTP port

In a standalone application the main HTTP port defaults to 8080, but can be set with server.port (e.g. in application.properties or as a System property). Thanks to relaxed binding of Environment values you can also use SERVER_PORT (e.g. as an OS environment variable).

To switch off the HTTP endpoints completely, but still create a WebApplicationContext, use server.port=-1 (this is sometimes useful for testing).

For more details look at spring-boot-features.adoc in the ‘Spring Boot features’ section, or the {sc-spring-boot-autoconfigure}/web/ServerProperties.{sc-ext}[ServerProperties] source code.

Use a random unassigned HTTP port

To scan for a free port (using OS natives to prevent clashes) use server.port=0.

Discover the HTTP port at runtime

You can access the port the server is running on from log output or from the EmbeddedWebApplicationContext via its EmbeddedServletContainer. The best way to get that and be sure that it has initialized is to add a @Bean of type ApplicationListener<EmbeddedServletContainerInitializedEvent> and pull the container out of the event when it is published.

A useful practice for use with @WebIntegrationTests is to set server.port=0 and then inject the actual (‘local’) port as a @Value. For example:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleDataJpaApplication.class)
@WebIntegrationTest("server.port:0")
public class CityRepositoryIntegrationTests {

	@Autowired
	EmbeddedWebApplicationContext server;

	@Value("${local.server.port}")
	int port;

	// ...

}

Configure SSL

SSL can be configured declaratively by setting the various server.ssl.* properties, typically in application.properties or application.yml. For example:

server.port = 8443
server.ssl.key-store = classpath:keystore.jks
server.ssl.key-store-password = secret
server.ssl.key-password = another-secret

See {sc-spring-boot}/context/embedded/Ssl.{sc-ext}[Ssl] for details of all of the supported properties.

Note
Tomcat requires the key store (and trust store if you’re using one) to be directly accessible on the filesystem, i.e. it cannot be read from within a jar file. This limitation doesn’t apply to Jetty and Undertow.

Using configuration like the example above means the application will no longer support plain HTTP connector at port 8080. Spring Boot doesn’t support the configuration of both an HTTP connector and an HTTPS connector via application.properties. If you want to have both then you’ll need to configure one of them programmatically. It’s recommended to use application.properties to configure HTTPS as the HTTP connector is the easier of the two to configure programmatically. See the {github-code}/spring-boot-samples/spring-boot-sample-tomcat-multi-connectors[spring-boot-sample-tomcat-multi-connectors] sample project for an example.

Configure Tomcat

Generally you can follow the advice from Discover built-in options for external properties about @ConfigurationProperties (ServerProperties is the main one here), but also look at EmbeddedServletContainerCustomizer and various Tomcat-specific *Customizers that you can add in one of those. The Tomcat APIs are quite rich so once you have access to the TomcatEmbeddedServletContainerFactory you can modify it in a number of ways. Or the nuclear option is to add your own TomcatEmbeddedServletContainerFactory.

Enable Multiple Connectors with Tomcat

Add a org.apache.catalina.connector.Connector to the TomcatEmbeddedServletContainerFactory which can allow multiple connectors, e.g. HTTP and HTTPS connector:

@Bean
public EmbeddedServletContainerFactory servletContainer() {
	TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
	tomcat.addAdditionalTomcatConnectors(createSslConnector());
	return tomcat;
}

private Connector createSslConnector() {
	Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
	Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
	try {
		File keystore = new ClassPathResource("keystore").getFile();
		File truststore = new ClassPathResource("keystore").getFile();
		connector.setScheme("https");
		connector.setSecure(true);
		connector.setPort(8443);
		protocol.setSSLEnabled(true);
		protocol.setKeystoreFile(keystore.getAbsolutePath());
		protocol.setKeystorePass("changeit");
		protocol.setTruststoreFile(truststore.getAbsolutePath());
		protocol.setTruststorePass("changeit");
		protocol.setKeyAlias("apitester");
		return connector;
	}
	catch (IOException ex) {
		throw new IllegalStateException("can't access keystore: [" + "keystore"
				+ "] or truststore: [" + "keystore" + "]", ex);
	}
}

Use Tomcat behind a front-end proxy server

Spring Boot will automatically configure Tomcat’s RemoteIpValve if you enable it. This allows you to transparently use the standard x-forwarded-for and x-forwarded-proto headers that most front-end proxy servers add. The valve is switched on by setting one or both of these properties to something non-empty (these are the conventional values used by most proxies, and if you only set one the other will be set automatically):

server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto

If your proxy uses different headers you can customize the valve’s configuration by adding some entries to application.properties, e.g.

server.tomcat.remote_ip_header=x-your-remote-ip-header
server.tomcat.protocol_header=x-your-protocol-header

The valve is also configured with a default regular expression that matches internal proxies that are to be trusted. By default, IP addresses in 10/8, 192.168/16, 169.254/16 and 127/8 are trusted. You can customize the valve’s configuration by adding an entry to application.properties, e.g.

server.tomcat.internal_proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}
Note
The double backslashes are only required when you’re using a properties file for configuration. If you are using YAML, single backslashes are sufficient and a value that’s equivalent to the one shown above would be 192\.168\.\d{1,3}\.\d{1,3}.

Alternatively, you can take complete control of the configuration of the RemoteIpValve by configuring and adding it in a TomcatEmbeddedServletContainerFactory bean.

Use Jetty instead of Tomcat

The Spring Boot starters (spring-boot-starter-web in particular) use Tomcat as an embedded container by default. You need to exclude those dependencies and include the Jetty one instead. Spring Boot provides Tomcat and Jetty dependencies bundled together as separate starters to help make this process as easy as possible.

Example in Maven:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	<exclusions>
		<exclusion>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

Example in Gradle:

configurations {
	compile.exclude module: "spring-boot-starter-tomcat"
}

dependencies {
	compile("org.springframework.boot:spring-boot-starter-web:{spring-boot-version}")
	compile("org.springframework.boot:spring-boot-starter-jetty:{spring-boot-version}")
	// ...
}

Configure Jetty

Generally you can follow the advice from Discover built-in options for external properties about @ConfigurationProperties (ServerProperties is the main one here), but also look at EmbeddedServletContainerCustomizer. The Jetty APIs are quite rich so once you have access to the JettyEmbeddedServletContainerFactory you can modify it in a number of ways. Or the nuclear option is to add your own JettyEmbeddedServletContainerFactory.

Use Undertow instead of Tomcat

Using Undertow instead of Tomcat is very similar to using Jetty instead of Tomcat. You need to exclude the Tomcat dependencies and include the Undertow starter instead.

Example in Maven:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	<exclusions>
		<exclusion>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

Example in Gradle:

configurations {
	compile.exclude module: "spring-boot-starter-tomcat"
}

dependencies {
	compile 'org.springframework.boot:spring-boot-starter-web:{spring-boot-version}")
	compile 'org.springframework.boot:spring-boot-starter-undertow:{spring-boot-version}")
	// ...
}

Configure Undertow

Generally you can follow the advice from Discover built-in options for external properties about @ConfigurationProperties (ServerProperties and ServerProperties.Undertow are the main ones here), but also look at EmbeddedServletContainerCustomizer. Once you have access to the UndertowEmbeddedServletContainerFactory you can use an UndertowBuilderCustomizer to modify Undertow’s configuration to meet your needs. Or the nuclear option is to add your own UndertowEmbeddedServletContainerFactory.

Enable Multiple Listeners with Undertow

Add an UndertowBuilderCustomizer to the UndertowEmbeddedServletContainerFactory and add a listener to the Builder:

@Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
	UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
	factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {

		@Override
		public void customize(Builder builder) {
			builder.addHttpListener(8080, "0.0.0.0");
		}

	});
	return factory;
}

Use Tomcat 7

Tomcat 7 works with Spring Boot, but the default is to use Tomcat 8. If you cannot use Tomcat 8 (for example, because you are using Java 1.6) you will need to change your classpath to reference Tomcat 7 .

Use Tomcat 7 with Maven

If you are using the starter poms and parent you can just change the Tomcat version property, e.g. for a simple webapp or service:

<properties>
	<tomcat.version>7.0.56</tomcat.version>
</properties>
<dependencies>
	...
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	...
</dependencies>

Use Tomcat 7 with Gradle

You can use a resolution strategy to change the versions of the Tomcat dependencies, e.g. for a simple webapp or service:

configurations.all {
	resolutionStrategy {
		eachDependency {
			if (it.requested.group == 'org.apache.tomcat.embed') {
				it.useVersion '7.0.56'
			}
		}
	}
}

dependencies {
	compile 'org.springframework.boot:spring-boot-starter-web'
}

Use Jetty 8

Jetty 8 works with Spring Boot, but the default is to use Jetty 9. If you cannot use Jetty 9 (for example, because you are using Java 1.6) you will need to change your classpath to reference Jetty 8. You will also need to exclude Jetty’s WebSocket-related dependencies.

Use Jetty 8 with Maven

If you are using the starter poms and parent you can just add the Jetty starter with the required WebSocket exclusion and change the version properties, e.g. for a simple webapp or service:

<properties>
	<jetty.version>8.1.15.v20140411</jetty.version>
	<jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.version>
</properties>
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
		<exclusions>
			<exclusion>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-starter-tomcat</artifactId>
			</exclusion>
		</exclusions>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-jetty</artifactId>
		<exclusions>
			<exclusion>
				<groupId>org.eclipse.jetty.websocket</groupId>
				<artifactId>*</artifactId>
			</exclusion>
		</exclusions>
	</dependency>
</dependencies>

Use Jetty 8 with Gradle

You can use a resolution strategy to change the version of the Jetty dependencies, e.g. for a simple webapp or service:

configurations.all {
	resolutionStrategy {
		eachDependency {
			if (it.requested.group == 'org.eclipse.jetty') {
				it.useVersion '8.1.15.v20140411'
			}
		}
	}
}

dependencies {
	compile ('org.springframework.boot:spring-boot-starter-web') {
		exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
	}
	compile ('org.springframework.boot:spring-boot-starter-jetty') {
		exclude group: 'org.eclipse.jetty.websocket'
	}
}

Create WebSocket endpoints using @ServerEndpoint

If you want to use @ServerEndpoint in a Spring Boot application that used an embedded container, you must declare a single ServerEndpointExporter @Bean:

@Bean
public ServerEndpointExporter serverEndpointExporter() {
	return new ServerEndpointExporter();
}

This bean will register any @ServerEndpoint annotated beans with the underlying WebSocket container. When deployed to a standalone servlet container this role is performed by a servlet container initializer and the ServerEndpointExporter bean is not required.

Enable HTTP response compression

Spring Boot provides two mechanisms for enabling compression of HTTP compression; one that is Tomcat-specific and another that uses a filter and works with Jetty, Tomcat, and Undertow.

Enable Tomcat’s HTTP response compression

Tomcat provides built-in support for HTTP response compression. It is disabled by default, but can easily be enabled via application.properties:

server.tomcat.compression: on

When set to on Tomcat will compress responses with a length that is at least 2048 bytes. This limit can be configured by specifying an integer value rather than on, e.g.:

server.tomcat.compression: 4096

By default Tomcat will only compress responses with certain MIME types (text/html, text/xml, and text/plain). You can customize this using the server.tomcat.compressableMimeTypes property, e.g.:

server.tomcat.compressableMimeTypes=application/json,application/xml

Enable HTTP response compression using GzipFilter

If you’re using Jetty or Undertow, or you want more sophisticated control over HTTP response compression, Spring Boot provides auto-configuration for Jetty’s GzipFilter. While this filter is part of Jetty, it’s compatible with Tomcat and Undertow as well. To enable the filter, simply add a dependency on org.eclipse.jetty:jetty-servlets to your application.

GzipFilter can be configured using the spring.http.gzip.* properties. See {sc-spring-boot-autoconfigure}/web/GzipFilterProperties.{sc-ext}[GzipFilterProperties] for more details.

Spring MVC

Write a JSON REST service

Any Spring @RestController in a Spring Boot application should render JSON response by default as long as Jackson2 is on the classpath. For example:

@RestController
public class MyController {

	@RequestMapping("/thing")
	public MyThing thing() {
			return new MyThing();
	}

}

As long as MyThing can be serialized by Jackson2 (e.g. a normal POJO or Groovy object) then http://localhost:8080/thing will serve a JSON representation of it by default. Sometimes in a browser you might see XML responses because browsers tend to send accept headers that prefer XML.

Write an XML REST service

If you have the Jackson XML extension (jackson-dataformat-xml) on the classpath, it will be used to render XML responses and the very same example as we used for JSON would work. To use it, add the following dependency to your project:

<dependency>
	<groupId>com.fasterxml.jackson.dataformat</groupId>
	<artifactId>jackson-dataformat-xml</artifactId>
</dependency>

You may also want to add a dependency on Woodstox. It’s faster than the default Stax implementation provided by the JDK and also adds pretty print support and improved namespace handling:

<dependency>
	<groupId>org.codehaus.woodstox</groupId>
	<artifactId>woodstox-core-asl</artifactId>
</dependency>

If Jackson’s XML extension is not available, JAXB (provided by default in the JDK) will be used, with the additional requirement to have MyThing annotated as @XmlRootElement:

@XmlRootElement
public class MyThing {
	private String name;
	// .. getters and setters
}

To get the server to render XML instead of JSON you might have to send an Accept: text/xml header (or use a browser).

Customize the Jackson ObjectMapper

Spring MVC (client and server side) uses HttpMessageConverters to negotiate content conversion in an HTTP exchange. If Jackson is on the classpath you already get the default converter(s) provided by Jackson2ObjectMapperBuilder.

The ObjectMapper (or XmlMapper for Jackson XML converter) instance created by default have the following customized properties:

  • MapperFeature.DEFAULT_VIEW_INCLUSION is disabled

  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES is disabled

Spring Boot has also some features to make it easier to customize this behavior.

You can configure the ObjectMapper and XmlMapper instances using the environment. Jackson provides an extensive suite of simple on/off features that can be used to configure various aspects of its processing. These features are described in five enums in Jackson which map onto properties in the environment:

Jackson enum Environment property

com.fasterxml.jackson.databind.DeserializationFeature

spring.jackson.deserialization.<feature_name>=true|false

com.fasterxml.jackson.core.JsonGenerator.Feature

spring.jackson.generator.<feature_name>=true|false

com.fasterxml.jackson.databind.MapperFeature

spring.jackson.mapper.<feature_name>=true|false

com.fasterxml.jackson.core.JsonParser.Feature

spring.jackson.parser.<feature_name>=true|false

com.fasterxml.jackson.databind.SerializationFeature

spring.jackson.serialization.<feature_name>=true|false

For example, to enable pretty print, set spring.jackson.serialization.indent_output=true. Note that, thanks to the use of relaxed binding, the case of indent_output doesn’t have to match the case of the corresponding enum constant which is INDENT_OUTPUT.

If you want to replace the default ObjectMapper completely, define a @Bean of that type and mark it as @Primary.

Defining a @Bean of type Jackson2ObjectMapperBuilder will allow you to customize both default ObjectMapper and XmlMapper (used in MappingJackson2HttpMessageConverter and MappingJackson2XmlHttpMessageConverter respectively).

Another way to customize Jackson is to add beans of type com.fasterxml.jackson.databind.Module to your context. They will be registered with every bean of type ObjectMapper, providing a global mechanism for contributing custom modules when you add new features to your application.

Finally, if you provide any @Beans of type MappingJackson2HttpMessageConverter then they will replace the default value in the MVC configuration. Also, a convenience bean is provided of type HttpMessageConverters (always available if you use the default MVC configuration) which has some useful methods to access the default and user-enhanced message converters.

See also the Customize the @ResponseBody rendering section and the {sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[WebMvcAutoConfiguration] source code for more details.

Customize the @ResponseBody rendering

Spring uses HttpMessageConverters to render @ResponseBody (or responses from @RestController). You can contribute additional converters by simply adding beans of that type in a Spring Boot context. If a bean you add is of a type that would have been included by default anyway (like MappingJackson2HttpMessageConverter for JSON conversions) then it will replace the default value. A convenience bean is provided of type HttpMessageConverters (always available if you use the default MVC configuration) which has some useful methods to access the default and user-enhanced message converters (useful, for example if you want to manually inject them into a custom RestTemplate).

As in normal MVC usage, any WebMvcConfigurerAdapter beans that you provide can also contribute converters by overriding the configureMessageConverters method, but unlike with normal MVC, you can supply only additional converters that you need (because Spring Boot uses the same mechanism to contribute its defaults). Finally, if you opt-out of the Spring Boot default MVC configuration by providing your own @EnableWebMvc configuration, then you can take control completely and do everything manually using getMessageConverters from WebMvcConfigurationSupport.

See the {sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[WebMvcAutoConfiguration] source code for more details.

Handling Multipart File Uploads

Spring Boot embraces the Servlet 3 javax.servlet.http.Part API to support uploading files. By default Spring Boot configures Spring MVC with a maximum file of 1Mb per file and a maximum of 10Mb of file data in a single request. You may override these values, as well as the location to which intermediate data is stored (e.g., to the /tmp directory) and the threshold past which data is flushed to disk by using the properties exposed in the MultipartProperties class. If you want to specify that files be unlimited, for example, set the multipart.maxFileSize property to -1.

The multipart support is helpful when you want to receive multipart encoded file data as a @RequestParam-annotated parameter of type MultipartFile in a Spring MVC controller handler method.

See the {sc-spring-boot-autoconfigure}/web/MultipartAutoConfiguration.{sc-ext}[MultipartAutoConfiguration] source for more details.

Switch off the Spring MVC DispatcherServlet

Spring Boot wants to serve all content from the root of your application / down. If you would rather map your own servlet to that URL you can do it, but of course you may lose some of the other Boot MVC features. To add your own servlet and map it to the root resource just declare a @Bean of type Servlet and give it the special bean name dispatcherServlet (You can also create a bean of a different type with that name if you want to switch it off and not replace it).

Switch off the Default MVC configuration

The easiest way to take complete control over MVC configuration is to provide your own @Configuration with the @EnableWebMvc annotation. This will leave all MVC configuration in your hands.

Customize ViewResolvers

A ViewResolver is a core component of Spring MVC, translating view names in @Controller to actual View implementations. Note that ViewResolvers are mainly used in UI applications, rather than REST-style services (a View is not used to render a @ResponseBody). There are many implementations of ViewResolver to choose from, and Spring on its own is not opinionated about which ones you should use. Spring Boot, on the other hand, installs one or two for you depending on what it finds on the classpath and in the application context. The DispatcherServlet uses all the resolvers it finds in the application context, trying each one in turn until it gets a result, so if you are adding your own you have to be aware of the order and in which position your resolver is added.

WebMvcAutoConfiguration adds the following ViewResolvers to your context:

  • An InternalResourceViewResolver with bean id ‘defaultViewResolver’. This one locates physical resources that can be rendered using the DefaultServlet (e.g. static resources and JSP pages if you are using those). It applies a prefix and a suffix to the view name and then looks for a physical resource with that path in the servlet context (defaults are both empty, but accessible for external configuration via spring.view.prefix and spring.view.suffix). It can be overridden by providing a bean of the same type.

  • A BeanNameViewResolver with id ‘beanNameViewResolver’. This is a useful member of the view resolver chain and will pick up any beans with the same name as the View being resolved. It shouldn’t be necessary to override or replace it.

  • A ContentNegotiatingViewResolver with id ‘viewResolver’ is only added if there are actually beans of type View present. This is a ‘master’ resolver, delegating to all the others and attempting to find a match to the ‘Accept’ HTTP header sent by the client. There is a useful blog about ContentNegotiatingViewResolver that you might like to study to learn more, and also look at the source code for detail. You can switch off the auto-configured ContentNegotiatingViewResolver by defining a bean named ‘viewResolver’.

  • If you use Thymeleaf you will also have a ThymeleafViewResolver with id ‘thymeleafViewResolver’. It looks for resources by surrounding the view name with a prefix and suffix (externalized to spring.thymeleaf.prefix and spring.thymeleaf.suffix, defaults ‘classpath:/templates/’ and ‘.html’ respectively). It can be overridden by providing a bean of the same name.

  • If you use FreeMarker you will also have a FreeMarkerViewResolver with id ‘freeMarkerViewResolver’. It looks for resources in a loader path (externalized to spring.freemarker.templateLoaderPath, default ‘classpath:/templates/’) by surrounding the view name with a prefix and suffix (externalized to spring.freemarker.prefix and spring.freemarker.suffix, with empty and ‘.ftl’ defaults respectively). It can be overridden by providing a bean of the same name.

  • If you use Groovy templates (actually if groovy-templates is on your classpath) you will also have a Groovy TemplateViewResolver with id ‘groovyTemplateViewResolver’. It looks for resources in a loader path by surrounding the view name with a prefix and suffix (externalized to spring.groovy.template.prefix and spring.groovy.template.suffix, defaults ‘classpath:/templates/’ and ‘.tpl’ respectively). It can be overriden by providing a bean of the same name.

  • If you use Velocity you will also have a VelocityViewResolver with id ‘velocityViewResolver’. It looks for resources in a loader path (externalized to spring.velocity.resourceLoaderPath, default ‘classpath:/templates/’) by surrounding the view name with a prefix and suffix (externalized to spring.velocity.prefix and spring.velocity.suffix, with empty and ‘.vm’ defaults respectively). It can be overridden by providing a bean of the same name.

Check out {sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[WebMvcAutoConfiguration], {sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[ThymeleafAutoConfiguration], {sc-spring-boot-autoconfigure}/freemarker/FreeMarkerAutoConfiguration.{sc-ext}[FreeMarkerAutoConfiguration], {sc-spring-boot-autoconfigure}/groovy/template/GroovyTemplateAutoConfiguration.{sc-ext}[GroovyTemplateAutoConfiguration] and {sc-spring-boot-autoconfigure}/velocity/VelocityAutoConfiguration.{sc-ext}[VelocityAutoConfiguration]

Logging

Spring Boot has no mandatory logging dependence, except for the commons-logging API, of which there are many implementations to choose from. To use Logback you need to include it, and some bindings for commons-logging on the classpath. The simplest way to do that is through the starter poms which all depend on spring-boot-starter-logging. For a web application you only need spring-boot-starter-web since it depends transitively on the logging starter. For example, using Maven:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot has a LoggingSystem abstraction that attempts to configure logging based on the content of the classpath. If Logback is available it is the first choice.

If the only change you need to make to logging is to set the levels of various loggers then you can do that in application.properties using the "logging.level" prefix, e.g.

logging.level.org.springframework.web: DEBUG
logging.level.org.hibernate: ERROR

You can also set the location of a file to log to (in addition to the console) using "logging.file".

To configure the more fine-grained settings of a logging system you need to use the native configuration format supported by the LoggingSystem in question. By default Spring Boot picks up the native configuration from its default location for the system (e.g. classpath:logback.xml for Logback), but you can set the location of the config file using the "logging.config" property.

Configure Logback for logging

If you put a logback.xml in the root of your classpath it will be picked up from there. Spring Boot provides a default base configuration that you can include if you just want to set levels, e.g.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<include resource="org/springframework/boot/logging/logback/base.xml"/>
	<logger name="org.springframework.web" level="DEBUG"/>
</configuration>

If you look at the default logback.xml in the spring-boot jar you will see that it uses some useful System properties which the LoggingSystem takes care of creating for you. These are:

  • ${PID} the current process ID.

  • ${LOG_FILE} if logging.file was set in Boot’s external configuration.

  • ${LOG_PATH} if logging.path was set (representing a directory for log files to live in).

Spring Boot also provides some nice ANSI colour terminal output on a console (but not in a log file) using a custom Logback converter. See the default base.xml configuration for details.

If Groovy is on the classpath you should be able to configure Logback with logback.groovy as well (it will be given preference if present).

Configure Log4j for logging

Spring Boot also supports either Log4j or Log4j 2 for logging configuration, but only if one of them is on the classpath. If you are using the starter poms for assembling dependencies that means you have to exclude Logback and then include your chosen version of Log4j instead. If you aren’t using the starter poms then you need to provide commons-logging (at least) in addition to your chosen version of Log4j.

The simplest path is probably through the starter poms, even though it requires some jiggling with excludes, .e.g. 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-log4j</artifactId>
</dependency>

To use Log4j 2, simply depend on spring-boot-starter-log4j2 rather than spring-boot-starter-log4j.

Note
The use of one of the Log4j starters gathers together the dependencies for common logging requirements (e.g. including having Tomcat use java.util.logging but configuring the output using Log4j or Log4j 2). See the Actuator Log4j or Log4j 2 samples for more detail and to see it in action.

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 all you need to do is add an appropriate dependency to the classpath. To use YAML, add a dependency on com.fasterxml.jackson.dataformat:jackson-dataformat-yaml and Log4j 2 will look for configuration files names log4j2.yaml or log4j2.yml. To use JSON, add a dependency on com.fasterxml.jackson.core:jackson-databind and Log4j 2 will look for configuration files named log4j2.json or log4j2.jsn

Data Access

Configure a DataSource

To override the default settings just define a @Bean of your own of type DataSource. Spring Boot provides a utility builder class DataSourceBuilder that can be used to create one of the standard ones (if it is on the classpath), or you can just create your own, and bind it to a set of Environment properties as explained in spring-boot-features.adoc, e.g.

@Bean
@ConfigurationProperties(prefix="datasource.mine")
public DataSource dataSource() {
	return new FancyDataSource();
}
datasource.mine.jdbcUrl=jdbc:h2:mem:mydb
datasource.mine.user=sa
datasource.mine.poolSize=30

See spring-boot-features.adoc in the ‘Spring Boot features’ section and the {sc-spring-boot-autoconfigure}/jdbc/DataSourceAutoConfiguration.{sc-ext}[DataSourceAutoConfiguration] class for more details.

Configure Two DataSources

Creating more than one data source works the same as creating the first one. You might want to mark one of them as @Primary if you are using the default auto-configuration for JDBC or JPA (then that one will be picked up by any @Autowired injections).

@Bean
@Primary
@ConfigurationProperties(prefix="datasource.primary")
public DataSource primaryDataSource() {
	return DataSourceBuilder.create().build();
}

@Bean
@ConfigurationProperties(prefix="datasource.secondary")
public DataSource secondaryDataSource() {
	return DataSourceBuilder.create().build();
}

Use Spring Data repositories

Spring Data can create implementations for you of @Repository interfaces of various flavors. Spring Boot will handle all of that for you as long as those @Repositories are included in the same package (or a sub-package) of your @EnableAutoConfiguration class.

For many applications all you will need is to put the right Spring Data dependencies on your classpath (there is a spring-boot-starter-data-jpa for JPA and a spring-boot-starter-data-mongodb for Mongodb), create some repository interfaces to handle your @Entity objects. Examples are in the {github-code}/spring-boot-samples/spring-boot-sample-data-jpa[JPA sample] or the {github-code}/spring-boot-samples/spring-boot-sample-data-mongodb[Mongodb sample].

Spring Boot tries to guess the location of your @Repository definitions, based on the @EnableAutoConfiguration it finds. To get more control, use the @EnableJpaRepositories annotation (from Spring Data JPA).

Separate @Entity definitions from Spring configuration

Spring Boot tries to guess the location of your @Entity definitions, based on the @EnableAutoConfiguration it finds. To get more control, you can use the @EntityScan annotation, e.g.

@Configuration
@EnableAutoConfiguration
@EntityScan(basePackageClasses=City.class)
public class Application {

	//...

}

Configure JPA properties

Spring Data JPA already provides some vendor-independent configuration options (e.g. for SQL logging) and Spring Boot exposes those, and a few more for hibernate as external configuration properties. The most common options to set are:

spring.jpa.hibernate.ddl-auto: create-drop
spring.jpa.hibernate.naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.database: H2
spring.jpa.show-sql: true

(Because of relaxed data binding hyphens or underscores should work equally well as property keys.) The ddl-auto setting is a special case in that it has different defaults depending on whether you are using an embedded database (create-drop) or not (none). In addition all properties in spring.jpa.properties.* are passed through as normal JPA properties (with the prefix stripped) when the local EntityManagerFactory is created.

See {sc-spring-boot-autoconfigure}/orm/jpa/HibernateJpaAutoConfiguration.{sc-ext}[HibernateJpaAutoConfiguration] and {sc-spring-boot-autoconfigure}/orm/jpa/JpaBaseConfiguration.{sc-ext}[JpaBaseConfiguration] for more details.

Use a custom EntityManagerFactory

To take full control of the configuration of the EntityManagerFactory, you need to add a @Bean named ‘entityManagerFactory’. Spring Boot auto-configuration switches off its entity manager based on the presence of a bean of that type.

Use Two EntityManagers

Even if the default EntityManagerFactory works fine, you will need to define a new one because otherwise the presence of the second bean of that type will switch off the default. To make it easy to do that you can use the convenient EntityManagerBuilder provided by Spring Boot, or if you prefer you can just use the LocalContainerEntityManagerFactoryBean directly from Spring ORM.

Example:

// add two data sources configured as above

@Bean
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
		EntityManagerFactoryBuilder builder) {
	return builder
			.dataSource(customerDataSource())
			.packages(Customer.class)
			.persistenceUnit("customers")
			.build();
}

@Bean
public LocalContainerEntityManagerFactoryBean orderEntityManagerFactory(
		EntityManagerFactoryBuilder builder) {
	return builder
			.dataSource(orderDataSource())
			.packages(Order.class)
			.persistenceUnit("orders")
			.build();
}

The configuration above almost works on its own. To complete the picture you need to configure TransactionManagers for the two EntityManagers as well. One of them could be picked up by the default JpaTransactionManager in Spring Boot if you mark it as @Primary. The other would have to be explicitly injected into a new instance. Or you might be able to use a JTA transaction manager spanning both.

Use a traditional persistence.xml

Spring doesn’t require the use of XML to configure the JPA provider, and Spring Boot assumes you want to take advantage of that feature. If you prefer to use persistence.xml then you need to define your own @Bean of type LocalEntityManagerFactoryBean (with id ‘entityManagerFactory’, and set the persistence unit name there.

See JpaBaseConfiguration for the default settings.

Use Spring Data JPA and Mongo repositories

Spring Data JPA and Spring Data Mongo can both create Repository implementations for you automatically. If they are both present on the classpath, you might have to do some extra configuration to tell Spring Boot which one (or both) you want to create repositories for you. The most explicit way to do that is to use the standard Spring Data @Enable*Repositories and tell it the location of your Repository interfaces (where ‘*’ is ‘Jpa’ or ‘Mongo’ or both).

There are also flags spring.data.*.repositories.enabled that you can use to switch the auto-configured repositories on and off in external configuration. This is useful for instance in case you want to switch off the Mongo repositories and still use the auto-configured MongoTemplate.

The same obstacle and the same features exist for other auto-configured Spring Data repository types (Elasticsearch, Solr). Just change the names of the annotations and flags respectively.

Database initialization

An SQL database can be initialized in different ways depending on what your stack is. Or of course you can do it manually as long as the database is a separate process.

Initialize a database using JPA

JPA has features for DDL generation, and these can be set up to run on startup against the database. This is controlled through two external properties:

  • spring.jpa.generate-ddl (boolean) switches the feature on and off and is vendor independent.

  • spring.jpa.hibernate.ddl-auto (enum) is a Hibernate feature that controls the behavior in a more fine-grained way. See below for more detail.

Initialize a database using Hibernate

You can set spring.jpa.hibernate.ddl-auto explicitly and the standard Hibernate property values are none, validate, update, create-drop. Spring Boot chooses a default value for you based on whether it thinks your database is embedded (default create-drop) or not (default none). An embedded database is detected by looking at the Connection type: hsqldb, h2 and derby are embedded, the rest are not. Be careful when switching from in-memory to a ‘real’ database that you don’t make assumptions about the existence of the tables and data in the new platform. You either have to set ddl-auto explicitly, or use one of the other mechanisms to initialize the database.

In addition, a file named import.sql in the root of the classpath will be executed on startup. This can be useful for demos and for testing if you are careful, but probably not something you want to be on the classpath in production. It is a Hibernate feature (nothing to do with Spring).

Initialize a database using Spring JDBC

Spring JDBC has a DataSource initializer feature. Spring Boot enables it by default and loads SQL from the standard locations schema.sql and data.sql (in the root of the classpath). In addition Spring Boot will load the schema-${platform}.sql and data-${platform}.sql files (if present), where platform is the value of spring.datasource.platform, e.g. you might choose to set it to the vendor name of the database (hsqldb, h2, oracle, mysql, postgresql etc.). Spring Boot enables the failfast feature of the Spring JDBC initializer by default, so if the scripts cause exceptions the application will fail to start. The script locations can be changed by setting spring.datasource.schema and spring.datasource.data, and neither location will be processed if spring.datasource.initialize=false.

To disable the failfast you can set spring.datasource.continueOnError=true. This can be useful once an application has matured and been deployed a few times, since the scripts can act as ‘poor man’s migrations’ — inserts that fail mean that the data is already there, so there would be no need to prevent the application from running, for instance.

If you want to use the schema.sql initialization in a JPA app (with Hibernate) then ddl-auto=create-drop will lead to errors if Hibernate tries to create the same tables. To avoid those errors set ddl-auto explicitly to "" (preferable) or "none". Whether or not you use ddl-auto=create-drop you can always use data.sql to initialize new data.

Initialize a Spring Batch database

If you are using Spring Batch then it comes pre-packaged with SQL initialization scripts for most popular database platforms. Spring Boot will detect your database type, and execute those scripts by default, and in this case will switch the fail fast setting to false (errors are logged but do not prevent the application from starting). This is because the scripts are known to be reliable and generally do not contain bugs, so errors are ignorable, and ignoring them makes the scripts idempotent. You can switch off the initialization explicitly using spring.batch.initializer.enabled=false.

Use a higher level database migration tool

Spring Boot works fine with higher level migration tools Flyway (SQL-based) and Liquibase (XML). In general we prefer Flyway because it is easier on the eyes, and it isn’t very common to need platform independence: usually only one or at most couple of platforms is needed.

Execute Flyway database migrations on startup

To automatically run Flyway database migrations on startup, add the org.flywaydb:flyway-core to your classpath.

The migrations are scripts in the form V<VERSION>__<NAME>.sql (with <VERSION> an underscore-separated version, e.g. ‘1’ or ‘2_1’). By default they live in a folder classpath:db/migration but you can modify that using flyway.locations (a list). See the Flyway class from flyway-core for details of available settings like schemas etc. In addition Spring Boot provides a small set of properties in {sc-spring-boot-autoconfigure}/flyway/FlywayProperties.{sc-ext}[FlywayProperties] that can be used to disable the migrations, or switch off the location checking.

By default Flyway will autowire the (@Primary) DataSource in your context and use that for migrations. If you like to use a different DataSource you can create one and mark its @Bean as @FlywayDataSource - if you do that remember to create another one and mark it as @Primary if you want two data sources. Or you can use Flyway’s native DataSource by setting flyway.[url,user,password] in external properties.

There is a {github-code}/spring-boot-samples/spring-boot-sample-flyway[Flyway sample] so you can see how to set things up.

Execute Liquibase database migrations on startup

To automatically run Liquibase database migrations on startup, add the org.liquibase:liquibase-core to your classpath.

The master change log is by default read from db/changelog/db.changelog-master.yaml but can be set using liquibase.change-log. See {sc-spring-boot-autoconfigure}/liquibase/LiquibaseProperties.{sc-ext}[LiquibaseProperties] for details of available settings like contexts, default schema etc.

There is a {github-code}/spring-boot-samples/spring-boot-sample-liquibase[Liquibase sample] so you can see how to set things up.

Batch applications

Execute Spring Batch jobs on startup

Spring Batch auto configuration is enabled by adding @EnableBatchProcessing (from Spring Batch) somewhere in your context.

By default it executes all Jobs in the application context on startup (see {sc-spring-boot-autoconfigure}/batch/JobLauncherCommandLineRunner.{sc-ext}[JobLauncherCommandLineRunner] for details). You can narrow down to a specific job or jobs by specifying spring.batch.job.names (comma-separated job name patterns).

If the application context includes a JobRegistry then the jobs in spring.batch.job.names are looked up in the registry instead of being autowired from the context. This is a common pattern with more complex systems where multiple jobs are defined in child contexts and registered centrally.

See {sc-spring-boot-autoconfigure}/batch/BatchAutoConfiguration.{sc-ext}[BatchAutoConfiguration] and @EnableBatchProcessing for more details.

Actuator

Change the HTTP port or address of the actuator endpoints

In a standalone application the Actuator HTTP port defaults to the same as the main HTTP port. To make the application listen on a different port set the external property management.port. To listen on a completely different network address (e.g. if you have an internal network for management and an external one for user applications) you can also set management.address to a valid IP address that the server is able to bind to.

For more detail look at the {sc-spring-boot-actuator}/autoconfigure/ManagementServerProperties.{sc-ext}[ManagementServerProperties] source code and production-ready-features.adoc in the ‘Production-ready features’ section.

Customize the ‘whitelabel’ error page

Spring Boot installs a ‘whitelabel’ error page that you will see in browser client if you encounter a server error (machine clients consuming JSON and other media types should see a sensible response with the right error code). To switch it off you can set error.whitelabel.enabled=false, but normally in addition or alternatively to that you will want to add your own error page replacing the whitelabel one. Exactly how you do this depends on the templating technology that you are using. For example, if you are using Thymeleaf you would add an error.html template and if you are using FreeMarker you would add an error.ftl template. In general what you need is a View that resolves with a name of error, and/or a @Controller that handles the /error path. Unless you replaced some of the default configuration you should find a BeanNameViewResolver in your ApplicationContext so a @Bean with id error would be a simple way of doing that. Look at {sc-spring-boot-autoconfigure}/web/ErrorMvcAutoConfiguration.{sc-ext}[ErrorMvcAutoConfiguration] for more options.

See also the section on Error Handling for details of how to register handlers in the servlet container.

Security

Switch off the Spring Boot security configuration

If you define a @Configuration with @EnableWebSecurity anywhere in your application it will switch off the default webapp security settings in Spring Boot. To tweak the defaults try setting properties in security.* (see {sc-spring-boot-autoconfigure}/security/SecurityProperties.{sc-ext}[SecurityProperties] for details of available settings) and SECURITY section of Common application properties.

Change the AuthenticationManager and add user accounts

If you provide a @Bean of type AuthenticationManager the default one will not be created, so you have the full feature set of Spring Security available (e.g. various authentication options).

Spring Security also provides a convenient AuthenticationManagerBuilder which can be used to build an AuthenticationManager with common options. The recommended way to use this in a webapp is to inject it into a void method in a WebSecurityConfigurerAdapter, e.g.

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
			auth.inMemoryAuthentication()
				.withUser("barry").password("password").roles("USER"); // ... etc.
	}

	// ... other stuff for application security

}

You will get the best results if you put this in a nested class, or a standalone class (i.e. not mixed in with a lot of other @Beans that might be allowed to influence the order of instantiation). The {github-code}/spring-boot-samples/spring-boot-sample-web-secure[secure web sample] is a useful template to follow.

If you experience instantiation issues (e.g. using JDBC or JPA for the user detail store) it might be worth extracting the AuthenticationManagerBuilder callback into a GlobalAuthenticationConfigurerAdapter (in the init() method so it happens before the authentication manager is needed elsewhere), e.g.

@Configuration
public class AuthenticationManagerConfiguration extends

	GlobalAuthenticationConfigurerAdapter {
	@Override
	public void init(AuthenticationManagerBuilder auth) {
		auth.inMemoryAuthentication() // ... etc.
	}

}

Enable HTTPS when running behind a proxy server

Ensuring that all your main endpoints are only available over HTTPS is an important chore for any application. If you are using Tomcat as a servlet container, then Spring Boot will add Tomcat’s own RemoteIpValve automatically if it detects some environment settings, and you should be able to rely on the HttpServletRequest to report whether it is secure or not (even downstream of a proxy server that handles the real SSL termination). The standard behavior is determined by the presence or absence of certain request headers (x-forwarded-for and x-forwarded-proto), whose names are conventional, so it should work with most front end proxies. You can switch on the valve by adding some entries to application.properties, e.g.

server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto

(The presence of either of those properties will switch on the valve. Or you can add the RemoteIpValve yourself by adding a TomcatEmbeddedServletContainerFactory bean.)

Spring Security can also be configured to require a secure channel for all (or some requests). To switch that on in a Spring Boot application you just need to set security.require_ssl to true in application.properties.

Hot swapping

Reload static content

There are several options for hot reloading. Running in an IDE (especially with debugging on) is a good way to do development (all modern IDEs allow reloading of static resources and usually also hot-swapping of Java class changes). The Maven and Gradle plugins also support running from the command line with reloading of static files. You can use that with an external css/js compiler process if you are writing that code with higher level tools.

Reload Thymeleaf templates without restarting the container

If you are using Thymeleaf, then set spring.thymeleaf.cache to false. See {sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[ThymeleafAutoConfiguration] for other Thymeleaf customization options.

Reload FreeMarker templates without restarting the container

If you are using FreeMarker, then set spring.freemarker.cache to false. See {sc-spring-boot-autoconfigure}/freemarker/FreeMarkerAutoConfiguration.{sc-ext}[FreeMarkerAutoConfiguration] for other FreeMarker customization options.

Reload Groovy templates without restarting the container

If you are using Groovy templates, then set spring.groovy.template.cache to false. See {sc-spring-boot-autoconfigure}/groovy/template/GroovyTemplateAutoConfiguration.{sc-ext}[GroovyTemplateAutoConfiguration] for other Groovy customization options.

Reload Velocity templates without restarting the container

If you are using Velocity, then set spring.velocity.cache to false. See {sc-spring-boot-autoconfigure}/velocity/VelocityAutoConfiguration.{sc-ext}[VelocityAutoConfiguration] for other Velocity customization options.

Reload Java classes without restarting the container

Modern IDEs (Eclipse, IDEA, etc.) all support hot swapping of bytecode, so if you make a change that doesn’t affect class or method signatures it should reload cleanly with no side effects.

Spring Loaded goes a little further in that it can reload class definitions with changes in the method signatures. With some customization it can force an ApplicationContext to refresh itself (but there is no general mechanism to ensure that would be safe for a running application anyway, so it would only ever be a development time trick probably).

Configuring Spring Loaded for use with Maven

To use Spring Loaded with the Maven command line, just add it as a dependency in the Spring Boot plugin declaration, e.g.

<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
			<version>1.2.0.RELEASE</version>
		</dependency>
	</dependencies>
</plugin>

This normally works pretty well with Eclipse and IntelliJ as long as they have their build configuration aligned with the Maven defaults (Eclipse m2e does this out of the box).

Configuring Spring Loaded for use with Gradle and IntelliJ

You need to jump through a few hoops if you want to use Spring Loaded in combination with Gradle and IntelliJ. By default, IntelliJ will compile classes into a different location than Gradle, causing Spring Loaded monitoring to fail.

To configure IntelliJ correctly you can use the idea Gradle plugin:

buildscript {
	repositories { jcenter() }
	dependencies {
		classpath "org.springframework.boot:spring-boot-gradle-plugin:{spring-boot-version}"
		classpath 'org.springframework:springloaded:1.2.0.RELEASE'
	}
}

apply plugin: 'idea'

idea {
	module {
		inheritOutputDirs = false
		outputDir = file("$buildDir/classes/main/")
	}
}

// ...
Note
IntelliJ must be configured to use the same Java version as the command line Gradle task and springloaded must be included as a buildscript dependency.

You can also additionally enable ‘Make Project Automatically’ inside Intellij to automatically compile your code whenever a file is saved.

Build

Customize dependency versions with Maven

If you use a Maven build that inherits directly or indirectly from spring-boot-dependencies (for instance spring-boot-starter-parent) but you want to override a specific third-party dependency you can add appropriate <properties> elements. Browse the {github-code}/spring-boot-dependencies/pom.xml[spring-boot-dependencies] POM for a complete list of properties. For example, to pick a different slf4j version you would add the following:

<properties>
	<slf4j.version>1.7.5<slf4j.version>
</properties>
Note
This only works if your Maven project inherits (directly or indirectly) from spring-boot-dependencies. If you have added spring-boot-dependencies in your own dependencyManagement section with <scope>import</scope> you have to redefine the artifact yourself instead of overriding the property .
Warning
Each Spring Boot release is designed and tested against a specific set of third-party dependencies. Overriding versions may cause compatibility issues.

Create an executable JAR with Maven

The spring-boot-maven-plugin can be used to create an executable ‘fat’ JAR. If you are using the spring-boot-starter-parent POM you can simply declare the plugin and your jars will be repackaged:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

If you are not using the parent POM you can still use the plugin, however, you must additionally add an <executions> section:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<version>{spring-boot-version}</version>
			<executions>
				<execution>
					<goals>
						<goal>repackage</goal>
					</goals>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>

See the {spring-boot-maven-plugin-site}/usage.html[plugin documentation] for full usage details.

Create an additional executable JAR

If you want to use your project as a library jar for other projects to depend on, and in addition have an executable (e.g. demo) version of it, you will want to configure the build in a slightly different way.

For Maven the normal JAR plugin and the Spring Boot plugin both have a ‘classifier’ configuration that you can add to create an additional JAR. Example (using the Spring Boot Starter Parent to manage the plugin versions and other configuration defaults):

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<configuration>
				<classifier>exec</classifier>
			</configuration>
		</plugin>
	</plugins>
</build>

Two jars are produced, the default one, and an executable one using the Boot plugin with classifier ‘exec’.

For Gradle users the steps are similar. Example:

bootRepackage  {
	classifier = 'exec'
}

Extract specific libraries when an executable jar runs

Most nested libraries in an executable jar do not need to be unpacked in order to run, however, certain libraries can have problems. For example, JRuby includes its own nested jar support which assumes that the jruby-complete.jar is always directly available as a file in its own right.

To deal with any problematic libraries, you can flag that specific nested jars should be automatically unpacked to the ‘temp folder’ when the executable jar first runs.

For example, to indicate that JRuby should be flagged for unpack using the Maven Plugin you would add the following configuration:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<configuration>
				<requiresUnpack>
					<dependency>
						<groupId>org.jruby</groupId>
						<artifactId>jruby-complete</artifactId>
					</dependency>
				</requiresUnpack>
			</configuration>
		</plugin>
	</plugins>
</build>

And to do that same with Gradle:

springBoot  {
	requiresUnpack = ['org.jruby:jruby-complete']
}

Create a non-executable JAR with exclusions

Often if you have an executable and a non-executable jar as build products, the executable version will have additional configuration files that are not needed in a library jar. E.g. the application.yml configuration file might excluded from the non-executable JAR.

Here’s how to do that in Maven:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<configuration>
				<classifier>exec</classifier>
			</configuration>
		</plugin>
		<plugin>
			<artifactId>maven-jar-plugin</artifactId>
			<executions>
				<execution>
					<id>exec</id>
					<phase>package</phase>
					<goals>
						<goal>jar</goal>
					</goals>
					<configuration>
						<classifier>exec</classifier>
					</configuration>
				</execution>
				<execution>
					<phase>package</phase>
					<goals>
						<goal>jar</goal>
					</goals>
					<configuration>
						<!-- Need this to ensure application.yml is excluded -->
						<forceCreation>true</forceCreation>
						<excludes>
							<exclude>application.yml</exclude>
						</excludes>
					</configuration>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>

In Gradle you can create a new JAR archive with standard task DSL features, and then have the bootRepackage task depend on that one using its withJarTask property:

jar {
	baseName = 'spring-boot-sample-profile'
	version =  '0.0.0'
	excludes = ['**/application.yml']
}

task('execJar', type:Jar, dependsOn: 'jar') {
	baseName = 'spring-boot-sample-profile'
	version =  '0.0.0'
	classifier = 'exec'
	from sourceSets.main.output
}

bootRepackage  {
	withJarTask = tasks['execJar']
}

Remote debug a Spring Boot application started with Maven

To attach a remote debugger to a Spring Boot application started with Maven you can use the jvmArguments property of the {spring-boot-maven-plugin-site}/[maven plugin].

Check {spring-boot-maven-plugin-site}/examples/run-debug.html[this example] for more details.

Remote debug a Spring Boot application started with Gradle

To attach a remote debugger to a Spring Boot application started with Gradle you can use the applicationDefaultJvmArgs in build.gradle or --debug-jvm command line option.

build.gradle:

applicationDefaultJvmArgs = [
    "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
]

Command line:

$ gradle run --debug-jvm

Check {gradle-userguide}/application_plugin.html[Gradle Application Plugin] for more details.

Build an executable archive with Ant

To build with Ant you need to grab dependencies, compile and then create a jar or war archive as normal. To make it executable:

  1. Use the appropriate launcher as a Main-Class, e.g. JarLauncher for a jar file, and specify the other properties it needs as manifest entries, principally a Start-Class.

  2. Add the runtime dependencies in a nested ‘lib’ directory (for a jar) and the provided (embedded container) dependencies in a nested lib-provided directory. Remember not to compress the entries in the archive.

  3. Add the spring-boot-loader classes at the root of the archive (so the Main-Class is available).

Example:

<target name="build" depends="compile">
	<copy todir="target/classes/lib">
		<fileset dir="lib/runtime" />
	</copy>
	<jar destfile="target/spring-boot-sample-actuator-${spring-boot.version}.jar" compress="false">
		<fileset dir="target/classes" />
		<fileset dir="src/main/resources" />
		<zipfileset src="lib/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
		<manifest>
			<attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
			<attribute name="Start-Class" value="${start-class}" />
		</manifest>
	</jar>
</target>

The Actuator Sample has a build.xml that should work if you run it with

$ ant -lib <path_to>/ivy-2.2.jar

after which you can run the application with

$ java -jar target/*.jar

How to use Java 6

If you want to use Spring Boot with Java 6 there are a small number of configuration changes that you will have to make. The exact changes depend on your application’s functionality.

Embedded servlet container compatibility

If you are using one of Boot’s embedded Servlet containers you will have to use a Java 6-compatible container. Both Tomcat 7 and Jetty 8 are Java 6 compatible. See Use Tomcat 7 and Use Jetty 8 for details.

JTA API compatibility

While the Java Transaction API itself doesn’t require Java 7 the official API jar contains classes that have been built to require Java 7. If you are using JTA then you will need to replace the official JTA 1.2 API jar with one that has been built to work on Java 6. To do so, exclude any transitive dependencies on javax.transaction:javax.transaction-api and replace them with a dependency on org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Final

Traditional deployment

Create a deployable war file

Use the SpringBootServletInitializer base class, which is picked up by Spring’s Servlet 3.0 support on deployment. Add an extension of that to your project and build a war file as normal. For more detail, see the ‘Converting a jar Project to a war’ guide on the spring.io website and the sample below.

The war file can also be executable if you use the Spring Boot build tools. In that case the embedded container classes (to launch Tomcat for instance) have to be added to the war in a lib-provided directory. The tools will take care of that as long as the dependencies are marked as ‘provided’ in Maven or Gradle. Here’s a Maven example {github-code}/spring-boot-samples/spring-boot-sample-traditional/pom.xml[in the Boot Samples].

Create a deployable war file for older servlet containers

Older Servlet containers don’t have support for the ServletContextInitializer bootstrap process used in Servlet 3.0. You can still use Spring and Spring Boot in these containers but you are going to need to add a web.xml to your application and configure it to load an ApplicationContext via a DispatcherServlet.

Convert an existing application to Spring Boot

For a non-web application it should be easy (throw away the code that creates your ApplicationContext and replace it with calls to SpringApplication or SpringApplicationBuilder). Spring MVC web applications are generally amenable to first creating a deployable war application, and then migrating it later to an executable war and/or jar. Useful reading is in the Getting Started Guide on Converting a jar to a war.

Create a deployable war by extending SpringBootServletInitializer (e.g. in a class called Application), and add the Spring Boot @EnableAutoConfiguration annotation. Example:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		// Customize the application or call application.sources(...) to add sources
		// Since our example is itself a @Configuration class we actually don't
		// need to override this method.
		return application;
	}

}

Remember that whatever you put in the sources is just a Spring ApplicationContext and normally anything that already works should work here. There might be some beans you can remove later and let Spring Boot provide its own defaults for them, but it should be possible to get something working first.

Static resources can be moved to /public (or /static or /resources or /META-INF/resources) in the classpath root. Same for messages.properties (Spring Boot detects this automatically in the root of the classpath).

Vanilla usage of Spring DispatcherServlet and Spring Security should require no further changes. If you have other features in your application, using other servlets or filters for instance, then you may need to add some configuration to your Application context, replacing those elements from the web.xml as follows:

  • A @Bean of type Servlet or ServletRegistrationBean installs that bean in the container as if it was a <servlet/> and <servlet-mapping/> in web.xml.

  • A @Bean of type Filter or FilterRegistrationBean behaves similarly (like a <filter/> and <filter-mapping/>.

  • An ApplicationContext in an XML file can be added to an @Import in your Application. Or simple cases where annotation configuration is heavily used already can be recreated in a few lines as @Bean definitions.

Once the war is working we make it executable by adding a main method to our Application, e.g.

public static void main(String[] args) {
	SpringApplication.run(Application.class, args);
}

Applications can fall into more than one category:

  • Servlet 3.0+ applications with no web.xml.

  • Applications with a web.xml.

  • Applications with a context hierarchy.

  • Applications without a context hierarchy.

All of these should be amenable to translation, but each might require slightly different tricks.

Servlet 3.0+ applications might translate pretty easily if they already use the Spring Servlet 3.0+ initializer support classes. Normally all the code from an existing WebApplicationInitializer can be moved into a SpringBootServletInitializer. If your existing application has more than one ApplicationContext (e.g. if it uses AbstractDispatcherServletInitializer) then you might be able to squash all your context sources into a single SpringApplication. The main complication you might encounter is if that doesn’t work and you need to maintain the context hierarchy. See the entry on building a hierarchy for examples. An existing parent context that contains web-specific features will usually need to be broken up so that all the ServletContextAware components are in the child context.

Applications that are not already Spring applications might be convertible to a Spring Boot application, and the guidance above might help, but your mileage may vary.

Deploying a WAR to Weblogic

To deploy a Spring Boot application to Weblogic you must ensure that your servlet initializer directly implements WebApplicationInitializer (even if you extend from a base class that already implements it).

A typical initializer for Weblogic would be something like this:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.web.WebApplicationInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer {

}

If you use logback, you will also need to tell Weblogic to prefer the packaged version rather than the version that pre-installed with the server. You can do this by adding a WEB-INF/weblogic.xml file with the following contents:

<?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
		http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd
		http://xmlns.oracle.com/weblogic/weblogic-web-app
		http://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>

Deploying a WAR in an Old (Servlet 2.5) Container

Spring Boot uses Servet 3.0 APIs to initialize the ServletContext (register Servlets etc.) so you can’t use the same application out of the box in a Servlet 2.5 container. It is however possible to run a Spring Boot application on an older container with some special tools. If you include org.springframework.boot:spring-boot-legacy as a dependency (maintained separately to the core of Spring Boot and currently available at 1.0.0.RELEASE), all you should need to do is create a web.xml and declare a context listener to create the application context and your filters and servlets. The context listener is a special purpose one for Spring Boot, but the rest of it is normal for a Spring application in Servlet 2.5. Example:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>demo.Application</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
	</listener>

	<filter>
		<filter-name>metricFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>metricFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextAttribute</param-name>
			<param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

In this example we are using a single application context (the one created by the context listener) and attaching it to the DispatcherServlet using an init parameter. This is normal in a Spring Boot application (you normally only have one application context).