diff --git a/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-docs/src/main/asciidoc/howto.adoc index 81ac197393..7290fdcec4 100644 --- a/spring-boot-docs/src/main/asciidoc/howto.adoc +++ b/spring-boot-docs/src/main/asciidoc/howto.adoc @@ -15,3 +15,1230 @@ the `spring-boot` tag). We're also more than happy to extend this section; If you want to add a ``how-to'' you can send us a {github-code}[pull request]. -- + + + +[[howto-spring-boot-application]] +== Spring Boot application + + + +[[howto-troubleshoot-auto-configuration]] +=== Troubleshoot auto-configuration +The Spring Boot auto-configuration tries it's 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 Javadocs. 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 `name="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`. + + + +[[howto-customize-the-environment-or-application-context]] +=== Customize the Environment or ApplicationContext before it starts +A `SpringApplication` has `ApplicationListeners` and `ApplicationContextInitializers` that +are used to apply customizations to the context or environment. Spring Boot loads a number +of such customizations for use internally from `META-INF/spring.factories`. There is more +than one way to register additional ones: + +* Programmatically per application by calling the `addListeners` and `addInitializers` + methods on `SpringApplication` before you run it. +* Declaratively per application by setting `context.initializer.classes` or + `context.listener.classes`. +* Declarative 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 +``<>'' in the +``<>'' section for a complete list. + + + +[[howto-build-an-application-context-hierarchy]] +=== Build an ApplicationContext hierarchy (adding a parent or root context) +You can use the `ApplicationBuilder` class to create parent/child `ApplicationContext` +hierarchies. See ``<>'' +in the ``<>'' section for more information. + + + +[[howto-create-a-non-web-application]] +=== Create a non-web application +Not all Spring applications have to be web applications (or web services). If you want to +execute some code in a `main` method, but also bootstrap a Spring application to set up +the infrastructure to use, then it's easy with the `SpringApplication` features of Spring +Boot. A `SpringApplication` changes its `ApplicationContext` class depending on whether it +thinks it needs a web application or not. The first thing you can do to help it is to just +leave the servlet API dependencies off the classpath. If you can't do that (e.g. you are +running 2 applications from the same code base) then you can explicitly call +`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. + + + +[[howto-properties-and-configuration]] +== Properties & configuration + + + +[[howto-externalize-configuration]] +=== Externalize the configuration of SpringApplication +A `SpringApplication` has bean properties (mainly setters) so you can use its Java API as +you create the application to modify its behavior. Or you can externalize the +configuration using properties in `spring.main.*`. E.g. in `application.properties` you +might have. + +[indent=0,subs="verbatim,quotes,attributes"] +---- + 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. + +[[howto-change-the-location-of-external-properties]] +=== Change the location of external properties of an application +By default properties from different sources are added to the Spring `Environment` in a +defined order (see ``<>'' in +the ``<>'' 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 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. + + + +[[howto-use-short-command-line-arguments]] +=== Use ``short'' command line arguments +Some people like to use (for example) `--port=9000` instead of `--server.port=9000` to +set configuration properties on the command line. You can easily enable this by using +placeholders in `application.properties`, e.g. + +[indent=0,subs="verbatim,quotes,attributes"] +---- + server.port: ${port:8080} +---- + +NOTE: In this specific case the port binding will work in a PaaS environment like Heroku +and Cloud Foundry, since in those two platforms the `PORT` environment variable is set +automatically and Spring can bind to capitalized synonyms for `Environment` properties. + + + +[[howto-use-yaml-for-external-properties]] +=== Use YAML for external properties +YAML is a superset of JSON and as such is a very convenient syntax for storing external +properties in a hierarchical format. E.g. + +[source,yaml,indent=0,subs="verbatim,quotes,attributes"] +---- + spring: + application: + name: cruncher + datasource: + driverClassName: com.mysql.jdbc.Driver + url: jdbc:mysql://localhost/test + server: + port: 9000 +---- + +Create a file called `application.yml` and stick it in the root of your classpath, and +also add `snakeyaml` to your classpath (Maven co-ordinates `org.yaml:snakeyaml`, already +included if you use the `spring-boot-starter`). A YAML file is parsed to a Java +`Map` (like a JSON object), and Spring Boot flattens the maps 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 + +[indent=0,subs="verbatim,quotes,attributes"] +---- + spring.application.name: cruncher + spring.datasource.driverClassName: com.mysql.jdbc.Driver + spring.datasource.url: jdbc:mysql://localhost/test + server.port: 9000 +---- + +See ``<>'' in +the ``<>'' section for more information +about YAML. + +[[howto-set-active-spring-profiles]] +=== Set the active Spring profiles +The Spring `Environment` has an API for this, but normally you would set a System 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): + +[indent=0,subs="verbatim,quotes,attributes"] +---- + $ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar +---- + +In Spring Boot you can also set the active profile in `application.properties`, e.g. + +[indent=0,subs="verbatim,quotes,attributes"] +---- + spring.profiles.active=production +---- + +A value set this way is replaced by the System property or environment variable setting, +but not by the `SpringApplicationBuilder.profiles()` method. Thus the latter Java API can +be used to augment the profiles without changing the defaults. + +See ``<>'' in +the ``<>'' section for more information. + + + +[[howto-change-configuration-depending-on-the-environment]] +=== Change configuration depending on the environment +A YAML file is actually a sequence of documents separated by `---` lines, and each +document is parsed separately to a flattened map. + +If a YAML document contains a `spring.profiles` key, then the profiles value +(comma-separated list of profiles) is fed into the Spring +`Environment.acceptsProfiles()` and if any of those profiles is active that document is +included in the final merge (otherwise not). + +Example: + +[source,yaml,indent=0,subs="verbatim,quotes,attributes"] +---- + server: + port: 9000 + --- + + spring: + profiles: development + server: + port: 9001 + + --- + + spring: + profiles: production + server: + port: 0 +---- + +In this example the default port is 9000, but if the Spring profile ``development'' is +active then the port is 9001, and if ``production'' is active then it is 0. + +The YAML documents are merged in the order they are encountered (so later values override +earlier ones). + +To do the same thing with properties files you can use `application-${profile}.properties` +to specify profile-specific values. + + + +[[howto-discover-build-in-options-for-external-properties]] +=== Discover built-in options for external properties +Spring Boot binds external properties from `application.properties` (or `.yml`) (and +other places) into an application at runtime. There is not (and technically cannot be) +an exhaustive list of all supported properties in a single location because contributions +can come from additional jar files on your classpath. + +A running application with the Actuator features has a `configprops` endpoint that shows +all the bound and bindable properties available through `@ConfigurationProperties`. + +The appendix includes an <> 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`. + + + +[[howto-embedded-servlet-containers]] +== Embedded servlet containers + + + +[[howto-add-a-servlet-filter-or-servletcontextlistener]] +=== 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. + + + +[[howto-change-the-http-port]] +=== Change the HTTP port +In a standalone application the main HTTP port defaults to `8080`, but can be set with +`server.port` (e.g. in `application.properties` or as a System property). Thanks to +relaxed binding of `Environment` values you can also use `SERVER_PORT` (e.g. as an OS +environment variable). + +To switch off the HTTP endpoints completely, but still create a `WebApplicationContext`, +use `server.port=-1` (this is sometimes useful for testing). + +For more details look at ``<>'' +in the ``<>'' section, or the +{sc-spring-boot-autoconfigure}/web/ServerProperties.{sc-ext}[`ServerProperties`] source +code. + + +[[howto-user-a-random-unassigned-http-port]] +=== Use a random unassigned HTTP port +To scan for a free port (using OS natives to prevent clashes) use `server.port=0`. + + + +[[howto-discover-the-http-port-at-runtime]] +=== Discover the HTTP port at runtime +You can access the port the server is running on from log output or from the +`EmbeddedWebApplicationContext` via its `EmbeddedServletContainer`. The best way to get +that and be sure that it has initialized is to add a `@Bean` of type +`ApplicationListener` and pull the container +out of the event wehen it is published. + + + +[[howto-configure-tomcat]] +=== Configure Tomcat +Generally you can follow the advice from +``<>'' about +`@ConfigurationProperties` (`ServerProperties` is the main one here), but also look at +`EmbeddedServletContainerCustomizer` and various Tomcat specific `*Customizers` that you +can add in one of those. The Tomcat APIs are quite rich so once you have access to the +`TomcatEmbeddedServletContainerFactory` you can modify it in a number of ways. Or the +nuclear option is to add your own `TomcatEmbeddedServletContainerFactory`. + + + +[[howto-terminate-ssl-in-tomcat]] +=== Terminate SSL in Tomcat +Use an `EmbeddedServletContainerCustomizer` and in that add a `TomcatConnectorCustomizer` +that sets up the connector to be secure: + +[source,java,indent=0,subs="verbatim,quotes,attributes"] +---- + @Bean + public EmbeddedServletContainerCustomizer containerCustomizer(){ + return new MyCustomizer(); + } + + // ... + + private static class MyCustomizer implements EmbeddedServletContainerCustomizer { + + @Override + public void customize(ConfigurableEmbeddedServletContainerFactory factory) { + if(factory instanceof TomcatEmbeddedServletContainerFactory) { + customizeTomcat((TomcatEmbeddedServletContainerFactory) factory)); + } + } + + public void customizeTomcat(TomcatEmbeddedServletContainerFactory factory) { + factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { + @Override + public void customize(Connector connector) { + connector.setPort(serverPort); + connector.setSecure(true); + connector.setScheme("https"); + connector.setAttribute("keyAlias", "tomcat"); + connector.setAttribute("keystorePass", "password"); + try { + connector.setAttribute("keystoreFile", + ResourceUtils.getFile("src/ssl/tomcat.keystore").getAbsolutePath()); + } catch (FileNotFoundException e) { + throw new IllegalStateException("Cannot load keystore", e); + } + connector.setAttribute("clientAuth", "false"); + connector.setAttribute("sslProtocol", "TLS"); + connector.setAttribute("SSLEnabled", true); + } + }); + } + + } +---- + + + +[[howto-use-jetty-instead-of-tomcat]] +=== Use Jetty instead of Tomcat +The Spring Boot starters (`spring-boot-starter-web` in particular) use Tomcat as an +embedded container by default. You need to exclude those dependencies and include the +Jetty ones instead. Spring Boot provides Tomcat and Jetty dependencies bundled together +as separate startes to help make this process as easy as possible. + +Example in Maven: + +[source,xml,indent=0,subs="verbatim,quotes,attributes"] +---- + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-jetty + +---- + +Example in Gradle: + +[source,groovy,indent=0,subs="verbatim,quotes,attributes"] +---- + configurations { + compile.exclude module: 'spring-boot-starter-tomcat' + } + + dependencies { + compile("org.springframework.boot:spring-boot-starter-web:1.0.0.RC3") + compile("org.springframework.boot:spring-boot-starter-jetty:1.0.0.RC3") + // ... + } +---- + + + +[[howto-configure-jetty]] +=== Configure Jetty +Generally you can follow the advice from +``<>'' about +`@ConfigurationProperties` (`ServerProperties` is the main one here), but also look at +`EmbeddedServletContainerCustomizer`. The Jetty APIs are quite rich so once you have +access to the `JettyEmbeddedServletContainerFactory` you can modify it in a number +of ways. Or the nuclear option is to add your own `JettyEmbeddedServletContainerFactory`. + + + +[[howto-use-tomcat-8]] +=== Use Tomcat 8 +Tomcat 8 works with Spring Boot, but the default is to use Tomcat 7 (so we can support +Java 1.6 out of the box). You should only need to change the classpath to use Tomcat 8 +for it to work. The {github-code}/spring-boot-samples/spring-boot-sample-websocket/pom.xml[websocket sample] +shows you how to do that in Maven. + + + +[[howto-use-jetty-9]] +=== Use Jetty 9 +Jetty 9 works with Spring Boot, but the default is to use Jetty 8 (so we can support +Java 1.6 out of the box). You should only need to change the classpath to use Jetty 9 +for it to work. + +If you are using the starter poms and parent you can just add the Jetty starter and +change the version properties, e.g. for a simple webapp or service: + +[source,xml,indent=0,subs="verbatim,quotes,attributes"] +---- + + 1.7 + 9.1.0.v20131115 + 3.1.0 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-jetty + + +---- + + + +[[howto-spring-mvc]] +== Spring MVC + + + +[[howto-write-a-json-rest-service]] +=== Write a JSON REST service +Any Spring `@RestController` in a Spring Boot application should render JSON response by +default as long as Jackson2 is on the classpath. For example: + +[source,java,indent=0,subs="verbatim,quotes,attributes"] +---- + @RestController + public class MyController { + + @RequestMapping("/thing") + public MyThing thing() { + return new MyThing(); + } + + } +---- + +As long as `MyThing` can be serialized by Jackson2 (e.g. a normal POJO or Groovy object) +then `http://localhost:8080/thing` will serve a JSON representation of it by default. +Sometimes in a browser you might see XML responses (but by default only if `MyThing` was +a JAXB object) because browsers tend to send accept headers that prefer XML. + + + +[[howto-customize-the-jackson-objectmapper]] +=== Customize the Jackson ObjectMapper +Spring MVC (client and server side) uses `HttpMessageConverters` to negotiate content +conversion in an HTTP exchange. If Jackson is on the classpath you already get a default +converter with a vanilla `ObjectMapper`. Spring Boot has some features to make it easier +to customize this behavior. + +The smallest change that might work is to just add beans of type +`com.fasterxml.jackson.databind.Module` to your context. They will be registered with the +default `ObjectMapper` and then injected into the default message converter. To replace +the default `ObjectMapper` completely, define a `@Bean` of that type and mark it as +`@Primary`. + +In addition, if your context contains any beans of type `ObjectMapper` then all of the +`Module` beans will be registered with all of the mappers. So there is 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 ``<>'' section and the +{sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[`WebMvcAutoConfiguration`] +source code for more details. + + + +[[howto-customize-the-responsebody-rendering]] +=== Customize the @ResponseBody rendering +Spring uses `HttpMessageConverters` to render `@ResponseBody` (or responses from +`@RestControllers`). You can contribute additional converters by simply adding beans of +that type in a Spring Boot context. If a bean you add is of a type that would have been +included by default anyway (like `MappingJackson2HttpMessageConverter` for JSON +conversions) then it will replace the default value. A convenience bean is provided of +type `HttpMessageConverters` (always available if you use the default MVC configuration) +which has some useful methods to access the default and user-enhanced message converters +(useful, for example if you want to manually inject them into a custom `RestTemplate`). + +As in normal MVC usage, any `WebMvcConfigurerAdapter` beans that you provide can also +contribute converters by overriding the `configureMessageConverters` method, but unlike +with normal MVC, you can supply only additional converters that you need (because Spring +Boot uses the same mechanism to contribute its defaults). Finally, if you opt-out of the +Spring Boot default MVC configuration by providing your own `@EnableWebMvc` configuration, +then you can take control completely and do everything manually using +`getMessageConverters` from `WebMvcConfigurationSupport`. + +See the {sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[`WebMvcAutoConfiguration`] +source code for more details. + + + +[[howto-switch-off-the-spring-mvc-dispatcherservlet]] +=== Switch off the Spring MVC DispatcherServlet +Spring Boot wants to serve all content from the root of your application `/` down. If you +would rather map your own servlet to that URL you can do it, but of course you may lose +some of the other Boot MVC features. To add your own servlet and map it to the root +resource just declare a `@Bean` of type `Servlet` and give it the special bean name +`dispatcherServlet` (You can also create a bean of a different type with that name if +you want to switch it off and not replace it). + + + +[[howto-switch-off-default-mvc-configuration]] +=== Switch off the Default MVC configuration +The easiest way to take complete control over MVC configuration is to provide your own +`@Configuration` with the `@EnableWebMvc` annotation. This will leave all MVC +configuration in your hands. + + + +[[howto-logging]] +== Logging + + + +[[howto-configure-logback-for-loggin]] +=== Configure Logback for 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 http://logback.qos.ch[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-start-logging`. For a web application you only need +`spring-boot-starter-web` since it depends transitively on the logging starter. +For example, using Maven: + +[source,xml,indent=0,subs="verbatim,quotes,attributes"] +---- + + org.springframework.boot + spring-boot-starter-web + +---- + +Spring Boot has a `LoggingSystem` abstraction that attempts to select a system depending +on the contents of the classpath. If Logback is available it is the first choice. So 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. + +[source,xml,indent=0,subs="verbatim,quotes,attributes"] +---- + + + + + +---- + +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). + + + +[[howto-configure-log4j-for-logging]] +=== Configure Log4j for logging +Spring Boot supports http://logging.apache.org/log4j/1.x/[Log4j] for logging +configuration, but it has to be on the classpath. If you are using the starter poms for +assembling dependencies that means you have to exclude logback and then include log4j +back. If you aren't using the starter poms then you need to provide `commons-logging` +(at least) in addition to Log4j. + +The simplest path to using Log4j is probably through the starter poms, even though it +requires some jiggling with excludes, e.g. in Maven: + +[source,xml,indent=0,subs="verbatim,quotes,attributes"] +---- + + org.springframework.boot + spring-boot-starter-web + + + ${project.groupId} + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j + +---- + +NOTE: The use of the log4j starter to gather together the dependencies for common logging +requirements (e.g. including having Tomcat use `java.util.logging` but configure the +output using Log4j). See the Actuator Log4j Sample for more detail and to see it in +action. + + + +[[howto-data-access]] +== Data Access + + + +[[howto-configure-a-datasource]] +=== Configure a DataSource +To override the default settings just define a `@Bean` of your own of type `DataSource`. +See ``<>'' in the +``<>'' section and the +{sc-spring-boot-autoconfigure}/jdbc/DataSourceAutoConfiguration.{sc-ext}[`DataSourceAutoConfiguration`] +class for more details. + + + +[[howto-use-spring-data-repositories]] +=== Use Spring Data repositories +Spring Data can create implementations for you of `@Repository` interfaces of various +flavours. 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 for Mongodb you +only need to add `spring-datamongodb`), create some repository interfaces to handle your +`@Entity` objects. Examples are in the {github-code}/spring-boot-samples/spring-boot-sample-data-jpa[JPA sample] +or the {github-code}/spring-boot-samples/spring-boot-sample-data-mongodb[Mongodb sample]. + +Spring Boot tries to guess the location of your `@Repository` definitions, based on the +`@EnableAutoConfiguration` it finds. To get more control, use the `@EnableJpaRepositories` +annotation (from Spring Data JPA). + + + +[[howto-separate-entity-definitions-from-spring-configuration]] +=== Separate @Entity definitions from Spring configuration +Spring Boot tries to guess the location of your `@Entity` definitions, based on the +`@EnableAutoConfiguration` it finds. To get more control, you can use the `@EntityScan` +annotation, e.g. + +[source,java,indent=0,subs="verbatim,quotes,attributes"] +---- + @Configuration + @EnableAutoConfiguration + @EntityScan(basePackageClasses=City.class) + public class Application { + + //... + + } +---- + + + +[[howto-configure-jpa-properties]] +=== Configure JPA properties +Spring JPA already provides some vendor-independent configuration options (e.g. for SQL +logging) and Spring Boot exposes those, and a few more for hibernate as external +configuration properties. The most common options to set are: + +[indent=0,subs="verbatim,quotes,attributes"] +---- + spring.jpa.hibernate.ddl-auto: create-drop + spring.jpa.hibernate.naming_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. + + + +[[howto-use-traditional-persistence-xml]] +=== Use a traditional persistence.xml +Spring doesn't require the use of XML to configure the JPA provider, and Spring Boot +assumes you want to take advantage of that feature. If you prefer to use `persistence.xml` +then you need to define your own `@Bean` of type `LocalEntityManagerFactoryBean`, and set +the persistence unit name there. + +See +https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java[`JpaBaseConfiguration`] +for the default settings. + + + +[[howto-database-initialization]] +== Database initialization +An SQL database can be initialized in different ways depending on what your stack is. Or +of course you can do it manually as long as the database is in a server. + + + +[[howto-initialize-a-database-using-jpa]] +=== Initialize a database using JPA +JPA has features for DDL generation, and these can be set up to run on startup against the +database. This is controlled through two external properties: + +* `spring.jpa.generate-ddl` (boolean) switches the feature on and off and is vendor + independent. +* `spring.jpa.hibernate.ddl-auto` (enum) is a Hibernate feature that controls the + behavior in a more fine-grained way. See below for more detail. + + + +[[howto-initialize-a-database-using-hibernate]] +=== Initialize a database using Hibernate +You can set `spring.jpa.hibernate.ddl-auto` explicitly and the standard Hibernate property +values are `none`, `validate`, `update`, `create-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` expicitly, 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 carefuil, but probably +not something you want to be on the classpath in production. It is a Hibernate feature +(nothing to do with Spring). + + + +[[howto-intialize-a-database-using-spring-jdbc]] +=== Initialize a database using Spring JDBC +Spring JDBC has a `DataSource` initializer feature. Spring Boot enables it by default and +loads SQL from the standard locations `schema.sql` and `data.sql` (in the root of the +classpath). In addition Spring Boot will load a file `schema-${platform}.sql` where +`platform` is 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 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. + + + +[[howto-initialize-a-spring-batch-database]] +=== Initialize a Spring Batch database +If you are using Spring Batch then it comes pre-packaged with SQL initialization scripts +for most popular database platforms. Spring Boot will detect your database type, and +execute those scripts by default, and in this case will switch the fail fast setting to +false (errors are logged but do not prevent the application from starting). This is +because the scripts are known to be reliable and generally do not contain bugs, so errors +are ignorable, and ignoring them makes the scripts idempotent. You can switch off the +initialization explicitly using `spring.batch.initializer.enabled=false`. + + + +[[howto-use-a-higher-level-database-migration-tool]] +=== Use a higher level datababse migration tool +Spring Boot works fine with higher level migration tools http://flywaydb.org/[Flyway] +(SQL-based) and http://www.liquibase.org/[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. + + + +[[howto-batch-applications]] +== Batch applications + + + +[[howto-execute-spring-batch-jobs-on-startup]] +=== Execute Spring Batch jobs on startup +Spring Batch autoconfiguration is enabled by adding `@EnableBatchProcessing` +(from Spring Batch) somewhere in your context. + +By default it executes *all* `Jobs` in the application context on startup (see +{sc-spring-boot-autoconfigure}/batch/JobLauncherCommandLineRunner.{sc-ext}[JobLauncherCommandLineRunner] +for details). You can narrow down to a specific job or jobs by specifying +`spring.batch.job.names` (comma separated job name patterns). + +If the application context includes a `JobRegistry` then the jobs in +`spring.batch.job.names` are looked up in the registry instead of being autowired from the +context. This is a common pattern with more complex systems where multiple jobs are +defined in child contexts and registered centrally. + +See +{sc-spring-boot-autoconfigure}/batch/BatchAutoConfiguration.{sc-ext}[BatchAutoConfiguration] +and +https://github.com/spring-projects/spring-batch/blob/master/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java[@EnableBatchProcessing] +for more details. + + + +[[howto-actuator]] +== Actuator + + + +[[howto-change-the-http-port-or-address-of-the-actuator-endpoints]] +=== Change the HTTP port or address of the actuator endpoints +In a standalone application the Actuator HTTP port defaults to the same as the main HTTP +port. To make the application listen on a different port set the external property +`management.port`. To listen on a completely different network address (e.g. if you have +an internal network for management and an external one for user applications) you can +also set `management.address` to a valid IP address that the server is able to bind to. + +For more detail look at the +{sc-spring-boot-actuator}/autoconfigure/ManagementServerProperties.{sc-ext}[`ManagementServerProperties`] +source code and +``<>'' +in the ``<>'' section. + + + +[[howto-customize-the-whitelabel-error-page]] +=== Customize the ``whitelabel'' error page +The Actuator 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. If you are using +Thymeleaf you can do this by adding an `error.html` 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-actuator}/autoconfigure/ErrorMvcAutoConfiguration.{sc-ext}[`ErrorMvcAutoConfiguration`] for more options. + + + +[[howto-security]] +== Security + + + +[[howto-secure-an-application]] +=== Secure an application +If Spring Security is on the classpath then web applications will be secure by default +(``basic'' authentication on all endpoints) . To add method-level security to a web +application you can simply `@EnableGlobalMethodSecurity` with your desired settings. + +The default `AuthenticationManager` has a single user (username ``user'' and password +random, printed at INFO when the application starts up). You can change the password by +providing a `security.user.password`. This and other useful properties are externalized +via `SecurityProperties`. + + + +[[howto-switch-off-spring-boot-security-configuration]] +=== Switch off the Spring Boot security configuration +If you define a `@Configuration` with `@EnableWebSecurity` anywhere in your application +it will switch off the default webapp security settings in Spring Boot. To tweak the +defaults try setting properties in `security.*` (see +{sc-spring-boot-autoconfigure}/security/SecurityProperties.{sc-ext}[`SecurityProperties`] +for details of available settings). + + + +[[howto-change-the-authenticationmanager-and-add-user-accounts]] +=== Change the AuthenticationManager and add user accounts +If you provide a `@Bean` of type `AuthenticationManager` the default one will not be +created, so you have the full feature set of Spring Security available (e.g. +http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#jc-authentication[various authentication options]). + +Spring Security also provides a convenient `AuthenticationManagerBuilder` which can be +used to build an `AuthenticationManager` with common options. The recommended way to +use this in a webapp is to inject it into a void method in a +`WebSecurityConfigurerAdapter`, e.g. + +[source,java,indent=0,subs="verbatim,quotes,attributes"] +---- + @Configuration + @Order(0) + public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Autowired + protected void init(AuthenticationManagerBuilder builder) { + builder.inMemoryAuthentication().withUser("barry"); // ... etc. + } + + // ... other stuff for application security + + } +---- + +The configuration class that does this should declare an `@Order` so that it is used +before the default one in Spring Boot (which has very low precedence). + + + +[[howto-enable-https]] +=== Enable HTTPS +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 the +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 or not it is secure (even downstream of 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 switch on the valve by adding some entries to +`application.properties`, e.g. + +[indent=0] +---- + server.tomcat.remote_ip_header: x-forwarded-for + server.tomcat.protocol_header: x-forwarded-proto +---- + +(The presence of either of those properties will switch on the valve. Or you can add the +`RemoteIpValve` yourself by adding a `TomcatEmbeddedServletContainerFactory` bean.) + +Spring Security can also be configured to require a secure channel for all (or some +requests). To switch that on in a Spring Boot application you just need to set +`security.require_https` to `true` in `application.properties`. + + + +[[howto-hotswapping]] +== Hot swapping + + + +[[howto-reload-static-content]] +=== 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 +<> 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. + + + +[[howto-reload-thymeleaf-content]] +=== 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 template customization options. + + + +[[howto-reload-java-classes-without-restarting]] +=== Reload Java classes without restarting the container +Modern IDEs (Eclipse, IDEA etc.) all support hot swapping of bytecode, so if you make a +change that doesn't affect class or method signatures it should reload cleanly with no +side effects. + +https://github.com/spring-projects/spring-loaded[Spring Loaded] goes a little further in +that it can reload class definitions with changes in the method signatures. With some +customization it can force an `ApplicationContext` to refresh itself (but there is no +general mechanism to ensure that would be safe for a running application anyway, so it +would only ever be a development time trick probably). + + + +[[howto-build]] +== Build + + + +[[howto-build-an-executable-archive-with-ant]] +=== Build an executable archive with Ant +To build with Ant you need to grab dependencies and compile and then create a jar or war +archive as normal. To make it executable: + +. 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`. + +. 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. + +. Add the `spring-boot-loader` classes at the root of the archive (so the `Main-Class` + is available). + +Example: + +[source,xml,indent=0,subs="verbatim,quotes,attributes"] +---- + + + + + + + + + + + + + + +---- + +The Actuator Sample has a `build.xml` that should work if you run it with + +[indent=0,subs="verbatim,quotes,attributes"] +---- + $ ant -lib /ivy-2.2.jar +---- + +after which you can run the application with + +[indent=0,subs="verbatim,quotes,attributes"] +---- + $ java -jar target/*.jar +---- + + + +[[howto-traditional-deployment]] +== Traditional deployment + + + +[[howto-create-a-deployable-war-file]] +=== 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 +http://spring.io/guides/gs/convert-jar-to-war[``Converting a jar Project to a war''] guide +on the spring.io website. + +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]. + + + +[[howto-create-a-deployable-war-file-for-older-containers]] +=== Create a deployable war file for older servlet containers +Older Servlet containers don't have support for the `ServletContextInitializer` bootstrap +process used in Servlet 3.0. You can still use Spring and Spring Boot in these containers +but you are going to need to add a `web.xml` to your application and configure it to load +an `ApplicationContext` via a `DispatcherServlet`. + + + +[[howto-convert-an-existing-application-to-spring-boot]] +=== Convert an existing application to Spring Boot +For a non-web application it should be easy (throw away the code that creates your +`ApplicationContext` and replace it with calls to `SpringApplication` or +`SpringApplicationBuilder`). Spring MVC web applications are generally amenable to first +creating a deployable war application, and then migrating it later to an executable war +and/or jar. Useful reading is in the http://spring.io/guides/gs/convert-jar-to-war/[Getting +Started Guide on Converting a jar to a war]. + +Create a deployable war by extending `SpringBootServletInitializer` (e.g. in a class +called `Application`), and add the Spring Boot `@EnableAutoConfiguration` annotation. +Example: + +[source,java,indent=0,subs="verbatim,quotes,attributes"] +---- + @Configuration + @EnableAutoConfiguration + @ComponentScan + public class Application extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(Application.class); + } + + } +---- + +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-INFO/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 `` and `` in `web.xml`. +* A `@Bean` of type `Filter` or `FilterRegistrationBean` behaves similarly (like a + `` and ``. +* 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. + +[source,java,indent=0,subs="verbatim,quotes,attributes"] +---- + 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 +<> 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. diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 5dfc7790d5..dc3955f3fd 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -291,7 +291,8 @@ properties). ---- TIP: You can also use this technique to create ``short'' variants of existing Spring Boot -properties. +properties. See the ``<>'' how-to +for details.