Commit 6281070d authored by Phillip Webb's avatar Phillip Webb

Merge branch '1.1.x'

Conflicts:
	spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
parents 9ba7a186 6009f417
...@@ -52,7 +52,6 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; ...@@ -52,7 +52,6 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.PropertyPlaceholderHelper; import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver; import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.View; import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.BeanNameViewResolver; import org.springframework.web.servlet.view.BeanNameViewResolver;
...@@ -107,7 +106,7 @@ public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustom ...@@ -107,7 +106,7 @@ public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustom
+ "<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>" + "<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>"
+ "<div id='created'>${timestamp}</div>" + "<div id='created'>${timestamp}</div>"
+ "<div>There was an unexpected error (type=${error}, status=${status}).</div>" + "<div>There was an unexpected error (type=${error}, status=${status}).</div>"
+ "<div>${message}</div>" + "</body></html>"); + "<div>${message}</div></body></html>");
@Bean(name = "error") @Bean(name = "error")
@ConditionalOnMissingBean(name = "error") @ConditionalOnMissingBean(name = "error")
...@@ -157,8 +156,6 @@ public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustom ...@@ -157,8 +156,6 @@ public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustom
private final String template; private final String template;
private final SpelExpressionParser parser = new SpelExpressionParser();
private final StandardEvaluationContext context = new StandardEvaluationContext(); private final StandardEvaluationContext context = new StandardEvaluationContext();
private PropertyPlaceholderHelper helper; private PropertyPlaceholderHelper helper;
...@@ -169,19 +166,7 @@ public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustom ...@@ -169,19 +166,7 @@ public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustom
this.template = template; this.template = template;
this.context.addPropertyAccessor(new MapAccessor()); this.context.addPropertyAccessor(new MapAccessor());
this.helper = new PropertyPlaceholderHelper("${", "}"); this.helper = new PropertyPlaceholderHelper("${", "}");
this.resolver = new PlaceholderResolver() { this.resolver = new SpelPlaceholderResolver(this.context);
@Override
public String resolvePlaceholder(String name) {
Expression expression = SpelView.this.parser.parseExpression(name);
try {
Object value = expression.getValue(SpelView.this.context);
return (value == null ? null : HtmlUtils.htmlEscape(value.toString()));
}
catch (Exception ex) {
return null;
}
}
};
} }
@Override @Override
...@@ -204,4 +189,31 @@ public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustom ...@@ -204,4 +189,31 @@ public class ErrorMvcAutoConfiguration implements EmbeddedServletContainerCustom
} }
/**
* SpEL based {@link PlaceholderResolver}.
*/
private static class SpelPlaceholderResolver implements PlaceholderResolver {
private final SpelExpressionParser parser = new SpelExpressionParser();
private final StandardEvaluationContext context;
public SpelPlaceholderResolver(StandardEvaluationContext context) {
this.context = context;
}
@Override
public String resolvePlaceholder(String name) {
Expression expression = this.parser.parseExpression(name);
try {
Object value = expression.getValue(this.context);
return HtmlUtils.htmlEscape(value == null ? null : value.toString());
}
catch (Exception ex) {
return null;
}
}
}
} }
...@@ -140,7 +140,7 @@ file and it's used to setup an appropriate `URLClassLoader` and ultimately call ...@@ -140,7 +140,7 @@ file and it's used to setup an appropriate `URLClassLoader` and ultimately call
There are 3 launcher subclasses (`JarLauncher`, `WarLauncher` and `PropertiesLauncher`). There are 3 launcher subclasses (`JarLauncher`, `WarLauncher` and `PropertiesLauncher`).
Their purpose is to load resources (`.class` files etc.) from nested jar files or war Their purpose is to load resources (`.class` files etc.) from nested jar files or war
files in directories (as opposed to explicitly on the classpath). In the case of the files in directories (as opposed to explicitly on the classpath). In the case of the
`[Jar|War]Launcher` the nested paths are fixed `(lib/\*.jar` and `lib-provided/\*.jar` for `[Jar|War]Launcher` the nested paths are fixed (`+lib/*.jar+` and `+lib-provided/*.jar+` for
the war case) so you just add extra jars in those locations if you want more. The the war case) so you just add extra jars in those locations if you want more. The
`PropertiesLauncher` looks in `lib/` by default, but you can add additional locations by `PropertiesLauncher` looks in `lib/` by default, but you can add additional locations by
setting an environment variable `LOADER_PATH` or `loader.path` in `application.properties` setting an environment variable `LOADER_PATH` or `loader.path` in `application.properties`
......
...@@ -57,7 +57,7 @@ using the latest version of Java. ...@@ -57,7 +57,7 @@ using the latest version of Java.
[[getting-started-installation-instructions-for-java]] [[getting-started-installation-instructions-for-java]]
=== Installation instructions for the Java developer === Installation instructions for the Java developer
You can use Spring Boot in the same way as any standard Java library. Simply include the You can use Spring Boot in the same way as any standard Java library. Simply include the
appropriate `spring-boot-*.jar` files on your classpath. Spring Boot does not require appropriate `+spring-boot-*.jar+` files on your classpath. Spring Boot does not require
any special tools integration, so you can use any IDE or text editor; and there is any special tools integration, so you can use any IDE or text editor; and there is
nothing special about a Spring Boot application, so you can run and debug as you would nothing special about a Spring Boot application, so you can run and debug as you would
any other Java program. any other Java program.
......
...@@ -6,6 +6,7 @@ Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson; ...@@ -6,6 +6,7 @@ Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson;
:source-highlighter: prettify :source-highlighter: prettify
:numbered: :numbered:
:icons: font :icons: font
:hide-uri-scheme:
:spring-boot-repo: snapshot :spring-boot-repo: snapshot
:github-tag: master :github-tag: master
:spring-boot-docs-version: current :spring-boot-docs-version: current
......
...@@ -184,7 +184,7 @@ implementations. To configure the severity or order add the following to your ap ...@@ -184,7 +184,7 @@ implementations. To configure the severity or order add the following to your ap
[[production-ready-application-info]] [[production-ready-application-info]]
=== Custom application info information === Custom application info information
You can customize the data exposed by the `info` endpoint by setting `info.*` Spring You can customize the data exposed by the `info` endpoint by setting `+info.*+` Spring
properties. All `Environment` properties under the info key will be automatically properties. All `Environment` properties under the info key will be automatically
exposed. For example, you could add the following to your `application.properties`: exposed. For example, you could add the following to your `application.properties`:
...@@ -234,7 +234,7 @@ You can then refer to your Maven '`project properties`' via placeholders, e.g. ...@@ -234,7 +234,7 @@ You can then refer to your Maven '`project properties`' via placeholders, e.g.
info.build.version=${project.version} info.build.version=${project.version}
---- ----
NOTE: In the above example we used `project.*` to set some values to be used as NOTE: In the above example we used `+project.*+` to set some values to be used as
fallbacks if the Maven resource filtering has not been switched on for some reason. fallbacks if the Maven resource filtering has not been switched on for some reason.
...@@ -554,8 +554,8 @@ The remote shell can be extended in a number of interesting ways. ...@@ -554,8 +554,8 @@ The remote shell can be extended in a number of interesting ways.
You can write additional shell commands using Groovy or Java (see the CRaSH documentation You can write additional shell commands using Groovy or Java (see the CRaSH documentation
for details). By default Spring Boot will search for commands in the following locations: for details). By default Spring Boot will search for commands in the following locations:
* `classpath*:/commands/**` * `+classpath*:/commands/**+`
* `classpath*:/crash/commands/**` * `+classpath*:/crash/commands/**+`
TIP: You can change the search path by settings a `shell.commandPathPatterns` property. TIP: You can change the search path by settings a `shell.commandPathPatterns` property.
...@@ -660,7 +660,7 @@ Here we can see basic `memory`, `heap`, `class loading`, `processor` and `thread ...@@ -660,7 +660,7 @@ Here we can see basic `memory`, `heap`, `class loading`, `processor` and `thread
information along with some HTTP metrics. In this instance the `root` ('`/`') and `/metrics` information along with some HTTP metrics. In this instance the `root` ('`/`') and `/metrics`
URLs have returned `HTTP 200` responses `20` and `3` times respectively. It also appears URLs have returned `HTTP 200` responses `20` and `3` times respectively. It also appears
that the `root` URL returned `HTTP 401` (unauthorized) `4` times. The double asterix (`star-star`) that the `root` URL returned `HTTP 401` (unauthorized) `4` times. The double asterix (`star-star`)
comes from a request matched by Spring MVC as `/**` (normally a static resource). comes from a request matched by Spring MVC as `+/**+` (normally a static resource).
The `gauge` shows the last response time for a request. So the last request to `root` took The `gauge` shows the last response time for a request. So the last request to `root` took
`2ms` to respond and the last to `/metrics` took `3ms`. `2ms` to respond and the last to `/metrics` took `3ms`.
...@@ -775,7 +775,7 @@ a dependency to the `com.codahale.metrics:metrics-core` library; you can also re ...@@ -775,7 +775,7 @@ a dependency to the `com.codahale.metrics:metrics-core` library; you can also re
own `@Bean` instance if you need customizations. own `@Bean` instance if you need customizations.
Users can create Coda Hale metrics by prefixing their metric names with the appropriate Users can create Coda Hale metrics by prefixing their metric names with the appropriate
type (e.g. `histogram.\*`, `meter.\*`). type (e.g. `+histogram.*+`, `+meter.*+`).
......
...@@ -206,7 +206,7 @@ sensible overriding of values, properties are considered in the the following or ...@@ -206,7 +206,7 @@ sensible overriding of values, properties are considered in the the following or
. Java System properties (`System.getProperties()`). . Java System properties (`System.getProperties()`).
. OS environment variables. . OS environment variables.
. JNDI attributes from `java:comp/env` . JNDI attributes from `java:comp/env`
. A `RandomValuePropertySource` that only has properties in `random.*`. . A `RandomValuePropertySource` that only has properties in `+random.*+`.
. Application properties outside of your packaged jar (`application.properties` . Application properties outside of your packaged jar (`application.properties`
including YAML and profile variants). including YAML and profile variants).
. Application properties packaged inside your jar (`application.properties` . Application properties packaged inside your jar (`application.properties`
...@@ -250,7 +250,7 @@ or test cases). It can produce integers, longs or strings, e.g. ...@@ -250,7 +250,7 @@ or test cases). It can produce integers, longs or strings, e.g.
my.number.in.range=${random.int[1024,65536]} my.number.in.range=${random.int[1024,65536]}
---- ----
The `random.int*` syntax is `OPEN value (,max) CLOSE` where the `OPEN,CLOSE` are any The `+random.int*+` syntax is `OPEN value (,max) CLOSE` where the `OPEN,CLOSE` are any
character and `value,max` are integers. If `max` is provided then `value` is the minimum character and `value,max` are integers. If `max` is provided then `value` is the minimum
value and `max` is the maximum (exclusive). value and `max` is the maximum (exclusive).
...@@ -740,7 +740,7 @@ As with console output, `ERROR`, `WARN` and `INFO` level messages are logged by ...@@ -740,7 +740,7 @@ As with console output, `ERROR`, `WARN` and `INFO` level messages are logged by
=== Log Levels === Log Levels
All the supported logging systems can have the logger levels set in the Spring All the supported logging systems can have the logger levels set in the Spring
`Environment` (so for example in `application.properties`) using '`logging.level.*=LEVEL`' `Environment` (so for example in `application.properties`) using '`+logging.level.*=LEVEL+`'
where '`LEVEL`' is one of TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF. Example where '`LEVEL`' is one of TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF. Example
`application.properties`: `application.properties`:
...@@ -933,7 +933,7 @@ the default MVC configuration) because Spring will always be able to handle requ ...@@ -933,7 +933,7 @@ the default MVC configuration) because Spring will always be able to handle requ
through the `DispatcherServlet`. through the `DispatcherServlet`.
In addition to the '`standard`' static resource locations above, a special case is made for In addition to the '`standard`' static resource locations above, a special case is made for
http://www.webjars.org/[Webjars content]. Any resources with a path in `/webjars/**` will http://www.webjars.org/[Webjars content]. Any resources with a path in `+/webjars/**+` will
be served from jar files if they are packaged in the Webjars format. be served from jar files if they are packaged in the Webjars format.
TIP: Do not use the `src/main/webapp` folder if your application will be packaged as a TIP: Do not use the `src/main/webapp` folder if your application will be packaged as a
...@@ -1101,7 +1101,7 @@ your `application.properties` during configuration. ...@@ -1101,7 +1101,7 @@ your `application.properties` during configuration.
By default, if the context contains only a single Servlet it will be mapped to `/`. In By default, if the context contains only a single Servlet it will be mapped to `/`. In
the case of multiple Servlets beans the bean name will be used as a path prefix. Filters the case of multiple Servlets beans the bean name will be used as a path prefix. Filters
will map to `/*`. will map to `+/*+`.
If convention-based mapping is not flexible enough you can use the If convention-based mapping is not flexible enough you can use the
`ServletRegistrationBean` and `FilterRegistrationBean` classes for complete control. You `ServletRegistrationBean` and `FilterRegistrationBean` classes for complete control. You
...@@ -1242,8 +1242,8 @@ The basic features you get out of the box in a web application are: ...@@ -1242,8 +1242,8 @@ The basic features you get out of the box in a web application are:
* An `AuthenticationManager` bean with in-memory store and a single user (see * An `AuthenticationManager` bean with in-memory store and a single user (see
`SecurityProperties.User` for the properties of the user). `SecurityProperties.User` for the properties of the user).
* Ignored (unsecure) paths for common static resource locations (`/css/\*\*`, `/js/\*\*`, * Ignored (unsecure) paths for common static resource locations (`+/css/**+`, `+/js/**+`,
`/images/\*\*` and `\*\*/favicon.ico`). `+/images/**+` and `+**/favicon.ico+`).
* HTTP Basic security for all other endpoints. * HTTP Basic security for all other endpoints.
* Security events published to Spring's `ApplicationEventPublisher` (successful and * Security events published to Spring's `ApplicationEventPublisher` (successful and
unsuccessful authentication and access denied). unsuccessful authentication and access denied).
...@@ -1251,7 +1251,7 @@ The basic features you get out of the box in a web application are: ...@@ -1251,7 +1251,7 @@ The basic features you get out of the box in a web application are:
on by default. on by default.
All of the above can be switched on and off or modified using external properties All of the above can be switched on and off or modified using external properties
(`security.*`). To override the access rules without changing any other autoconfigured (`+security.*+`). To override the access rules without changing any other autoconfigured
features add a `@Bean` of type `WebConfigurerAdapter` with features add a `@Bean` of type `WebConfigurerAdapter` with
`@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)`. `@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)`.
...@@ -1262,7 +1262,7 @@ If the Actuator is also in use, you will find: ...@@ -1262,7 +1262,7 @@ If the Actuator is also in use, you will find:
* The default user will have the `ADMIN` role as well as the `USER` role. * The default user will have the `ADMIN` role as well as the `USER` role.
The Actuator security features can be modified using external properties The Actuator security features can be modified using external properties
(`management.security.*`). To override the application access rules (`+management.security.*+`). To override the application access rules
add a `@Bean` of type `WebConfigurerAdapter` and use add a `@Bean` of type `WebConfigurerAdapter` and use
`@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)` if you _don't_ want to override `@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)` if you _don't_ want to override
the actuator access rules, or `@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)` the actuator access rules, or `@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)`
...@@ -1343,7 +1343,7 @@ NOTE: Additional connection pools can always be configured manually. If you defi ...@@ -1343,7 +1343,7 @@ NOTE: Additional connection pools can always be configured manually. If you defi
own `DataSource` bean, auto-configuration will not occur. own `DataSource` bean, auto-configuration will not occur.
DataSource configuration is controlled by external configuration properties in DataSource configuration is controlled by external configuration properties in
`spring.datasource.\*`. For example, you might declare the following section `+spring.datasource.*+`. For example, you might declare the following section
in `application.properties`: in `application.properties`:
[source,properties,indent=0] [source,properties,indent=0]
...@@ -1534,7 +1534,7 @@ their http://projects.spring.io/spring-data-jpa/[reference documentation]. ...@@ -1534,7 +1534,7 @@ their http://projects.spring.io/spring-data-jpa/[reference documentation].
==== Creating and dropping JPA databases ==== Creating and dropping JPA databases
By default JPA database will be automatically created *only* if you use an embedded By default JPA database will be automatically created *only* if you use an embedded
database (H2, HSQL or Derby). You can explicitly configure JPA settings using database (H2, HSQL or Derby). You can explicitly configure JPA settings using
`spring.jpa.*` properties. For example, to create and drop tables you can add the `+spring.jpa.*+` properties. For example, to create and drop tables you can add the
following to your `application.properties`. following to your `application.properties`.
[indent=0] [indent=0]
...@@ -1544,7 +1544,7 @@ following to your `application.properties`. ...@@ -1544,7 +1544,7 @@ following to your `application.properties`.
NOTE: Hibernate's own internal property name for this (if you happen to remember it NOTE: Hibernate's own internal property name for this (if you happen to remember it
better) is `hibernate.hbm2ddl.auto`. You can set it, along with other Hibernate native better) is `hibernate.hbm2ddl.auto`. You can set it, along with other Hibernate native
properties, using `spring.jpa.properties.*` (the prefix is stripped before adding them properties, using `+spring.jpa.properties.*+` (the prefix is stripped before adding them
to the entity manager). Example: to the entity manager). Example:
[indent=0] [indent=0]
...@@ -1898,7 +1898,7 @@ to integrate with JMS. Adding `org.hornetq:hornetq-jms-server` to your applicati ...@@ -1898,7 +1898,7 @@ to integrate with JMS. Adding `org.hornetq:hornetq-jms-server` to your applicati
you to use the embedded mode. you to use the embedded mode.
HornetQ configuration is controlled by external configuration properties in HornetQ configuration is controlled by external configuration properties in
`spring.hornetq.*`. For example, you might declare the following section in `+spring.hornetq.*+`. For example, you might declare the following section in
`application.properties`: `application.properties`:
[source,properties,indent=0] [source,properties,indent=0]
...@@ -1931,7 +1931,7 @@ available on the classpath. If the broker is present, an embedded broker is star ...@@ -1931,7 +1931,7 @@ available on the classpath. If the broker is present, an embedded broker is star
configured automatically (as long as no broker URL is specified through configuration). configured automatically (as long as no broker URL is specified through configuration).
ActiveMQ configuration is controlled by external configuration properties in ActiveMQ configuration is controlled by external configuration properties in
`spring.activemq.*`. For example, you might declare the following section in `+spring.activemq.*+`. For example, you might declare the following section in
`application.properties`: `application.properties`:
[source,properties,indent=0] [source,properties,indent=0]
......
...@@ -199,7 +199,7 @@ running quickly and with a consistent, supported set of managed transitive depen ...@@ -199,7 +199,7 @@ running quickly and with a consistent, supported set of managed transitive depen
.What's in a name .What's in a name
**** ****
All starters follow a similar naming pattern; `spring-boot-starter-\*`, where `*` is All starters follow a similar naming pattern; `+spring-boot-starter-*+`, where `+*+` is
a particular type of application. This naming structure is intended to help when you need a particular type of application. This naming structure is intended to help when you need
to find a starter. The Maven integration in many IDEs allow you to search dependencies by to find a starter. The Maven integration in many IDEs allow you to search dependencies by
name. For example, with the appropriate Eclipse or STS plugin installed, you can simply name. For example, with the appropriate Eclipse or STS plugin installed, you can simply
...@@ -430,7 +430,7 @@ is also a good candidate as the primary `@Configuration`. ...@@ -430,7 +430,7 @@ is also a good candidate as the primary `@Configuration`.
TIP: Many Spring configuration examples have been published on the Internet that use XML TIP: Many Spring configuration examples have been published on the Internet that use XML
configuration. Always try to use the equivalent Java-base configuration if possible. configuration. Always try to use the equivalent Java-base configuration if possible.
Searching for `enable*` annotations can be a good starting point. Searching for `+enable*+` annotations can be a good starting point.
......
...@@ -222,18 +222,21 @@ public class LoggingApplicationListener implements SmartApplicationListener { ...@@ -222,18 +222,21 @@ public class LoggingApplicationListener implements SmartApplicationListener {
Map<String, Object> levels = new RelaxedPropertyResolver(environment) Map<String, Object> levels = new RelaxedPropertyResolver(environment)
.getSubProperties("logging.level."); .getSubProperties("logging.level.");
for (Entry<String, Object> entry : levels.entrySet()) { for (Entry<String, Object> entry : levels.entrySet()) {
String name = entry.getKey(); setLogLevel(system, environment, entry.getKey(), entry.getValue().toString());
try { }
LogLevel level = LogLevel.valueOf(environment.resolvePlaceholders(entry.getValue().toString())); }
if (name.equalsIgnoreCase("root")) {
name = null; private void setLogLevel(LoggingSystem system, Environment environment, String name,
} String level) {
system.setLogLevel(name, level); try {
} if (name.equalsIgnoreCase("root")) {
catch (RuntimeException e) { name = null;
this.logger.error("Cannot set level: " + entry.getValue() + " for '"
+ name + "'");
} }
level = environment.resolvePlaceholders(level);
system.setLogLevel(name, LogLevel.valueOf(level));
}
catch (RuntimeException ex) {
this.logger.error("Cannot set level: " + level + " for '" + name + "'");
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment