Polish
This commit is contained in:
parent
fd1cbed51c
commit
6c2ea4648f
|
@ -20,13 +20,13 @@ package org.springframework.boot.actuate.metrics.writer;
|
|||
* Simple writer for counters (metrics that increment).
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public interface CounterWriter {
|
||||
|
||||
/**
|
||||
* Increment the value of a metric (or decrement if the delta is negative). The name
|
||||
* of the delta is the name of the metric to increment.
|
||||
*
|
||||
* @param delta the amount to increment by
|
||||
*/
|
||||
void increment(Delta<?> delta);
|
||||
|
@ -34,9 +34,8 @@ public interface CounterWriter {
|
|||
/**
|
||||
* Reset the value of a metric, usually to zero value. Implementations can discard the
|
||||
* old values if desired, but may choose not to. This operation is optional (some
|
||||
* implementations may not be able to fulfil the contract, in which case they should
|
||||
* implementations may not be able to fulfill the contract, in which case they should
|
||||
* simply do nothing).
|
||||
*
|
||||
* @param metricName the name to reset
|
||||
*/
|
||||
void reset(String metricName);
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.springframework.boot.actuate.metrics.Metric;
|
|||
* Writer for gauge values (simple metric with a number value).
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public interface GaugeWriter {
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ import org.springframework.boot.actuate.metrics.Metric;
|
|||
* Basic strategy for write operations on {@link Metric} data.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see GaugeWriter
|
||||
* @see CounterWriter
|
||||
*/
|
||||
public interface MetricWriter extends GaugeWriter, CounterWriter {
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public class AuthenticationAuditListener implements
|
|||
this.webListener.process(this, event);
|
||||
}
|
||||
else if (event instanceof AuthenticationSuccessEvent) {
|
||||
onAuthenticationEvent((AuthenticationSuccessEvent) event);
|
||||
onAuthenticationSuccessEvent((AuthenticationSuccessEvent) event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ public class AuthenticationAuditListener implements
|
|||
"AUTHENTICATION_FAILURE", data));
|
||||
}
|
||||
|
||||
private void onAuthenticationEvent(AuthenticationSuccessEvent event) {
|
||||
private void onAuthenticationSuccessEvent(AuthenticationSuccessEvent event) {
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
if (event.getAuthentication().getDetails() != null) {
|
||||
data.put("details", event.getAuthentication().getDetails());
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||
* Configuration properties for OAuth2 Authorization server.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@ConfigurationProperties("security.oauth2.authorization")
|
||||
public class AuthorizationServerProperties {
|
||||
|
|
|
@ -94,13 +94,16 @@ public class OAuth2AuthorizationServerConfiguration
|
|||
.scopes(this.details.getScope().toArray(new String[0]));
|
||||
|
||||
if (this.details.getAutoApproveScopes() != null) {
|
||||
builder.autoApprove(this.details.getAutoApproveScopes().toArray(new String[0]));
|
||||
builder.autoApprove(
|
||||
this.details.getAutoApproveScopes().toArray(new String[0]));
|
||||
}
|
||||
if (this.details.getAccessTokenValiditySeconds() != null) {
|
||||
builder.accessTokenValiditySeconds(this.details.getAccessTokenValiditySeconds());
|
||||
builder.accessTokenValiditySeconds(
|
||||
this.details.getAccessTokenValiditySeconds());
|
||||
}
|
||||
if (this.details.getRefreshTokenValiditySeconds() != null) {
|
||||
builder.refreshTokenValiditySeconds(this.details.getRefreshTokenValiditySeconds());
|
||||
builder.refreshTokenValiditySeconds(
|
||||
this.details.getRefreshTokenValiditySeconds());
|
||||
}
|
||||
if (this.details.getRegisteredRedirectUri() != null) {
|
||||
builder.redirectUris(
|
||||
|
|
|
@ -114,9 +114,7 @@ public class OAuth2ResourceServerConfiguration {
|
|||
Environment environment = context.getEnvironment();
|
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
|
||||
"security.oauth2.resource.");
|
||||
String client = environment
|
||||
.resolvePlaceholders("${security.oauth2.client.client-id:}");
|
||||
if (StringUtils.hasText(client)) {
|
||||
if (hasOAuthClientId(environment)) {
|
||||
return ConditionOutcome.match("found client id");
|
||||
}
|
||||
if (!resolver.getSubProperties("jwt").isEmpty()) {
|
||||
|
@ -137,6 +135,12 @@ public class OAuth2ResourceServerConfiguration {
|
|||
+ "JWT resource nor authorization server");
|
||||
}
|
||||
|
||||
private boolean hasOAuthClientId(Environment environment) {
|
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
|
||||
"security.oauth2.client.");
|
||||
return StringUtils.hasLength(resolver.getProperty("client-id", ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnBean(AuthorizationServerEndpointsConfiguration.class)
|
||||
|
|
|
@ -140,4 +140,5 @@ public class UserInfoTokenServices implements ResourceServerTokenServices {
|
|||
"Could not fetch user details");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.springframework.util.ReflectionUtils;
|
|||
* {@link RestartListener} that prepares Log4J2 for an application restart.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class Log4J2RestartListener implements RestartListener {
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.springframework.boot.devtools.restart;
|
|||
* Listener that is notified of application restarts.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public interface RestartListener {
|
||||
|
||||
|
|
|
@ -411,6 +411,7 @@ and mark it as disabled. For example:
|
|||
----
|
||||
|
||||
|
||||
|
||||
[[howto-add-a-servlet-filter-or-listener-using-scanning]]
|
||||
==== Add Servlets, Filters, and Listeners using classpath scanning
|
||||
`@WebServlet`, `@WebFilter`, and `@WebListener` annotated classes can be automatically
|
||||
|
|
|
@ -186,13 +186,14 @@ If the https://github.com/mikekelly/hal-browser[HAL Browser] is on the classpath
|
|||
via its webjar (`org.webjars:hal-browser`), or via the `spring-data-rest-hal-browser` then
|
||||
an HTML "`discovery page`", in the form of the HAL Browser, is also provided.
|
||||
|
||||
|
||||
|
||||
[[production-ready-endpoint-cors]]
|
||||
=== CORS support
|
||||
|
||||
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing[Cross-origin resource sharing]
|
||||
(CORS) is a http://www.w3.org/TR/cors/[W3C specification] that allows you to specify in a
|
||||
flexible way what kind of cross domain requests are authorized. Actuator's MVC endpoints
|
||||
can be configured to support such scenario.
|
||||
can be configured to support such scenarios.
|
||||
|
||||
CORS support is disabled by default and is only enabled once the
|
||||
`endpoints.cors.allowed-origins` property has been set. The configuration below permits
|
||||
|
@ -208,6 +209,7 @@ TIP: Check {sc-spring-boot-actuator}/autoconfigure/EndpointCorsProperties.{sc-ex
|
|||
for a complete list of options.
|
||||
|
||||
|
||||
|
||||
[[production-ready-customizing-endpoints-programmatically]]
|
||||
=== Adding custom endpoints
|
||||
If you add a `@Bean` of type `Endpoint` then it will automatically be exposed over JMX and
|
||||
|
@ -1076,16 +1078,13 @@ used by default if you are on Java 8 or if you are using Dropwizard metrics.
|
|||
|
||||
[[production-ready-metric-writers]]
|
||||
=== Metric writers, exporters and aggregation
|
||||
|
||||
Spring Boot provides a couple of implementations of a marker interface
|
||||
called `Exporter` which can be used to copy metric readings from the
|
||||
in-memory buffers to a place where they can be analyzed and
|
||||
displayed. Indeed, if you provide a `@Bean` that implements the
|
||||
`MetricWriter` interface (or `GaugeWriter` for simple use cases) and
|
||||
mark it `@ExportMetricWriter`, then it will automatically be hooked up
|
||||
to an `Exporter` and fed metric updates every 5 seconds (configured
|
||||
via `spring.metrics.export.delay-millis`). In addition, any
|
||||
`MetricReader` that you define and mark as `@ExportMetricReader` will
|
||||
Spring Boot provides a couple of implementations of a marker interface called `Exporter`
|
||||
which can be used to copy metric readings from the in-memory buffers to a place where they
|
||||
can be analyzed and displayed. Indeed, if you provide a `@Bean` that implements the
|
||||
`MetricWriter` interface (or `GaugeWriter` for simple use cases) and mark it
|
||||
`@ExportMetricWriter`, then it will automatically be hooked up to an `Exporter` and fed
|
||||
metric updates every 5 seconds (configured via `spring.metrics.export.delay-millis`).
|
||||
In addition, any `MetricReader` that you define and mark as `@ExportMetricReader` will
|
||||
have its values exported by the default exporter.
|
||||
|
||||
The default exporter is a `MetricCopyExporter` which tries to optimize itself by not
|
||||
|
|
|
@ -330,16 +330,13 @@ To provide a concrete example, suppose you develop a `@Component` that uses a
|
|||
----
|
||||
|
||||
On your application classpath (e.g. inside your jar) you can have an
|
||||
`application.properties` that provides a sensible default property
|
||||
value for `name`. When running in a new environment, an
|
||||
`application.properties` can be provided outside of your jar that
|
||||
overrides the `name`; and for one-off testing, you can launch with a
|
||||
specific command line switch (e.g. `java -jar app.jar
|
||||
--name="Spring"`).
|
||||
`application.properties` that provides a sensible default property value for `name`. When
|
||||
running in a new environment, an `application.properties` can be provided outside of your
|
||||
jar that overrides the `name`; and for one-off testing, you can launch with a specific
|
||||
command line switch (e.g. `java -jar app.jar --name="Spring"`).
|
||||
|
||||
[TIP]
|
||||
====
|
||||
|
||||
The `SPRING_APPLICATION_JSON` properties can be supplied on the
|
||||
command line with an environment variable. For example in a
|
||||
UN{asterisk}X shell:
|
||||
|
@ -366,6 +363,7 @@ or as a JNDI variable `java:comp/env/spring.application.json`.
|
|||
====
|
||||
|
||||
|
||||
|
||||
[[boot-features-external-config-random-values]]
|
||||
=== Configuring random values
|
||||
The `RandomValuePropertySource` is useful for injecting random values (e.g. into secrets
|
||||
|
|
|
@ -27,9 +27,9 @@ work with other build systems (Ant for example), but they will not be particular
|
|||
supported.
|
||||
|
||||
|
||||
|
||||
[[using-boot-dependency-management]]
|
||||
=== Dependency management
|
||||
|
||||
Each release of Spring Boot provides a curated list of dependencies it supports. In
|
||||
practice, you do not need to provide a version for any of these dependencies in your
|
||||
build configuration as Spring Boot is managing that for you. When you upgrade Spring
|
||||
|
@ -48,6 +48,7 @@ WARNING: Each release of Spring Boot is associated with a base version of the Sp
|
|||
Framework so we **highly** recommend you to not specify its version on your own.
|
||||
|
||||
|
||||
|
||||
[[using-boot-maven]]
|
||||
=== Maven
|
||||
Maven users can inherit from the `spring-boot-starter-parent` project to obtain sensible
|
||||
|
@ -105,6 +106,7 @@ TIP: Check the {github-code}/spring-boot-dependencies/pom.xml[`spring-boot-depen
|
|||
for a list of supported properties.
|
||||
|
||||
|
||||
|
||||
[[using-boot-maven-without-a-parent]]
|
||||
==== Using Spring Boot without the parent POM
|
||||
Not everyone likes inheriting from the `spring-boot-starter-parent` POM. You may have your
|
||||
|
@ -164,6 +166,7 @@ NOTE: In the example above, we specify a _BOM_ but any dependency type can be ov
|
|||
that way.
|
||||
|
||||
|
||||
|
||||
[[using-boot-maven-java-version]]
|
||||
==== Changing the Java version
|
||||
The `spring-boot-starter-parent` chooses fairly conservative Java compatibility. If you
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
<module>spring-boot-sample-property-validation</module>
|
||||
<module>spring-boot-sample-secure</module>
|
||||
<module>spring-boot-sample-secure-oauth2</module>
|
||||
<module>spring-boot-sample-secure-oauth2-resource</module>
|
||||
<module>spring-boot-sample-secure-sso</module>
|
||||
<module>spring-boot-sample-servlet</module>
|
||||
<module>spring-boot-sample-session-redis</module>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.secure.oauth2;
|
||||
package sample.secure.oauth2.resource;
|
||||
|
||||
import java.util.Date;
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.secure.oauth2;
|
||||
package sample.secure.oauth2.resource;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
|
@ -13,7 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package sample.secure.oauth2;
|
||||
|
||||
package sample.secure.oauth2.resource;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
@ -23,8 +24,9 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.R
|
|||
|
||||
@SpringBootApplication
|
||||
@EnableResourceServer
|
||||
public class SampleSecureOAuth2ResourceApplication extends ResourceServerConfigurerAdapter {
|
||||
|
||||
public class SampleSecureOAuth2ResourceApplication
|
||||
extends ResourceServerConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
http.antMatcher("/flights/**").authorizeRequests().anyRequest().authenticated();
|
|
@ -1,13 +1,25 @@
|
|||
package sample.secure.oauth2;
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
|
||||
package sample.secure.oauth2.resource;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.boot.test.WebIntegrationTest;
|
||||
|
@ -18,6 +30,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
|
||||
|
||||
/**
|
||||
* Series of automated integration tests to verify proper behavior of auto-configured,
|
||||
* OAuth2-secured system
|
||||
|
@ -36,6 +53,7 @@ public class SampleSecureOAuth2ResourceApplicationTests {
|
|||
FilterChainProxy filterChain;
|
||||
|
||||
private MockMvc mvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mvc = webAppContextSetup(this.context).addFilters(this.filterChain).build();
|
||||
|
@ -44,8 +62,8 @@ public class SampleSecureOAuth2ResourceApplicationTests {
|
|||
|
||||
@Test
|
||||
public void homePageAvailable() throws Exception {
|
||||
this.mvc.perform(get("/").accept(MediaTypes.HAL_JSON))
|
||||
.andExpect(status().isOk()).andDo(print());
|
||||
this.mvc.perform(get("/").accept(MediaTypes.HAL_JSON)).andExpect(status().isOk())
|
||||
.andDo(print());
|
||||
}
|
||||
|
||||
@Test
|
|
@ -51,8 +51,7 @@ class TypeElementMembers {
|
|||
|
||||
private final Map<String, ExecutableElement> publicGetters = new LinkedHashMap<String, ExecutableElement>();
|
||||
|
||||
private final Map<String, List<ExecutableElement>> publicSetters =
|
||||
new LinkedHashMap<String, List<ExecutableElement>>();
|
||||
private final Map<String, List<ExecutableElement>> publicSetters = new LinkedHashMap<String, List<ExecutableElement>>();
|
||||
|
||||
TypeElementMembers(ProcessingEnvironment env, TypeElement element) {
|
||||
this.env = env;
|
||||
|
@ -84,7 +83,8 @@ class TypeElementMembers {
|
|||
}
|
||||
else if (isSetter(method)) {
|
||||
String propertyName = getAccessorName(name);
|
||||
List<ExecutableElement> matchingSetters = this.publicSetters.get(propertyName);
|
||||
List<ExecutableElement> matchingSetters = this.publicSetters
|
||||
.get(propertyName);
|
||||
if (matchingSetters == null) {
|
||||
matchingSetters = new ArrayList<ExecutableElement>();
|
||||
this.publicSetters.put(propertyName, matchingSetters);
|
||||
|
@ -97,7 +97,8 @@ class TypeElementMembers {
|
|||
}
|
||||
}
|
||||
|
||||
private ExecutableElement getMatchingSetter(List<ExecutableElement> candidates, TypeMirror type) {
|
||||
private ExecutableElement getMatchingSetter(List<ExecutableElement> candidates,
|
||||
TypeMirror type) {
|
||||
for (ExecutableElement candidate : candidates) {
|
||||
TypeMirror paramType = candidate.getParameters().get(0).asType();
|
||||
if (this.env.getTypeUtils().isSameType(paramType, type)) {
|
||||
|
|
|
@ -40,7 +40,6 @@ import javax.lang.model.util.Types;
|
|||
class TypeUtils {
|
||||
|
||||
private static final Map<TypeKind, Class<?>> PRIMITIVE_WRAPPERS;
|
||||
private static final Map<String, TypeKind> WRAPPER_TO_PRIMITIVE;
|
||||
|
||||
static {
|
||||
Map<TypeKind, Class<?>> wrappers = new HashMap<TypeKind, Class<?>>();
|
||||
|
@ -53,16 +52,15 @@ class TypeUtils {
|
|||
wrappers.put(TypeKind.LONG, Long.class);
|
||||
wrappers.put(TypeKind.SHORT, Short.class);
|
||||
PRIMITIVE_WRAPPERS = Collections.unmodifiableMap(wrappers);
|
||||
}
|
||||
|
||||
private static final Map<String, TypeKind> WRAPPER_TO_PRIMITIVE;
|
||||
|
||||
static {
|
||||
Map<String, TypeKind> primitives = new HashMap<String, TypeKind>();
|
||||
primitives.put(Boolean.class.getName(), TypeKind.BOOLEAN);
|
||||
primitives.put(Byte.class.getName(), TypeKind.BYTE);
|
||||
primitives.put(Character.class.getName(), TypeKind.CHAR);
|
||||
primitives.put(Double.class.getName(), TypeKind.DOUBLE);
|
||||
primitives.put(Float.class.getName(), TypeKind.FLOAT);
|
||||
primitives.put(Integer.class.getName(), TypeKind.INT);
|
||||
primitives.put(Long.class.getName(), TypeKind.LONG);
|
||||
primitives.put(Short.class.getName(), TypeKind.SHORT);
|
||||
for (Map.Entry<TypeKind, Class<?>> entry : PRIMITIVE_WRAPPERS.entrySet()) {
|
||||
primitives.put(entry.getValue().getName(), entry.getKey());
|
||||
}
|
||||
WRAPPER_TO_PRIMITIVE = primitives;
|
||||
}
|
||||
|
||||
|
@ -111,7 +109,6 @@ class TypeUtils {
|
|||
|| this.env.getTypeUtils().isAssignable(type, this.mapType);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEnclosedIn(Element candidate, TypeElement element) {
|
||||
if (candidate == null || element == null) {
|
||||
return false;
|
||||
|
@ -134,7 +131,8 @@ class TypeUtils {
|
|||
public TypeMirror getWrapperOrPrimitiveFor(TypeMirror typeMirror) {
|
||||
Class<?> candidate = getWrapperFor(typeMirror);
|
||||
if (candidate != null) {
|
||||
return this.env.getElementUtils().getTypeElement(candidate.getName()).asType();
|
||||
return this.env.getElementUtils().getTypeElement(candidate.getName())
|
||||
.asType();
|
||||
}
|
||||
TypeKind primitiveKind = getPrimitiveFor(typeMirror);
|
||||
if (primitiveKind != null) {
|
||||
|
|
|
@ -205,11 +205,9 @@ public class ConfigurationMetadataAnnotationProcessorTests {
|
|||
ConfigurationMetadata metadata = compile(type);
|
||||
assertThat(metadata, containsGroup("not.deprecated").fromSource(type));
|
||||
assertThat(metadata, containsProperty("not.deprecated.counter", Integer.class)
|
||||
.withNoDeprecation()
|
||||
.fromSource(type));
|
||||
.withNoDeprecation().fromSource(type));
|
||||
assertThat(metadata, containsProperty("not.deprecated.flag", Boolean.class)
|
||||
.withNoDeprecation()
|
||||
.fromSource(type));
|
||||
.withNoDeprecation().fromSource(type));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -217,10 +215,10 @@ public class ConfigurationMetadataAnnotationProcessorTests {
|
|||
Class<?> type = BoxingPojo.class;
|
||||
ConfigurationMetadata metadata = compile(type);
|
||||
assertThat(metadata, containsGroup("boxing").fromSource(type));
|
||||
assertThat(metadata, containsProperty("boxing.flag", Boolean.class)
|
||||
.fromSource(type));
|
||||
assertThat(metadata, containsProperty("boxing.counter", Integer.class)
|
||||
.fromSource(type));
|
||||
assertThat(metadata,
|
||||
containsProperty("boxing.flag", Boolean.class).fromSource(type));
|
||||
assertThat(metadata,
|
||||
containsProperty("boxing.counter", Integer.class).fromSource(type));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -366,12 +364,9 @@ public class ConfigurationMetadataAnnotationProcessorTests {
|
|||
null, null, true, null);
|
||||
writeAdditionalMetadata(property);
|
||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
||||
assertThat(metadata,
|
||||
containsProperty("simple.flag", Boolean.class)
|
||||
.fromSource(SimpleProperties.class)
|
||||
.withDescription("A simple flag.")
|
||||
.withDeprecation(null, null)
|
||||
.withDefaultValue(is(true)));
|
||||
assertThat(metadata, containsProperty("simple.flag", Boolean.class)
|
||||
.fromSource(SimpleProperties.class).withDescription("A simple flag.")
|
||||
.withDeprecation(null, null).withDefaultValue(is(true)));
|
||||
assertThat(metadata.getItems().size(), is(4));
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ package org.springframework.boot.configurationsample.specific;
|
|||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Demonstrate the use of boxing/unboxing. Even if the type does not
|
||||
* strictly match, it should still be detected.
|
||||
* Demonstrate the use of boxing/unboxing. Even if the type does not strictly match, it
|
||||
* should still be detected.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
|
|
|
@ -19,8 +19,8 @@ package org.springframework.boot.configurationsample.specific;
|
|||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Demonstrate that an unrelated setter is not taken into account
|
||||
* to detect the deprecated flag.
|
||||
* Demonstrate that an unrelated setter is not taken into account to detect the deprecated
|
||||
* flag.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
|
|
|
@ -63,11 +63,9 @@ public class LaunchedURLClassLoader extends URLClassLoader {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the resource with the given {@code name}.
|
||||
* <p>
|
||||
* Unlike a standard {@link ClassLoader}, this method will first search the root class
|
||||
* loader. If the resource is not found, this method will call
|
||||
* {@link #findResource(String)}.
|
||||
* Gets the resource with the given {@code name}. Unlike a standard
|
||||
* {@link ClassLoader}, this method will first search the root class loader. If the
|
||||
* resource is not found, this method will call {@link #findResource(String)}.
|
||||
*/
|
||||
@Override
|
||||
public URL getResource(String name) {
|
||||
|
@ -104,11 +102,10 @@ public class LaunchedURLClassLoader extends URLClassLoader {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the resources with the given {@code name}.
|
||||
* <p>
|
||||
* Returns a combination of the resources found by {@link #findResources(String)} and
|
||||
* from {@link ClassLoader#getResources(String) getResources(String)} on the root
|
||||
* class loader, if any.
|
||||
* Gets the resources with the given {@code name}. Returns a combination of the
|
||||
* resources found by {@link #findResources(String)} and from
|
||||
* {@link ClassLoader#getResources(String) getResources(String)} on the root class
|
||||
* loader, if any.
|
||||
*/
|
||||
@Override
|
||||
public Enumeration<URL> getResources(String name) throws IOException {
|
||||
|
|
|
@ -40,9 +40,8 @@ import org.springframework.context.annotation.Import;
|
|||
public @interface EnableConfigurationProperties {
|
||||
|
||||
/**
|
||||
* Convenient way to quickly register {@link ConfigurationProperties} annotated
|
||||
* beans with Spring. Standard Spring Beans will also be scanned regardless of
|
||||
* this value.
|
||||
* Convenient way to quickly register {@link ConfigurationProperties} annotated beans
|
||||
* with Spring. Standard Spring Beans will also be scanned regardless of this value.
|
||||
* @return {@link ConfigurationProperties} annotated beans to register
|
||||
*/
|
||||
Class<?>[] value() default {};
|
||||
|
|
|
@ -115,8 +115,9 @@ class EnableConfigurationPropertiesImportSelector implements ImportSelector {
|
|||
|
||||
ConfigurationProperties properties = AnnotationUtils.findAnnotation(type,
|
||||
ConfigurationProperties.class);
|
||||
Assert.notNull(properties, "No " + ConfigurationProperties.class.getSimpleName()
|
||||
+ " annotation found on '" + type.getName() + "'.");
|
||||
Assert.notNull(properties,
|
||||
"No " + ConfigurationProperties.class.getSimpleName()
|
||||
+ " annotation found on '" + type.getName() + "'.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
|||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
@ -38,24 +39,29 @@ import org.springframework.web.context.support.StandardServletEnvironment;
|
|||
|
||||
/**
|
||||
* An {@link EnvironmentPostProcessor} that parses JSON from
|
||||
* <code>spring.application.json</code> or equivalently
|
||||
* {@code spring.application.json} or equivalently
|
||||
* {@link SpringApplicationJsonEnvironmentPostProcessor} and adds it as a map property
|
||||
* source to the {@link Environment}. The new properties are added with higher priority
|
||||
* than the system properties.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class SpringApplicationJsonEnvironmentPostProcessor
|
||||
implements EnvironmentPostProcessor, Ordered {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(SpringApplicationJsonEnvironmentPostProcessor.class);
|
||||
private static final String SERVLET_ENVIRONMENT_CLASS = "org.springframework.web."
|
||||
+ "context.support.StandardServletEnvironment";
|
||||
|
||||
/**
|
||||
* The default order for the processor.
|
||||
*/
|
||||
public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 5;
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(SpringApplicationJsonEnvironmentPostProcessor.class);
|
||||
|
||||
private int order = DEFAULT_ORDER;
|
||||
|
||||
@Override
|
||||
|
@ -73,26 +79,22 @@ public class SpringApplicationJsonEnvironmentPostProcessor
|
|||
String json = environment.resolvePlaceholders(
|
||||
"${spring.application.json:${SPRING_APPLICATION_JSON:}}");
|
||||
if (StringUtils.hasText(json)) {
|
||||
try {
|
||||
JsonParser parser = JsonParserFactory.getJsonParser();
|
||||
Map<String, Object> map = parser.parseMap(json);
|
||||
if (!map.isEmpty()) {
|
||||
MapPropertySource source = new MapPropertySource(
|
||||
"spring.application.json", flatten(map));
|
||||
MutablePropertySources sources = environment.getPropertySources();
|
||||
String name = findPropertySource(sources);
|
||||
if (sources.contains(name)) {
|
||||
sources.addBefore(name, source);
|
||||
}
|
||||
else {
|
||||
sources.addFirst(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Cannot parse JSON for spring.application.json: " + json, e);
|
||||
processJson(environment, json);
|
||||
}
|
||||
}
|
||||
|
||||
private void processJson(ConfigurableEnvironment environment, String json) {
|
||||
try {
|
||||
JsonParser parser = JsonParserFactory.getJsonParser();
|
||||
Map<String, Object> map = parser.parseMap(json);
|
||||
if (!map.isEmpty()) {
|
||||
addJsonPropertySource(environment,
|
||||
new MapPropertySource("spring.application.json", flatten(map)));
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.warn("Cannot parse JSON for spring.application.json: " + json, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,30 +110,20 @@ public class SpringApplicationJsonEnvironmentPostProcessor
|
|||
|
||||
private void flatten(String prefix, Map<String, Object> result,
|
||||
Map<String, Object> map) {
|
||||
if (prefix == null) {
|
||||
prefix = "";
|
||||
}
|
||||
else {
|
||||
prefix = prefix + ".";
|
||||
}
|
||||
for (String key : map.keySet()) {
|
||||
String name = prefix + key;
|
||||
Object value = map.get(key);
|
||||
extract(name, result, value);
|
||||
prefix = (prefix == null ? "" : prefix + ".");
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
extract(prefix + entry.getKey(), result, entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void extract(String name, Map<String, Object> result, Object value) {
|
||||
if (value instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> nested = (Map<String, Object>) value;
|
||||
flatten(name, result, nested);
|
||||
flatten(name, result, (Map<String, Object>) value);
|
||||
}
|
||||
if (value instanceof Collection) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Object> nested = (Collection<Object>) value;
|
||||
int index = 0;
|
||||
for (Object object : nested) {
|
||||
for (Object object : (Collection<Object>) value) {
|
||||
extract(name + "[" + index + "]", result, object);
|
||||
index++;
|
||||
}
|
||||
|
@ -141,12 +133,21 @@ public class SpringApplicationJsonEnvironmentPostProcessor
|
|||
}
|
||||
}
|
||||
|
||||
private void addJsonPropertySource(ConfigurableEnvironment environment,
|
||||
PropertySource<?> source) {
|
||||
MutablePropertySources sources = environment.getPropertySources();
|
||||
String name = findPropertySource(sources);
|
||||
if (sources.contains(name)) {
|
||||
sources.addBefore(name, source);
|
||||
}
|
||||
else {
|
||||
sources.addFirst(source);
|
||||
}
|
||||
}
|
||||
|
||||
private String findPropertySource(MutablePropertySources sources) {
|
||||
if (ClassUtils.isPresent(
|
||||
"org.springframework.web.context.support.StandardServletEnvironment",
|
||||
null)
|
||||
&& sources
|
||||
.contains(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME)) {
|
||||
if (ClassUtils.isPresent(SERVLET_ENVIRONMENT_CLASS, null) && sources
|
||||
.contains(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME)) {
|
||||
return StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME;
|
||||
|
||||
}
|
||||
|
|
|
@ -712,7 +712,6 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
|
|||
@EnableConfigurationProperties(PropertyWithoutConfigurationPropertiesAnnotation.class)
|
||||
public static class ConfigurationPropertiesWithoutAnnotation {
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static class PropertyWithoutConfigurationPropertiesAnnotation {
|
||||
|
@ -726,6 +725,7 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
|
|||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -415,41 +415,49 @@ public class EnableConfigurationPropertiesTests {
|
|||
@Configuration
|
||||
@EnableConfigurationProperties(TestProperties.class)
|
||||
protected static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(StrictTestProperties.class)
|
||||
protected static class StrictTestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(EmbeddedTestProperties.class)
|
||||
protected static class EmbeddedTestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(IgnoreNestedTestProperties.class)
|
||||
protected static class IgnoreNestedTestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(ExceptionIfInvalidTestProperties.class)
|
||||
protected static class ExceptionIfInvalidTestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(NoExceptionIfInvalidTestProperties.class)
|
||||
protected static class NoExceptionIfInvalidTestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(DerivedProperties.class)
|
||||
protected static class DerivedConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(NestedProperties.class)
|
||||
protected static class NestedConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
@ -467,6 +475,7 @@ public class EnableConfigurationPropertiesTests {
|
|||
@Configuration
|
||||
@ImportResource("org/springframework/boot/context/properties/testProperties.xml")
|
||||
protected static class DefaultXmlConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@EnableConfigurationProperties
|
||||
|
@ -483,16 +492,19 @@ public class EnableConfigurationPropertiesTests {
|
|||
@EnableConfigurationProperties(External.class)
|
||||
@Configuration
|
||||
public static class AnotherExampleConfig {
|
||||
|
||||
}
|
||||
|
||||
@EnableConfigurationProperties({ External.class, Another.class })
|
||||
@Configuration
|
||||
public static class FurtherExampleConfig {
|
||||
|
||||
}
|
||||
|
||||
@EnableConfigurationProperties({ SystemEnvVar.class })
|
||||
@Configuration
|
||||
public static class SystemExampleConfig {
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties(prefix = "external")
|
||||
|
@ -507,6 +519,7 @@ public class EnableConfigurationPropertiesTests {
|
|||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties(prefix = "another")
|
||||
|
@ -521,11 +534,14 @@ public class EnableConfigurationPropertiesTests {
|
|||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties(prefix = "spring_test_external")
|
||||
public static class SystemEnvVar {
|
||||
|
||||
private String val;
|
||||
|
||||
public String getVal() {
|
||||
return this.val;
|
||||
}
|
||||
|
@ -534,8 +550,6 @@ public class EnableConfigurationPropertiesTests {
|
|||
this.val = val;
|
||||
}
|
||||
|
||||
private String val;
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
|
@ -552,19 +566,20 @@ public class EnableConfigurationPropertiesTests {
|
|||
public String getName() {
|
||||
return this.properties.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(MoreProperties.class)
|
||||
protected static class MoreConfiguration {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(InvalidConfiguration.class)
|
||||
protected static class InvalidConfiguration {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties
|
||||
protected static class NestedProperties {
|
||||
|
@ -605,6 +620,7 @@ public class EnableConfigurationPropertiesTests {
|
|||
}
|
||||
|
||||
protected static class DerivedProperties extends BaseProperties {
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties
|
||||
|
@ -638,14 +654,17 @@ public class EnableConfigurationPropertiesTests {
|
|||
|
||||
@ConfigurationProperties(ignoreUnknownFields = false)
|
||||
protected static class StrictTestProperties extends TestProperties {
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties(prefix = "spring.foo")
|
||||
protected static class EmbeddedTestProperties extends TestProperties {
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties(ignoreUnknownFields = false, ignoreNestedProperties = true)
|
||||
protected static class IgnoreNestedTestProperties extends TestProperties {
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties
|
||||
|
@ -704,6 +723,7 @@ public class EnableConfigurationPropertiesTests {
|
|||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConfigurationProperties(locations = "${binding.location:classpath:name.yml}")
|
||||
|
@ -731,5 +751,7 @@ public class EnableConfigurationPropertiesTests {
|
|||
public Map<String, String> getMymap() {
|
||||
return this.mymap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ import org.springframework.core.env.StandardEnvironment;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringApplicationJsonEnvironmentPostProcessor}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class SpringApplicationJsonEnvironmentPostProcessorTests {
|
||||
|
|
|
@ -32,7 +32,6 @@ import static org.junit.Assert.assertNotNull;
|
|||
*/
|
||||
public class LoggingApplicationListenerIntegrationTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void loggingSystemRegisteredInTheContext() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(
|
||||
|
@ -46,7 +45,6 @@ public class LoggingApplicationListenerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Component
|
||||
static class SampleService {
|
||||
|
||||
|
@ -56,7 +54,7 @@ public class LoggingApplicationListenerIntegrationTests {
|
|||
SampleService(LoggingSystem loggingSystem) {
|
||||
this.loggingSystem = loggingSystem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue