Merge branch '1.5.x'
This commit is contained in:
commit
8b47561f7e
|
|
@ -18,10 +18,12 @@ package org.springframework.boot.actuate.autoconfigure;
|
|||
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.actuate.endpoint.MetricReaderPublicMetrics;
|
||||
import org.springframework.boot.actuate.metrics.CounterService;
|
||||
import org.springframework.boot.actuate.metrics.GaugeService;
|
||||
import org.springframework.boot.actuate.metrics.dropwizard.DropwizardMetricServices;
|
||||
import org.springframework.boot.actuate.metrics.dropwizard.ReservoirFactory;
|
||||
import org.springframework.boot.actuate.metrics.reader.MetricRegistryMetricReader;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
|
|
@ -41,6 +43,13 @@ import org.springframework.context.annotation.Configuration;
|
|||
@AutoConfigureBefore(MetricRepositoryAutoConfiguration.class)
|
||||
public class MetricsDropwizardAutoConfiguration {
|
||||
|
||||
private final ReservoirFactory reservoirFactory;
|
||||
|
||||
public MetricsDropwizardAutoConfiguration(
|
||||
ObjectProvider<ReservoirFactory> reservoirFactory) {
|
||||
this.reservoirFactory = reservoirFactory.getIfAvailable();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MetricRegistry metricRegistry() {
|
||||
|
|
@ -52,7 +61,12 @@ public class MetricsDropwizardAutoConfiguration {
|
|||
GaugeService.class })
|
||||
public DropwizardMetricServices dropwizardMetricServices(
|
||||
MetricRegistry metricRegistry) {
|
||||
return new DropwizardMetricServices(metricRegistry);
|
||||
if (this.reservoirFactory == null) {
|
||||
return new DropwizardMetricServices(metricRegistry);
|
||||
}
|
||||
else {
|
||||
return new DropwizardMetricServices(metricRegistry, this.reservoirFactory);
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.security.IgnoredRequestCustomizer;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.cloud.CloudPlatform;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
|
@ -83,10 +84,14 @@ public class CloudFoundryActuatorAutoConfiguration {
|
|||
|
||||
private CloudFoundrySecurityService getCloudFoundrySecurityService(
|
||||
RestTemplateBuilder restTemplateBuilder, Environment environment) {
|
||||
RelaxedPropertyResolver cloudFoundryProperties = new RelaxedPropertyResolver(
|
||||
environment, "management.cloudfoundry.");
|
||||
String cloudControllerUrl = environment.getProperty("vcap.application.cf_api");
|
||||
boolean skipSslValidation = cloudFoundryProperties
|
||||
.getProperty("skip-ssl-validation", Boolean.class, false);
|
||||
return cloudControllerUrl == null ? null
|
||||
: new CloudFoundrySecurityService(restTemplateBuilder,
|
||||
cloudControllerUrl);
|
||||
: new CloudFoundrySecurityService(restTemplateBuilder, cloudControllerUrl,
|
||||
skipSslValidation);
|
||||
}
|
||||
|
||||
private CorsConfiguration getCorsConfiguration() {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
|||
*/
|
||||
class CloudFoundrySecurityInterceptor extends HandlerInterceptorAdapter {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(CloudFoundrySecurityInterceptor.class);
|
||||
|
||||
private final TokenValidator tokenValidator;
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ class CloudFoundrySecurityInterceptor extends HandlerInterceptorAdapter {
|
|||
check(request, mvcEndpoint);
|
||||
}
|
||||
catch (CloudFoundryAuthorizationException ex) {
|
||||
this.logger.error(ex);
|
||||
logger.error(ex);
|
||||
response.setContentType(MediaType.APPLICATION_JSON.toString());
|
||||
response.getWriter()
|
||||
.write("{\"security_error\":\"" + ex.getMessage() + "\"}");
|
||||
|
|
|
|||
|
|
@ -46,11 +46,14 @@ class CloudFoundrySecurityService {
|
|||
private String uaaUrl;
|
||||
|
||||
CloudFoundrySecurityService(RestTemplateBuilder restTemplateBuilder,
|
||||
String cloudControllerUrl) {
|
||||
String cloudControllerUrl, boolean skipSslValidation) {
|
||||
Assert.notNull(restTemplateBuilder, "RestTemplateBuilder must not be null");
|
||||
Assert.notNull(cloudControllerUrl, "CloudControllerUrl must not be null");
|
||||
this.restTemplate = restTemplateBuilder
|
||||
.requestFactory(SkipSslVerificationHttpRequestFactory.class).build();
|
||||
if (skipSslValidation) {
|
||||
restTemplateBuilder = restTemplateBuilder
|
||||
.requestFactory(SkipSslVerificationHttpRequestFactory.class);
|
||||
}
|
||||
this.restTemplate = restTemplateBuilder.build();
|
||||
this.cloudControllerUrl = cloudControllerUrl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,11 +17,16 @@
|
|||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.cors.CorsUtils;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
|
@ -34,10 +39,15 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
|||
*/
|
||||
public class MvcEndpointSecurityInterceptor extends HandlerInterceptorAdapter {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(MvcEndpointSecurityInterceptor.class);
|
||||
|
||||
private final boolean secure;
|
||||
|
||||
private final List<String> roles;
|
||||
|
||||
private AtomicBoolean loggedUnauthorizedAttempt = new AtomicBoolean();
|
||||
|
||||
public MvcEndpointSecurityInterceptor(boolean secure, List<String> roles) {
|
||||
this.secure = secure;
|
||||
this.roles = roles;
|
||||
|
|
@ -59,17 +69,30 @@ public class MvcEndpointSecurityInterceptor extends HandlerInterceptorAdapter {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
setFailureResponseStatus(request, response);
|
||||
sendFailureResponse(request, response);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setFailureResponseStatus(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
private void sendFailureResponse(HttpServletRequest request,
|
||||
HttpServletResponse response) throws Exception {
|
||||
if (request.getUserPrincipal() != null) {
|
||||
response.setStatus(HttpStatus.FORBIDDEN.value());
|
||||
String roles = StringUtils.collectionToDelimitedString(this.roles, " ");
|
||||
response.sendError(HttpStatus.FORBIDDEN.value(),
|
||||
"Access is denied. User must have one of the these roles: " + roles);
|
||||
}
|
||||
else {
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
logUnauthorizedAttempt();
|
||||
response.sendError(HttpStatus.UNAUTHORIZED.value(),
|
||||
"Full authentication is required to access this resource.");
|
||||
}
|
||||
}
|
||||
|
||||
private void logUnauthorizedAttempt() {
|
||||
if (this.loggedUnauthorizedAttempt.compareAndSet(false, true)
|
||||
&& logger.isInfoEnabled()) {
|
||||
logger.info("Full authentication is required to access "
|
||||
+ "actuator endpoints. Consider adding Spring Security "
|
||||
+ "or set 'management.security.enabled' to false.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,15 @@ import com.codahale.metrics.Counter;
|
|||
import com.codahale.metrics.Gauge;
|
||||
import com.codahale.metrics.Histogram;
|
||||
import com.codahale.metrics.Meter;
|
||||
import com.codahale.metrics.Metric;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.codahale.metrics.Reservoir;
|
||||
import com.codahale.metrics.Timer;
|
||||
|
||||
import org.springframework.boot.actuate.metrics.CounterService;
|
||||
import org.springframework.boot.actuate.metrics.GaugeService;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link GaugeService} and {@link CounterService} that sends data to a Dropwizard
|
||||
|
|
@ -53,6 +57,8 @@ public class DropwizardMetricServices implements CounterService, GaugeService {
|
|||
|
||||
private final MetricRegistry registry;
|
||||
|
||||
private final ReservoirFactory reservoirFactory;
|
||||
|
||||
private final ConcurrentMap<String, SimpleGauge> gauges = new ConcurrentHashMap<String, SimpleGauge>();
|
||||
|
||||
private final ConcurrentHashMap<String, String> names = new ConcurrentHashMap<String, String>();
|
||||
|
|
@ -62,7 +68,20 @@ public class DropwizardMetricServices implements CounterService, GaugeService {
|
|||
* @param registry the underlying metric registry
|
||||
*/
|
||||
public DropwizardMetricServices(MetricRegistry registry) {
|
||||
this(registry, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link DropwizardMetricServices} instance.
|
||||
* @param registry the underlying metric registry
|
||||
* @param reservoirFactory the factory that instantiates the {@link Reservoir} that
|
||||
* will be used on Timers and Histograms
|
||||
*/
|
||||
public DropwizardMetricServices(MetricRegistry registry,
|
||||
ReservoirFactory reservoirFactory) {
|
||||
this.registry = registry;
|
||||
this.reservoirFactory = (reservoirFactory == null ? ReservoirFactory.NONE
|
||||
: reservoirFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -90,14 +109,10 @@ public class DropwizardMetricServices implements CounterService, GaugeService {
|
|||
@Override
|
||||
public void submit(String name, double value) {
|
||||
if (name.startsWith("histogram")) {
|
||||
long longValue = (long) value;
|
||||
Histogram metric = this.registry.histogram(name);
|
||||
metric.update(longValue);
|
||||
submitHistogram(name, value);
|
||||
}
|
||||
else if (name.startsWith("timer")) {
|
||||
long longValue = (long) value;
|
||||
Timer metric = this.registry.timer(name);
|
||||
metric.update(longValue, TimeUnit.MILLISECONDS);
|
||||
submitTimer(name, value);
|
||||
}
|
||||
else {
|
||||
name = wrapGaugeName(name);
|
||||
|
|
@ -105,6 +120,39 @@ public class DropwizardMetricServices implements CounterService, GaugeService {
|
|||
}
|
||||
}
|
||||
|
||||
private void submitTimer(String name, double value) {
|
||||
long longValue = (long) value;
|
||||
Timer metric = register(name, new TimerMetricRegistrar());
|
||||
metric.update(longValue, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private void submitHistogram(String name, double value) {
|
||||
long longValue = (long) value;
|
||||
Histogram metric = register(name, new HistogramMetricRegistrar());
|
||||
metric.update(longValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Metric> T register(String name, MetricRegistrar<T> registrar) {
|
||||
Reservoir reservoir = this.reservoirFactory.getReservoir(name);
|
||||
if (reservoir == null) {
|
||||
return registrar.register(this.registry, name);
|
||||
}
|
||||
Metric metric = this.registry.getMetrics().get(name);
|
||||
if (metric != null) {
|
||||
registrar.checkExisting(metric);
|
||||
return (T) metric;
|
||||
}
|
||||
try {
|
||||
return this.registry.register(name, registrar.createForReservoir(reservoir));
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
Metric added = this.registry.getMetrics().get(name);
|
||||
registrar.checkExisting(metric);
|
||||
return (T) added;
|
||||
}
|
||||
}
|
||||
|
||||
private void setGaugeValue(String name, double value) {
|
||||
// NOTE: Dropwizard provides no way to do this atomically
|
||||
SimpleGauge gauge = this.gauges.get(name);
|
||||
|
|
@ -170,4 +218,62 @@ public class DropwizardMetricServices implements CounterService, GaugeService {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Strategy used to register metrics.
|
||||
*/
|
||||
private static abstract class MetricRegistrar<T extends Metric> {
|
||||
|
||||
private final Class<T> type;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
MetricRegistrar() {
|
||||
this.type = (Class<T>) ResolvableType
|
||||
.forClass(MetricRegistrar.class, getClass()).resolveGeneric();
|
||||
}
|
||||
|
||||
public void checkExisting(Metric metric) {
|
||||
Assert.isInstanceOf(this.type, metric,
|
||||
"Different metric type already registered");
|
||||
}
|
||||
|
||||
protected abstract T register(MetricRegistry registry, String name);
|
||||
|
||||
protected abstract T createForReservoir(Reservoir reservoir);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MetricRegistrar} for {@link Timer} metrics.
|
||||
*/
|
||||
private static class TimerMetricRegistrar extends MetricRegistrar<Timer> {
|
||||
|
||||
@Override
|
||||
protected Timer register(MetricRegistry registry, String name) {
|
||||
return registry.timer(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Timer createForReservoir(Reservoir reservoir) {
|
||||
return new Timer(reservoir);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MetricRegistrar} for {@link Histogram} metrics.
|
||||
*/
|
||||
private static class HistogramMetricRegistrar extends MetricRegistrar<Histogram> {
|
||||
|
||||
@Override
|
||||
protected Histogram register(MetricRegistry registry, String name) {
|
||||
return registry.histogram(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Histogram createForReservoir(Reservoir reservoir) {
|
||||
return new Histogram(reservoir);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.metrics.dropwizard;
|
||||
|
||||
import com.codahale.metrics.Reservoir;
|
||||
|
||||
/**
|
||||
* Factory interface that can be used by {@link DropwizardMetricServices} to create a
|
||||
* custom {@link Reservoir}.
|
||||
*
|
||||
* @author Lucas Saldanha
|
||||
* @author Phillip Webb
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public interface ReservoirFactory {
|
||||
|
||||
/**
|
||||
* Default empty {@link ReservoirFactory} implementation.
|
||||
*/
|
||||
ReservoirFactory NONE = new ReservoirFactory() {
|
||||
|
||||
@Override
|
||||
public Reservoir getReservoir(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the {@link Reservoir} instance to use or {@code null} if a custom reservoir
|
||||
* is not needed.
|
||||
* @param name the name of the metric
|
||||
* @return a reservoir instance or {@code null}
|
||||
*/
|
||||
Reservoir getReservoir(String name);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import com.codahale.metrics.Reservoir;
|
||||
import com.codahale.metrics.UniformReservoir;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.metrics.dropwizard.DropwizardMetricServices;
|
||||
import org.springframework.boot.actuate.metrics.dropwizard.ReservoirFactory;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link MetricsDropwizardAutoConfiguration}.
|
||||
*
|
||||
* @author Lucas Saldanha
|
||||
*/
|
||||
public class MetricsDropwizardAutoConfigurationTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dropwizardWithoutCustomReservoirConfigured() {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
MetricsDropwizardAutoConfiguration.class);
|
||||
DropwizardMetricServices dropwizardMetricServices = this.context
|
||||
.getBean(DropwizardMetricServices.class);
|
||||
ReservoirFactory reservoirFactory = (ReservoirFactory) ReflectionTestUtils
|
||||
.getField(dropwizardMetricServices, "reservoirFactory");
|
||||
assertThat(reservoirFactory.getReservoir("test")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dropwizardWithCustomReservoirConfigured() {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
MetricsDropwizardAutoConfiguration.class, Config.class);
|
||||
DropwizardMetricServices dropwizardMetricServices = this.context
|
||||
.getBean(DropwizardMetricServices.class);
|
||||
ReservoirFactory reservoirFactory = (ReservoirFactory) ReflectionTestUtils
|
||||
.getField(dropwizardMetricServices, "reservoirFactory");
|
||||
assertThat(reservoirFactory.getReservoir("test"))
|
||||
.isInstanceOf(UniformReservoir.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public ReservoirFactory reservoirFactory() {
|
||||
return new UniformReservoirFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class UniformReservoirFactory implements ReservoirFactory {
|
||||
|
||||
@Override
|
||||
public Reservoir getReservoir(String name) {
|
||||
return new UniformReservoir();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ import org.springframework.mock.web.MockServletContext;
|
|||
import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
|
||||
|
|
@ -117,6 +118,22 @@ public class CloudFoundryActuatorAutoConfigurationTests {
|
|||
assertThat(cloudControllerUrl).isEqualTo("http://my-cloud-controller.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void skipSslValidation() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"management.cloudfoundry.skipSslValidation:true");
|
||||
this.context.refresh();
|
||||
CloudFoundryEndpointHandlerMapping handlerMapping = getHandlerMapping();
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
|
||||
"securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils
|
||||
.getField(interceptorSecurityService, "restTemplate");
|
||||
assertThat(restTemplate.getRequestFactory())
|
||||
.isInstanceOf(SkipSslVerificationHttpRequestFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent()
|
||||
throws Exception {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ import org.springframework.boot.test.web.client.MockServerRestTemplateCustomizer
|
|||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
|
||||
|
|
@ -63,10 +65,33 @@ public class CloudFoundrySecurityServiceTests {
|
|||
public void setup() throws Exception {
|
||||
MockServerRestTemplateCustomizer mockServerCustomizer = new MockServerRestTemplateCustomizer();
|
||||
RestTemplateBuilder builder = new RestTemplateBuilder(mockServerCustomizer);
|
||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER);
|
||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER,
|
||||
false);
|
||||
this.server = mockServerCustomizer.getServer();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void skipSslValidationWhenTrue() throws Exception {
|
||||
RestTemplateBuilder builder = new RestTemplateBuilder();
|
||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER,
|
||||
true);
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils
|
||||
.getField(this.securityService, "restTemplate");
|
||||
assertThat(restTemplate.getRequestFactory())
|
||||
.isInstanceOf(SkipSslVerificationHttpRequestFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doNotskipSslValidationWhenFalse() throws Exception {
|
||||
RestTemplateBuilder builder = new RestTemplateBuilder();
|
||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER,
|
||||
false);
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils
|
||||
.getField(this.securityService, "restTemplate");
|
||||
assertThat(restTemplate.getRequestFactory())
|
||||
.isNotInstanceOf(SkipSslVerificationHttpRequestFactory.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAccessLevelWhenSpaceDeveloperShouldReturnFull() throws Exception {
|
||||
String responseBody = "{\"read_sensitive_data\": true,\"read_basic_data\": true}";
|
||||
|
|
|
|||
|
|
@ -16,19 +16,26 @@
|
|||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.boot.test.rule.OutputCapture;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link MvcEndpointSecurityInterceptor}.
|
||||
|
|
@ -37,6 +44,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*/
|
||||
public class MvcEndpointSecurityInterceptorTests {
|
||||
|
||||
@Rule
|
||||
public OutputCapture output = new OutputCapture();
|
||||
|
||||
private MvcEndpointSecurityInterceptor securityInterceptor;
|
||||
|
||||
private TestMvcEndpoint mvcEndpoint;
|
||||
|
|
@ -47,7 +57,7 @@ public class MvcEndpointSecurityInterceptorTests {
|
|||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
private HttpServletResponse response;
|
||||
|
||||
private MockServletContext servletContext;
|
||||
|
||||
|
|
@ -62,7 +72,7 @@ public class MvcEndpointSecurityInterceptorTests {
|
|||
this.handlerMethod = new HandlerMethod(this.mvcEndpoint, "invoke");
|
||||
this.servletContext = new MockServletContext();
|
||||
this.request = new MockHttpServletRequest(this.servletContext);
|
||||
this.response = new MockHttpServletResponse();
|
||||
this.response = mock(HttpServletResponse.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -87,11 +97,30 @@ public class MvcEndpointSecurityInterceptorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void sensitiveEndpointIfRoleIsNotPresentShouldNotAllowAccess()
|
||||
public void sensitiveEndpointIfNotAuthenticatedShouldNotAllowAccess()
|
||||
throws Exception {
|
||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
||||
this.handlerMethod)).isFalse();
|
||||
verify(this.response).sendError(HttpStatus.UNAUTHORIZED.value(),
|
||||
"Full authentication is required to access this resource.");
|
||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
||||
this.handlerMethod)).isFalse();
|
||||
assertThat(this.output.toString())
|
||||
.containsOnlyOnce("Full authentication is required to access actuator "
|
||||
+ "endpoints. Consider adding Spring Security or set "
|
||||
+ "'management.security.enabled' to false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sensitiveEndpointIfRoleIsNotCorrectShouldNotAllowAccess()
|
||||
throws Exception {
|
||||
Principal principal = mock(Principal.class);
|
||||
this.request.setUserPrincipal(principal);
|
||||
this.servletContext.declareRoles("HERO");
|
||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
||||
this.handlerMethod)).isFalse();
|
||||
verify(this.response).sendError(HttpStatus.FORBIDDEN.value(),
|
||||
"Access is denied. User must have one of the these roles: SUPER_HERO");
|
||||
}
|
||||
|
||||
private static class TestEndpoint extends AbstractEndpoint<Object> {
|
||||
|
|
|
|||
|
|
@ -20,22 +20,41 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import com.codahale.metrics.Gauge;
|
||||
import com.codahale.metrics.Histogram;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.codahale.metrics.Timer;
|
||||
import com.codahale.metrics.UniformReservoir;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
|
||||
/**
|
||||
* Tests for {@link DropwizardMetricServices}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Lucas Saldanha
|
||||
*/
|
||||
public class DropwizardMetricServicesTests {
|
||||
|
||||
private final MetricRegistry registry = new MetricRegistry();
|
||||
private MetricRegistry registry = new MetricRegistry();
|
||||
|
||||
private final DropwizardMetricServices writer = new DropwizardMetricServices(
|
||||
this.registry);
|
||||
@Mock
|
||||
private ReservoirFactory reservoirFactory;
|
||||
|
||||
private DropwizardMetricServices writer;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
this.writer = new DropwizardMetricServices(this.registry, this.reservoirFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void incrementCounter() {
|
||||
|
|
@ -78,6 +97,20 @@ public class DropwizardMetricServicesTests {
|
|||
assertThat(this.registry.timer("timer.foo").getCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCustomReservoirTimer() {
|
||||
given(this.reservoirFactory.getReservoir(anyString()))
|
||||
.willReturn(new UniformReservoir());
|
||||
this.writer.submit("timer.foo", 200);
|
||||
this.writer.submit("timer.foo", 300);
|
||||
assertThat(this.registry.timer("timer.foo").getCount()).isEqualTo(2);
|
||||
Timer timer = (Timer) this.registry.getMetrics().get("timer.foo");
|
||||
Histogram histogram = (Histogram) ReflectionTestUtils.getField(timer,
|
||||
"histogram");
|
||||
assertThat(ReflectionTestUtils.getField(histogram, "reservoir").getClass()
|
||||
.equals(UniformReservoir.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPredefinedHistogram() {
|
||||
this.writer.submit("histogram.foo", 2.1);
|
||||
|
|
@ -85,6 +118,18 @@ public class DropwizardMetricServicesTests {
|
|||
assertThat(this.registry.histogram("histogram.foo").getCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCustomReservoirHistogram() {
|
||||
given(this.reservoirFactory.getReservoir(anyString()))
|
||||
.willReturn(new UniformReservoir());
|
||||
this.writer.submit("histogram.foo", 2.1);
|
||||
this.writer.submit("histogram.foo", 2.3);
|
||||
assertThat(this.registry.histogram("histogram.foo").getCount()).isEqualTo(2);
|
||||
assertThat(ReflectionTestUtils
|
||||
.getField(this.registry.getMetrics().get("histogram.foo"), "reservoir")
|
||||
.getClass().equals(UniformReservoir.class)).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the case where a given writer is used amongst several threads where each
|
||||
* thread is updating the same set of metrics. This would be an example case of the
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import org.springframework.batch.core.repository.support.JobRepositoryFactoryBea
|
|||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -40,6 +41,7 @@ import org.springframework.util.StringUtils;
|
|||
*
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
* @author Kazuki Shimizu
|
||||
*/
|
||||
public class BasicBatchConfigurer implements BatchConfigurer {
|
||||
|
||||
|
|
@ -150,6 +152,12 @@ public class BasicBatchConfigurer implements BatchConfigurer {
|
|||
}
|
||||
|
||||
protected PlatformTransactionManager createTransactionManager() {
|
||||
AbstractPlatformTransactionManager transactionManager = createAppropriateTransactionManager();
|
||||
this.properties.getTransaction().applyTo(transactionManager);
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
private AbstractPlatformTransactionManager createAppropriateTransactionManager() {
|
||||
if (this.entityManagerFactory != null) {
|
||||
return new JpaTransactionManager(this.entityManagerFactory);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -57,6 +58,7 @@ import org.springframework.util.StringUtils;
|
|||
*
|
||||
* @author Dave Syer
|
||||
* @author Eddú Meléndez
|
||||
* @author Kazuki Shimizu
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ JobLauncher.class, DataSource.class, JdbcOperations.class })
|
||||
|
|
@ -133,7 +135,8 @@ public class BatchAutoConfiguration {
|
|||
return factory;
|
||||
}
|
||||
|
||||
@ConditionalOnClass(name = "javax.persistence.EntityManagerFactory")
|
||||
@EnableConfigurationProperties(BatchProperties.class)
|
||||
@ConditionalOnClass(value = PlatformTransactionManager.class, name = "javax.persistence.EntityManagerFactory")
|
||||
@ConditionalOnMissingBean(BatchConfigurer.class)
|
||||
@Configuration
|
||||
protected static class JpaBatchConfiguration {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.batch;
|
||||
|
||||
import org.springframework.boot.autoconfigure.transaction.TransactionProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
|
||||
/**
|
||||
* Configuration properties for Spring Batch.
|
||||
|
|
@ -46,6 +48,9 @@ public class BatchProperties {
|
|||
|
||||
private final Job job = new Job();
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private final TransactionProperties transaction = new TransactionProperties();
|
||||
|
||||
public String getSchema() {
|
||||
return this.schema;
|
||||
}
|
||||
|
|
@ -54,6 +59,14 @@ public class BatchProperties {
|
|||
this.schema = schema;
|
||||
}
|
||||
|
||||
public String getTablePrefix() {
|
||||
return this.tablePrefix;
|
||||
}
|
||||
|
||||
public void setTablePrefix(String tablePrefix) {
|
||||
this.tablePrefix = tablePrefix;
|
||||
}
|
||||
|
||||
public Initializer getInitializer() {
|
||||
return this.initializer;
|
||||
}
|
||||
|
|
@ -62,12 +75,8 @@ public class BatchProperties {
|
|||
return this.job;
|
||||
}
|
||||
|
||||
public void setTablePrefix(String tablePrefix) {
|
||||
this.tablePrefix = tablePrefix;
|
||||
}
|
||||
|
||||
public String getTablePrefix() {
|
||||
return this.tablePrefix;
|
||||
public TransactionProperties getTransaction() {
|
||||
return this.transaction;
|
||||
}
|
||||
|
||||
public class Initializer {
|
||||
|
|
|
|||
|
|
@ -48,10 +48,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
|||
* @author Josh Long
|
||||
* @author Vince Bickers
|
||||
* @author Stephane Nicoll
|
||||
* @author Kazuki Shimizu
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(SessionFactory.class)
|
||||
@ConditionalOnClass({ SessionFactory.class, PlatformTransactionManager.class })
|
||||
@ConditionalOnMissingBean(SessionFactory.class)
|
||||
@EnableConfigurationProperties(Neo4jProperties.class)
|
||||
@SuppressWarnings("deprecation")
|
||||
|
|
@ -87,8 +88,12 @@ public class Neo4jDataAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory) {
|
||||
return new Neo4jTransactionManager(sessionFactory);
|
||||
public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory,
|
||||
Neo4jProperties properties) {
|
||||
Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(
|
||||
sessionFactory);
|
||||
properties.getTransaction().applyTo(transactionManager);
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
private String[] getPackagesToScan(ApplicationContext applicationContext) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ import org.neo4j.ogm.config.Configuration;
|
|||
import org.neo4j.ogm.config.DriverConfiguration;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.boot.autoconfigure.transaction.TransactionProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
|
@ -69,6 +71,9 @@ public class Neo4jProperties implements ApplicationContextAware {
|
|||
|
||||
private final Embedded embedded = new Embedded();
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private final TransactionProperties transaction = new TransactionProperties();
|
||||
|
||||
private ClassLoader classLoader = Neo4jProperties.class.getClassLoader();
|
||||
|
||||
public String getUri() {
|
||||
|
|
@ -107,6 +112,10 @@ public class Neo4jProperties implements ApplicationContextAware {
|
|||
return this.embedded;
|
||||
}
|
||||
|
||||
public TransactionProperties getTransaction() {
|
||||
return this.transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
|
||||
this.classLoader = ctx.getClassLoader();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.data.redis;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -55,6 +57,7 @@ import org.springframework.util.StringUtils;
|
|||
* @author Phillip Webb
|
||||
* @author Eddú Meléndez
|
||||
* @author Stephane Nicoll
|
||||
* @author Marco Aust
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
|
||||
|
|
@ -91,10 +94,9 @@ public class RedisAutoConfiguration {
|
|||
|
||||
protected final JedisConnectionFactory applyProperties(
|
||||
JedisConnectionFactory factory) {
|
||||
factory.setHostName(this.properties.getHost());
|
||||
factory.setPort(this.properties.getPort());
|
||||
if (this.properties.getPassword() != null) {
|
||||
factory.setPassword(this.properties.getPassword());
|
||||
configureConnection(factory);
|
||||
if (this.properties.isSsl()) {
|
||||
factory.setUseSsl(true);
|
||||
}
|
||||
factory.setDatabase(this.properties.getDatabase());
|
||||
if (this.properties.getTimeout() > 0) {
|
||||
|
|
@ -103,6 +105,43 @@ public class RedisAutoConfiguration {
|
|||
return factory;
|
||||
}
|
||||
|
||||
private void configureConnection(JedisConnectionFactory factory) {
|
||||
if (StringUtils.hasText(this.properties.getUrl())) {
|
||||
configureConnectionFromUrl(factory);
|
||||
}
|
||||
else {
|
||||
factory.setHostName(this.properties.getHost());
|
||||
factory.setPort(this.properties.getPort());
|
||||
if (this.properties.getPassword() != null) {
|
||||
factory.setPassword(this.properties.getPassword());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void configureConnectionFromUrl(JedisConnectionFactory factory) {
|
||||
String url = this.properties.getUrl();
|
||||
if (url.startsWith("rediss://")) {
|
||||
factory.setUseSsl(true);
|
||||
}
|
||||
try {
|
||||
URI uri = new URI(url);
|
||||
factory.setHostName(uri.getHost());
|
||||
factory.setPort(uri.getPort());
|
||||
if (uri.getUserInfo() != null) {
|
||||
String password = uri.getUserInfo();
|
||||
int index = password.lastIndexOf(":");
|
||||
if (index >= 0) {
|
||||
password = password.substring(index + 1);
|
||||
}
|
||||
factory.setPassword(password);
|
||||
}
|
||||
}
|
||||
catch (URISyntaxException ex) {
|
||||
throw new IllegalArgumentException("Malformed 'spring.redis.url' " + url,
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected final RedisSentinelConfiguration getSentinelConfig() {
|
||||
if (this.sentinelConfiguration != null) {
|
||||
return this.sentinelConfiguration;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||
* @author Dave Syer
|
||||
* @author Christoph Strobl
|
||||
* @author Eddú Meléndez
|
||||
* @author Marco Aust
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "spring.redis")
|
||||
public class RedisProperties {
|
||||
|
|
@ -35,6 +36,11 @@ public class RedisProperties {
|
|||
*/
|
||||
private int database = 0;
|
||||
|
||||
/**
|
||||
* Redis url, which will overrule host, port and password if set.
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* Redis server host.
|
||||
*/
|
||||
|
|
@ -50,6 +56,11 @@ public class RedisProperties {
|
|||
*/
|
||||
private int port = 6379;
|
||||
|
||||
/**
|
||||
* Enable SSL.
|
||||
*/
|
||||
private boolean ssl;
|
||||
|
||||
/**
|
||||
* Connection timeout in milliseconds.
|
||||
*/
|
||||
|
|
@ -69,6 +80,14 @@ public class RedisProperties {
|
|||
this.database = database;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return this.host;
|
||||
}
|
||||
|
|
@ -93,6 +112,14 @@ public class RedisProperties {
|
|||
this.port = port;
|
||||
}
|
||||
|
||||
public boolean isSsl() {
|
||||
return this.ssl;
|
||||
}
|
||||
|
||||
public void setSsl(boolean ssl) {
|
||||
this.ssl = ssl;
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ import javax.sql.DataSource;
|
|||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.autoconfigure.transaction.TransactionProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
|
@ -157,6 +159,9 @@ public class DataSourceProperties
|
|||
|
||||
private String uniqueName;
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private final TransactionProperties transaction = new TransactionProperties();
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
|
|
@ -473,6 +478,10 @@ public class DataSourceProperties
|
|||
this.xa = xa;
|
||||
}
|
||||
|
||||
public TransactionProperties getTransaction() {
|
||||
return this.transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* XA Specific datasource settings.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
|
|
@ -39,10 +40,12 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
* @author Andy Wilkinson
|
||||
* @author Kazuki Shimizu
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class })
|
||||
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
|
||||
@EnableConfigurationProperties(DataSourceProperties.class)
|
||||
public class DataSourceTransactionManagerAutoConfiguration {
|
||||
|
||||
@Configuration
|
||||
|
|
@ -57,8 +60,12 @@ public class DataSourceTransactionManagerAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
public DataSourceTransactionManager transactionManager() {
|
||||
return new DataSourceTransactionManager(this.dataSource);
|
||||
public DataSourceTransactionManager transactionManager(
|
||||
DataSourceProperties properties) {
|
||||
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(
|
||||
this.dataSource);
|
||||
properties.getTransaction().applyTo(transactionManager);
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import org.apache.kafka.common.serialization.StringSerializer;
|
|||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.kafka.listener.AbstractMessageListenerContainer.AckMode;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Configuration properties for Spring for Apache Kafka.
|
||||
|
|
@ -47,18 +48,6 @@ import org.springframework.kafka.listener.AbstractMessageListenerContainer.AckMo
|
|||
@ConfigurationProperties(prefix = "spring.kafka")
|
||||
public class KafkaProperties {
|
||||
|
||||
private final Consumer consumer = new Consumer();
|
||||
|
||||
private final Producer producer = new Producer();
|
||||
|
||||
private final Listener listener = new Listener();
|
||||
|
||||
private final Template template = new Template();
|
||||
|
||||
private final Ssl ssl = new Ssl();
|
||||
|
||||
// Apache Kafka Common Properties
|
||||
|
||||
/**
|
||||
* Comma-delimited list of host:port pairs to use for establishing the initial
|
||||
* connection to the Kafka cluster.
|
||||
|
|
@ -71,6 +60,45 @@ public class KafkaProperties {
|
|||
*/
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* Additional properties used to configure the client.
|
||||
*/
|
||||
private Map<String, String> properties = new HashMap<String, String>();
|
||||
|
||||
private final Consumer consumer = new Consumer();
|
||||
|
||||
private final Producer producer = new Producer();
|
||||
|
||||
private final Listener listener = new Listener();
|
||||
|
||||
private final Ssl ssl = new Ssl();
|
||||
|
||||
private final Template template = new Template();
|
||||
|
||||
public List<String> getBootstrapServers() {
|
||||
return this.bootstrapServers;
|
||||
}
|
||||
|
||||
public void setBootstrapServers(List<String> bootstrapServers) {
|
||||
this.bootstrapServers = bootstrapServers;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return this.clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
public void setProperties(Map<String, String> properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public Consumer getConsumer() {
|
||||
return this.consumer;
|
||||
}
|
||||
|
|
@ -91,22 +119,6 @@ public class KafkaProperties {
|
|||
return this.template;
|
||||
}
|
||||
|
||||
public List<String> getBootstrapServers() {
|
||||
return this.bootstrapServers;
|
||||
}
|
||||
|
||||
public void setBootstrapServers(List<String> bootstrapServers) {
|
||||
this.bootstrapServers = bootstrapServers;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return this.clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
private Map<String, Object> buildCommonProperties() {
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
if (this.bootstrapServers != null) {
|
||||
|
|
@ -135,6 +147,9 @@ public class KafkaProperties {
|
|||
properties.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG,
|
||||
this.ssl.getTruststorePassword());
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(this.properties)) {
|
||||
properties.putAll(this.properties);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
|
@ -147,9 +162,9 @@ public class KafkaProperties {
|
|||
* instance
|
||||
*/
|
||||
public Map<String, Object> buildConsumerProperties() {
|
||||
Map<String, Object> props = buildCommonProperties();
|
||||
props.putAll(this.consumer.buildProperties());
|
||||
return props;
|
||||
Map<String, Object> properties = buildCommonProperties();
|
||||
properties.putAll(this.consumer.buildProperties());
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,9 +176,9 @@ public class KafkaProperties {
|
|||
* instance
|
||||
*/
|
||||
public Map<String, Object> buildProducerProperties() {
|
||||
Map<String, Object> props = buildCommonProperties();
|
||||
props.putAll(this.producer.buildProperties());
|
||||
return props;
|
||||
Map<String, Object> properties = buildCommonProperties();
|
||||
properties.putAll(this.producer.buildProperties());
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static String resourceToPath(Resource resource) {
|
||||
|
|
@ -240,6 +255,11 @@ public class KafkaProperties {
|
|||
*/
|
||||
private Class<?> valueDeserializer = StringDeserializer.class;
|
||||
|
||||
/**
|
||||
* Maximum number of records returned in a single call to poll().
|
||||
*/
|
||||
private Integer maxPollRecords;
|
||||
|
||||
public Ssl getSsl() {
|
||||
return this.ssl;
|
||||
}
|
||||
|
|
@ -332,6 +352,14 @@ public class KafkaProperties {
|
|||
this.valueDeserializer = valueDeserializer;
|
||||
}
|
||||
|
||||
public Integer getMaxPollRecords() {
|
||||
return this.maxPollRecords;
|
||||
}
|
||||
|
||||
public void setMaxPollRecords(Integer maxPollRecords) {
|
||||
this.maxPollRecords = maxPollRecords;
|
||||
}
|
||||
|
||||
public Map<String, Object> buildProperties() {
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
if (this.autoCommitInterval != null) {
|
||||
|
|
@ -395,6 +423,10 @@ public class KafkaProperties {
|
|||
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
|
||||
this.valueDeserializer);
|
||||
}
|
||||
if (this.maxPollRecords != null) {
|
||||
properties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG,
|
||||
this.maxPollRecords);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
|||
* @author Dave Syer
|
||||
* @author Oliver Gierke
|
||||
* @author Andy Wilkinson
|
||||
* @author Kazuki Shimizu
|
||||
*/
|
||||
@EnableConfigurationProperties(JpaProperties.class)
|
||||
@Import(DataSourceInitializedPublisher.Registrar.class)
|
||||
|
|
@ -82,7 +83,9 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware {
|
|||
@Bean
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return new JpaTransactionManager();
|
||||
JpaTransactionManager transactionManager = new JpaTransactionManager();
|
||||
this.properties.getTransaction().applyTo(transactionManager);
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import java.util.Map;
|
|||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection;
|
||||
import org.springframework.boot.autoconfigure.transaction.TransactionProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
|
|
@ -67,6 +68,9 @@ public class JpaProperties {
|
|||
|
||||
private Hibernate hibernate = new Hibernate();
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private final TransactionProperties transaction = new TransactionProperties();
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
|
@ -125,6 +129,10 @@ public class JpaProperties {
|
|||
return this.hibernate.getAdditionalProperties(this.properties, dataSource);
|
||||
}
|
||||
|
||||
public TransactionProperties getTransaction() {
|
||||
return this.transaction;
|
||||
}
|
||||
|
||||
public static class Hibernate {
|
||||
|
||||
private static final String USE_NEW_ID_GENERATOR_MAPPINGS = "hibernate.id."
|
||||
|
|
|
|||
|
|
@ -16,12 +16,6 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.security.oauth2.client;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
|
@ -76,7 +70,7 @@ import org.springframework.util.StringUtils;
|
|||
public class OAuth2RestOperationsConfiguration {
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClientCredentials
|
||||
@Conditional(ClientCredentialsCondition.class)
|
||||
protected static class SingletonScopedConfiguration {
|
||||
|
||||
@Bean
|
||||
|
|
@ -96,7 +90,7 @@ public class OAuth2RestOperationsConfiguration {
|
|||
|
||||
@Configuration
|
||||
@ConditionalOnBean(OAuth2ClientConfiguration.class)
|
||||
@ConditionalOnNotClientCredentials
|
||||
@Conditional(NoClientCredentialsCondition.class)
|
||||
@Import(OAuth2ProtectedResourceDetailsConfiguration.class)
|
||||
protected static class SessionScopedConfiguration {
|
||||
|
||||
|
|
@ -126,15 +120,13 @@ public class OAuth2RestOperationsConfiguration {
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* When the authentication is per cookie but the stored token is an oauth2 one, we can
|
||||
* pass that on to a client that wants to call downstream. We don't even need an
|
||||
* OAuth2ClientContextFilter until we need to refresh the access token. To handle
|
||||
* refresh tokens you need to {@code @EnableOAuth2Client}
|
||||
*/
|
||||
// When the authentication is per cookie but the stored token is an oauth2 one, we can
|
||||
// pass that on to a client that wants to call downstream. We don't even need an
|
||||
// OAuth2ClientContextFilter until we need to refresh the access token. To handle
|
||||
// refresh tokens you need to @EnableOAuth2Client
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(OAuth2ClientConfiguration.class)
|
||||
@ConditionalOnNotClientCredentials
|
||||
@Conditional(NoClientCredentialsCondition.class)
|
||||
@Import(OAuth2ProtectedResourceDetailsConfiguration.class)
|
||||
protected static class RequestScopedConfiguration {
|
||||
|
||||
|
|
@ -182,22 +174,24 @@ public class OAuth2RestOperationsConfiguration {
|
|||
|
||||
}
|
||||
|
||||
@Conditional(ClientCredentialsCondition.class)
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public static @interface ConditionalOnClientCredentials {
|
||||
|
||||
}
|
||||
|
||||
@Conditional(NotClientCredentialsCondition.class)
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public static @interface ConditionalOnNotClientCredentials {
|
||||
/**
|
||||
* Condition to check for no client credentials.
|
||||
*/
|
||||
static class NoClientCredentialsCondition extends NoneNestedConditions {
|
||||
|
||||
NoClientCredentialsCondition() {
|
||||
super(ConfigurationPhase.PARSE_CONFIGURATION);
|
||||
}
|
||||
|
||||
@Conditional(ClientCredentialsCondition.class)
|
||||
static class ClientCredentialsActivated {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Condition to check for client credentials.
|
||||
*/
|
||||
static class ClientCredentialsCondition extends AnyNestedCondition {
|
||||
|
||||
ClientCredentialsCondition() {
|
||||
|
|
@ -211,17 +205,6 @@ public class OAuth2RestOperationsConfiguration {
|
|||
@ConditionalOnNotWebApplication
|
||||
static class NoWebApplication {
|
||||
}
|
||||
}
|
||||
|
||||
static class NotClientCredentialsCondition extends NoneNestedConditions {
|
||||
|
||||
NotClientCredentialsCondition() {
|
||||
super(ConfigurationPhase.PARSE_CONFIGURATION);
|
||||
}
|
||||
|
||||
@ConditionalOnClientCredentials
|
||||
static class ClientCredentialsActivated {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@ package org.springframework.boot.autoconfigure.security.oauth2.resource;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
|
@ -43,8 +40,6 @@ import org.springframework.social.oauth2.AccessGrant;
|
|||
*/
|
||||
public class SpringSocialTokenServices implements ResourceServerTokenServices {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final OAuth2ConnectionFactory<?> connectionFactory;
|
||||
|
||||
private final String clientId;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.transaction;
|
||||
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* Nested configuration properties that can be applied to an
|
||||
* {@link AbstractPlatformTransactionManager}.
|
||||
*
|
||||
* @author Kazuki Shimizu
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class TransactionProperties {
|
||||
|
||||
/**
|
||||
* Default transaction timeout in seconds.
|
||||
*/
|
||||
private Integer defaultTimeout;
|
||||
|
||||
/**
|
||||
* Perform the rollback on commit failurures.
|
||||
*/
|
||||
private Boolean rollbackOnCommitFailure;
|
||||
|
||||
public Integer getDefaultTimeout() {
|
||||
return this.defaultTimeout;
|
||||
}
|
||||
|
||||
public void setDefaultTimeout(Integer defaultTimeout) {
|
||||
this.defaultTimeout = defaultTimeout;
|
||||
}
|
||||
|
||||
public Boolean getRollbackOnCommitFailure() {
|
||||
return this.rollbackOnCommitFailure;
|
||||
}
|
||||
|
||||
public void setRollbackOnCommitFailure(Boolean rollbackOnCommitFailure) {
|
||||
this.rollbackOnCommitFailure = rollbackOnCommitFailure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply all transaction custom properties to the specified transaction manager.
|
||||
* @param transactionManager the target transaction manager
|
||||
*/
|
||||
public void applyTo(AbstractPlatformTransactionManager transactionManager) {
|
||||
if (this.defaultTimeout != null) {
|
||||
transactionManager.setDefaultTimeout(this.defaultTimeout);
|
||||
}
|
||||
if (this.rollbackOnCommitFailure != null) {
|
||||
transactionManager.setRollbackOnCommitFailure(this.rollbackOnCommitFailure);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -50,10 +50,11 @@ import org.springframework.util.StringUtils;
|
|||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Stephane Nicoll
|
||||
* @author Kazuki Shimizu
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AtomikosProperties.class)
|
||||
@EnableConfigurationProperties({ AtomikosProperties.class, JtaProperties.class })
|
||||
@ConditionalOnClass({ JtaTransactionManager.class, UserTransactionManager.class })
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
class AtomikosJtaConfiguration {
|
||||
|
|
@ -111,7 +112,10 @@ class AtomikosJtaConfiguration {
|
|||
@Bean
|
||||
public JtaTransactionManager transactionManager(UserTransaction userTransaction,
|
||||
TransactionManager transactionManager) {
|
||||
return new JtaTransactionManager(userTransaction, transactionManager);
|
||||
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(
|
||||
userTransaction, transactionManager);
|
||||
this.jtaProperties.getTransaction().applyTo(jtaTransactionManager);
|
||||
return jtaTransactionManager;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import org.springframework.boot.ApplicationHome;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.jta.XAConnectionFactoryWrapper;
|
||||
import org.springframework.boot.jta.XADataSourceWrapper;
|
||||
import org.springframework.boot.jta.bitronix.BitronixDependentBeanFactoryPostProcessor;
|
||||
|
|
@ -46,9 +47,11 @@ import org.springframework.util.StringUtils;
|
|||
* @author Josh Long
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Kazuki Shimizu
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(JtaProperties.class)
|
||||
@ConditionalOnClass({ JtaTransactionManager.class, BitronixContext.class })
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
class BitronixJtaConfiguration {
|
||||
|
|
@ -105,7 +108,10 @@ class BitronixJtaConfiguration {
|
|||
@Bean
|
||||
public JtaTransactionManager transactionManager(
|
||||
TransactionManager transactionManager) {
|
||||
return new JtaTransactionManager(transactionManager);
|
||||
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(
|
||||
transactionManager);
|
||||
this.jtaProperties.getTransaction().applyTo(jtaTransactionManager);
|
||||
return jtaTransactionManager;
|
||||
}
|
||||
|
||||
@ConditionalOnClass(Message.class)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import org.springframework.transaction.jta.JtaTransactionManager;
|
|||
*
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
* @author Kazuki Shimizu
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Configuration
|
||||
|
|
@ -40,9 +41,18 @@ import org.springframework.transaction.jta.JtaTransactionManager;
|
|||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
class JndiJtaConfiguration {
|
||||
|
||||
private final JtaProperties jtaProperties;
|
||||
|
||||
JndiJtaConfiguration(JtaProperties jtaProperties) {
|
||||
this.jtaProperties = jtaProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JtaTransactionManager transactionManager() {
|
||||
return new JtaTransactionManagerFactoryBean().getObject();
|
||||
JtaTransactionManager transactionManager = new JtaTransactionManagerFactoryBean()
|
||||
.getObject();
|
||||
this.jtaProperties.getTransaction().applyTo(transactionManager);
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.transaction.jta;
|
||||
|
||||
import org.springframework.boot.autoconfigure.transaction.TransactionProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
|
||||
/**
|
||||
|
|
@ -42,6 +44,9 @@ public class JtaProperties {
|
|||
*/
|
||||
private String transactionManagerId;
|
||||
|
||||
@NestedConfigurationProperty
|
||||
private final TransactionProperties transaction = new TransactionProperties();
|
||||
|
||||
public void setLogDir(String logDir) {
|
||||
this.logDir = logDir;
|
||||
}
|
||||
|
|
@ -58,4 +63,8 @@ public class JtaProperties {
|
|||
this.transactionManagerId = transactionManagerId;
|
||||
}
|
||||
|
||||
public TransactionProperties getTransaction() {
|
||||
return this.transaction;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import org.jboss.tm.XAResourceRecoveryRegistry;
|
|||
import org.springframework.boot.ApplicationHome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.jta.XAConnectionFactoryWrapper;
|
||||
import org.springframework.boot.jta.XADataSourceWrapper;
|
||||
import org.springframework.boot.jta.narayana.NarayanaBeanFactoryPostProcessor;
|
||||
|
|
@ -47,12 +48,14 @@ import org.springframework.util.StringUtils;
|
|||
* JTA Configuration for <a href="http://narayana.io/">Narayana</a>.
|
||||
*
|
||||
* @author Gytis Trikleris
|
||||
* @author Kazuki Shimizu
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ JtaTransactionManager.class,
|
||||
com.arjuna.ats.jta.UserTransaction.class, XAResourceRecoveryRegistry.class })
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
@EnableConfigurationProperties(JtaProperties.class)
|
||||
public class NarayanaJtaConfiguration {
|
||||
|
||||
private final JtaProperties jtaProperties;
|
||||
|
|
@ -116,7 +119,10 @@ public class NarayanaJtaConfiguration {
|
|||
@Bean
|
||||
public JtaTransactionManager transactionManager(UserTransaction userTransaction,
|
||||
TransactionManager transactionManager) {
|
||||
return new JtaTransactionManager(userTransaction, transactionManager);
|
||||
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(
|
||||
userTransaction, transactionManager);
|
||||
this.jtaProperties.getTransaction().applyTo(jtaTransactionManager);
|
||||
return jtaTransactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.BadSqlGrammarException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
|
@ -68,6 +70,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
* @author Kazuki Shimizu
|
||||
*/
|
||||
public class BatchAutoConfigurationTests {
|
||||
|
||||
|
|
@ -267,6 +270,43 @@ public class BatchAutoConfigurationTests {
|
|||
.queryForList("select * from BATCH_JOB_EXECUTION");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomizeJpaTransactionManagerUsingProperties() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.batch.transaction.default-timeout:30",
|
||||
"spring.batch.transaction.rollback-on-commit-failure:true");
|
||||
this.context.register(TestConfiguration.class,
|
||||
EmbeddedDataSourceConfiguration.class,
|
||||
HibernateJpaAutoConfiguration.class, BatchAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
this.context.getBean(BatchConfigurer.class);
|
||||
JpaTransactionManager transactionManager = JpaTransactionManager.class.cast(
|
||||
this.context.getBean(BatchConfigurer.class).getTransactionManager());
|
||||
assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30);
|
||||
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomizeDataSourceTransactionManagerUsingProperties()
|
||||
throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.batch.transaction.default-timeout:30",
|
||||
"spring.batch.transaction.rollback-on-commit-failure:true");
|
||||
this.context.register(TestConfiguration.class,
|
||||
EmbeddedDataSourceConfiguration.class, BatchAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
this.context.getBean(BatchConfigurer.class);
|
||||
DataSourceTransactionManager transactionManager = DataSourceTransactionManager.class
|
||||
.cast(this.context.getBean(BatchConfigurer.class)
|
||||
.getTransactionManager());
|
||||
assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30);
|
||||
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class EmptyConfiguration {
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
|
||||
import org.springframework.data.neo4j.web.support.OpenSessionInViewInterceptor;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
|
|
@ -53,6 +54,7 @@ import static org.mockito.Mockito.verify;
|
|||
* @author Michael Hunger
|
||||
* @author Vince Bickers
|
||||
* @author Andy Wilkinson
|
||||
* @author Kazuki Shimizu
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class Neo4jDataAutoConfigurationTests {
|
||||
|
|
@ -73,10 +75,21 @@ public class Neo4jDataAutoConfigurationTests {
|
|||
.hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(SessionFactory.class)).hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(Neo4jOperations.class)).hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(Neo4jTransactionManager.class)).hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(OpenSessionInViewInterceptor.class))
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customNeo4jTransactionManagerUsingProperties() {
|
||||
load(null, "spring.data.neo4j.transaction.default-timeout=30",
|
||||
"spring.data.neo4j.transaction.rollback-on-commit-failure:true");
|
||||
Neo4jTransactionManager transactionManager = this.context
|
||||
.getBean(Neo4jTransactionManager.class);
|
||||
assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30);
|
||||
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customSessionFactory() {
|
||||
load(CustomSessionFactory.class);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
* @author Christian Dupuis
|
||||
* @author Christoph Strobl
|
||||
* @author Eddú Meléndez
|
||||
* @author Marco Aust
|
||||
*/
|
||||
public class RedisAutoConfigurationTests {
|
||||
|
||||
|
|
@ -75,6 +76,21 @@ public class RedisAutoConfigurationTests {
|
|||
.isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverrideUrlRedisConfiguration() throws Exception {
|
||||
load("spring.redis.host:foo", "spring.redis.password:xyz",
|
||||
"spring.redis.port:1000", "spring.redis.ssl:true",
|
||||
"spring.redis.url:redis://user:password@example:33");
|
||||
assertThat(this.context.getBean(JedisConnectionFactory.class).getHostName())
|
||||
.isEqualTo("example");
|
||||
assertThat(this.context.getBean(JedisConnectionFactory.class).getPort())
|
||||
.isEqualTo(33);
|
||||
assertThat(this.context.getBean(JedisConnectionFactory.class).getPassword())
|
||||
.isEqualTo("password");
|
||||
assertThat(this.context.getBean(JedisConnectionFactory.class).isUseSsl())
|
||||
.isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRedisConfigurationWithPool() throws Exception {
|
||||
load("spring.redis.host:foo", "spring.redis.pool.max-idle:1");
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import javax.sql.DataSource;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
|
@ -106,6 +107,21 @@ public class DataSourceTransactionManagerAutoConfigurationTests {
|
|||
.isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomizeDataSourceTransactionManagerUsingProperties()
|
||||
throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.datasource.transaction.default-timeout:30",
|
||||
"spring.datasource.transaction.rollback-on-commit-failure:true");
|
||||
this.context.register(EmbeddedDataSourceConfiguration.class,
|
||||
DataSourceTransactionManagerAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
DataSourceTransactionManager transactionManager = this.context
|
||||
.getBean(DataSourceTransactionManager.class);
|
||||
assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30);
|
||||
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
|
||||
}
|
||||
|
||||
@EnableTransactionManagement
|
||||
protected static class SwitchTransactionsOn {
|
||||
|
||||
|
|
|
|||
|
|
@ -60,13 +60,16 @@ public class KafkaAutoConfigurationTests {
|
|||
|
||||
@Test
|
||||
public void consumerProperties() {
|
||||
load("spring.kafka.bootstrap-servers=foo:1234",
|
||||
load("spring.kafka.bootstrap-servers=foo:1234", "spring.kafka.properties.foo=bar",
|
||||
"spring.kafka.properties.baz=qux",
|
||||
"spring.kafka.properties.foo.bar.baz=qux.fiz.buz",
|
||||
"spring.kafka.ssl.key-password=p1",
|
||||
"spring.kafka.ssl.keystore-location=classpath:ksLoc",
|
||||
"spring.kafka.ssl.keystore-password=p2",
|
||||
"spring.kafka.ssl.truststore-location=classpath:tsLoc",
|
||||
"spring.kafka.ssl.truststore-password=p3",
|
||||
"spring.kafka.consumer.auto-commit-interval=123",
|
||||
"spring.kafka.consumer.max-poll-records=42",
|
||||
"spring.kafka.consumer.auto-offset-reset=earliest",
|
||||
"spring.kafka.consumer.client-id=ccid", // test override common
|
||||
"spring.kafka.consumer.enable-auto-commit=false",
|
||||
|
|
@ -109,6 +112,10 @@ public class KafkaAutoConfigurationTests {
|
|||
.isEqualTo(LongDeserializer.class);
|
||||
assertThat(configs.get(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG))
|
||||
.isEqualTo(IntegerDeserializer.class);
|
||||
assertThat(configs.get(ConsumerConfig.MAX_POLL_RECORDS_CONFIG)).isEqualTo(42);
|
||||
assertThat(configs.get("foo")).isEqualTo("bar");
|
||||
assertThat(configs.get("baz")).isEqualTo("qux");
|
||||
assertThat(configs.get("foo.bar.baz")).isEqualTo("qux.fiz.buz");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -81,20 +81,24 @@ public class AutoConfigurationReportLoggingInitializerTests {
|
|||
|
||||
given(this.log.isDebugEnabled()).willReturn(debug);
|
||||
willAnswer(new Answer<Object>() {
|
||||
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return AutoConfigurationReportLoggingInitializerTests.this.debugLog
|
||||
.add(String.valueOf(invocation.getArguments()[0]));
|
||||
}
|
||||
|
||||
}).given(this.log).debug(anyObject());
|
||||
|
||||
given(this.log.isInfoEnabled()).willReturn(info);
|
||||
willAnswer(new Answer<Object>() {
|
||||
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return AutoConfigurationReportLoggingInitializerTests.this.infoLog
|
||||
.add(String.valueOf(invocation.getArguments()[0]));
|
||||
}
|
||||
|
||||
}).given(this.log).info(anyObject());
|
||||
|
||||
LogFactory.releaseAll();
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfigurati
|
|||
import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
|
@ -48,6 +49,7 @@ import static org.mockito.Mockito.mock;
|
|||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Kazuki Shimizu
|
||||
*/
|
||||
public class HibernateJpaAutoConfigurationTests
|
||||
extends AbstractJpaAutoConfigurationTests {
|
||||
|
|
@ -134,6 +136,19 @@ public class HibernateJpaAutoConfigurationTests
|
|||
.isEqualTo(TestJtaPlatform.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomJpaTransactionManagerUsingProperties() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.jpa.transaction.default-timeout:30",
|
||||
"spring.jpa.transaction.rollback-on-commit-failure:true");
|
||||
setupTestConfiguration();
|
||||
this.context.refresh();
|
||||
JpaTransactionManager transactionManager = this.context
|
||||
.getBean(JpaTransactionManager.class);
|
||||
assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30);
|
||||
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
|
||||
}
|
||||
|
||||
public static class TestJtaPlatform implements JtaPlatform {
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
|
|
@ -196,8 +195,8 @@ public class OAuth2AutoConfigurationTests {
|
|||
"security.oauth2.client.clientId=client",
|
||||
"security.oauth2.client.grantType=client_credentials");
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean(OAuth2ClientContext.class).getAccessTokenRequest())
|
||||
.isNotNull();
|
||||
OAuth2ClientContext bean = this.context.getBean(OAuth2ClientContext.class);
|
||||
assertThat(bean.getAccessTokenRequest()).isNotNull();
|
||||
assertThat(countBeans(ClientCredentialsResourceDetails.class)).isEqualTo(1);
|
||||
assertThat(countBeans(OAuth2ClientContext.class)).isEqualTo(1);
|
||||
}
|
||||
|
|
@ -211,17 +210,15 @@ public class OAuth2AutoConfigurationTests {
|
|||
"security.oauth2.client.clientId=client",
|
||||
"security.oauth2.client.grantType=client_credentials");
|
||||
this.context.refresh();
|
||||
// Thr primary context is fine (not session scoped):
|
||||
assertThat(this.context.getBean(OAuth2ClientContext.class).getAccessTokenRequest())
|
||||
.isNotNull();
|
||||
// The primary context is fine (not session scoped):
|
||||
OAuth2ClientContext bean = this.context.getBean(OAuth2ClientContext.class);
|
||||
assertThat(bean.getAccessTokenRequest()).isNotNull();
|
||||
assertThat(countBeans(ClientCredentialsResourceDetails.class)).isEqualTo(1);
|
||||
/*
|
||||
* Kind of a bug (should ideally be 1), but the cause is in Spring OAuth2 (there
|
||||
* is no need for the extra session-scoped bean). What this test proves is that
|
||||
* even if the user screws up and does @EnableOAuth2Client for client credentials,
|
||||
* it will still just about work (because of the @Primary annotation on the
|
||||
* Boot-created instance of OAuth2ClientContext).
|
||||
*/
|
||||
// Kind of a bug (should ideally be 1), but the cause is in Spring OAuth2 (there
|
||||
// is no need for the extra session-scoped bean). What this test proves is that
|
||||
// even if the user screws up and does @EnableOAuth2Client for client credentials,
|
||||
// it will still just about work (because of the @Primary annotation on the
|
||||
// Boot-created instance of OAuth2ClientContext).
|
||||
assertThat(countBeans(OAuth2ClientContext.class)).isEqualTo(2);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ import static org.mockito.Mockito.mock;
|
|||
* @author Josh Long
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Kazuki Shimizu
|
||||
*/
|
||||
public class JtaAutoConfigurationTests {
|
||||
|
||||
|
|
@ -245,6 +246,34 @@ public class JtaAutoConfigurationTests {
|
|||
assertThat(dataSource.getMaxPoolSize()).isEqualTo(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void atomikosCustomizeJtaTransactionManagerUsingProperties() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.jta.transaction.default-timeout:30",
|
||||
"spring.jta.transaction.rollback-on-commit-failure:true");
|
||||
this.context.register(AtomikosJtaConfiguration.class);
|
||||
this.context.refresh();
|
||||
JtaTransactionManager transactionManager = this.context
|
||||
.getBean(JtaTransactionManager.class);
|
||||
assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30);
|
||||
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bitronixCustomizeJtaTransactionManagerUsingProperties() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.jta.transaction.default-timeout:30",
|
||||
"spring.jta.transaction.rollback-on-commit-failure:true");
|
||||
this.context.register(BitronixJtaConfiguration.class);
|
||||
this.context.refresh();
|
||||
JtaTransactionManager transactionManager = this.context
|
||||
.getBean(JtaTransactionManager.class);
|
||||
assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30);
|
||||
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(JtaProperties.class)
|
||||
public static class JtaPropertiesConfiguration {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ import java.util.jar.Attributes;
|
|||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.boot.devtools.settings.DevToolsSettings;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -41,6 +44,8 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
final class ChangeableUrls implements Iterable<URL> {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ChangeableUrls.class);
|
||||
|
||||
private final List<URL> urls;
|
||||
|
||||
private ChangeableUrls(URL... urls) {
|
||||
|
|
@ -52,6 +57,9 @@ final class ChangeableUrls implements Iterable<URL> {
|
|||
reloadableUrls.add(url);
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Matching URLs for reloading : " + reloadableUrls);
|
||||
}
|
||||
this.urls = Collections.unmodifiableList(reloadableUrls);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
|
||||
|
|
@ -40,6 +43,8 @@ public class DevToolsSettings {
|
|||
*/
|
||||
public static final String SETTINGS_RESOURCE_LOCATION = "META-INF/spring-devtools.properties";
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DevToolsSettings.class);
|
||||
|
||||
private static DevToolsSettings settings;
|
||||
|
||||
private final List<Pattern> restartIncludePatterns = new ArrayList<Pattern>();
|
||||
|
|
@ -105,6 +110,12 @@ public class DevToolsSettings {
|
|||
settings.add(PropertiesLoaderUtils
|
||||
.loadProperties(new UrlResource(urls.nextElement())));
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Included patterns for restart : "
|
||||
+ settings.restartIncludePatterns);
|
||||
logger.debug("Excluded patterns for restart : "
|
||||
+ settings.restartExcludePatterns);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
|
|
|||
|
|
@ -581,6 +581,7 @@ content into your application; rather pick only the properties that you need.
|
|||
spring.data.neo4j.open-in-view=false # Register OpenSessionInViewInterceptor. Binds a Neo4j Session to the thread for the entire processing of the request.
|
||||
spring.data.neo4j.password= # Login password of the server.
|
||||
spring.data.neo4j.repositories.enabled=true # Enable Neo4j repositories.
|
||||
spring.data.neo4j.transaction.*= # Transaction manager settings
|
||||
spring.data.neo4j.uri= # URI used by the driver. Auto-detected by default.
|
||||
spring.data.neo4j.username= # Login user of the server.
|
||||
|
||||
|
|
@ -622,6 +623,7 @@ content into your application; rather pick only the properties that you need.
|
|||
spring.datasource.separator=; # Statement separator in SQL initialization scripts.
|
||||
spring.datasource.sql-script-encoding= # SQL scripts encoding.
|
||||
spring.datasource.tomcat.*= # Tomcat datasource specific settings
|
||||
spring.datasource.transaction.*= # Transaction manager settings
|
||||
spring.datasource.type= # Fully qualified name of the connection pool implementation to use. By default, it is auto-detected from the classpath.
|
||||
spring.datasource.url= # JDBC url of the database.
|
||||
spring.datasource.username=
|
||||
|
|
@ -656,10 +658,12 @@ content into your application; rather pick only the properties that you need.
|
|||
spring.jpa.open-in-view=true # Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request.
|
||||
spring.jpa.properties.*= # Additional native properties to set on the JPA provider.
|
||||
spring.jpa.show-sql=false # Enable logging of SQL statements.
|
||||
spring.jpa.transaction.*= # Transaction manager settings
|
||||
|
||||
# JTA ({sc-spring-boot-autoconfigure}/transaction/jta/JtaAutoConfiguration.{sc-ext}[JtaAutoConfiguration])
|
||||
spring.jta.enabled=true # Enable JTA support.
|
||||
spring.jta.log-dir= # Transaction logs directory.
|
||||
spring.jta.transaction.*= # Transaction manager settings
|
||||
spring.jta.transaction-manager-id= # Transaction manager unique identifier.
|
||||
|
||||
# ATOMIKOS ({sc-spring-boot}/jta/atomikos/AtomikosProperties.{sc-ext}[AtomikosProperties])
|
||||
|
|
@ -793,8 +797,10 @@ content into your application; rather pick only the properties that you need.
|
|||
spring.redis.cluster.max-redirects= # Maximum number of redirects to follow when executing commands across the cluster.
|
||||
spring.redis.cluster.nodes= # Comma-separated list of "host:port" pairs to bootstrap from.
|
||||
spring.redis.database=0 # Database index used by the connection factory.
|
||||
spring.redis.url= # Connection URL, will override host, port and password (user will be ignored), e.g. redis://user:password@example.com:6379
|
||||
spring.redis.host=localhost # Redis server host.
|
||||
spring.redis.password= # Login password of the redis server.
|
||||
spring.redis.ssl=false # Enable SSL support.
|
||||
spring.redis.pool.max-active=8 # Max number of connections that can be allocated by the pool at a given time. Use a negative value for no limit.
|
||||
spring.redis.pool.max-idle=8 # Max number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections.
|
||||
spring.redis.pool.max-wait=-1 # Maximum amount of time (in milliseconds) a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
|
||||
|
|
@ -842,6 +848,7 @@ content into your application; rather pick only the properties that you need.
|
|||
spring.batch.job.names= # Comma-separated list of job names to execute on startup (For instance `job1,job2`). By default, all Jobs found in the context are executed.
|
||||
spring.batch.schema=classpath:org/springframework/batch/core/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema.
|
||||
spring.batch.table-prefix= # Table prefix for all the batch meta-data tables.
|
||||
spring.batch.transaction.*= # Transaction manager settings
|
||||
|
||||
# JMS ({sc-spring-boot-autoconfigure}/jms/JmsProperties.{sc-ext}[JmsProperties])
|
||||
spring.jms.jndi-name= # Connection factory JNDI name. When set, takes precedence to others connection factory auto-configurations.
|
||||
|
|
@ -871,6 +878,7 @@ content into your application; rather pick only the properties that you need.
|
|||
spring.kafka.consumer.group-id= # Unique string that identifies the consumer group this consumer belongs to.
|
||||
spring.kafka.consumer.heartbeat-interval= # Expected time in milliseconds between heartbeats to the consumer coordinator.
|
||||
spring.kafka.consumer.key-deserializer= # Deserializer class for keys.
|
||||
spring.kafka.consumer.max-poll-messages= # Maximum number of records returned in a single call to poll().
|
||||
spring.kafka.consumer.value-deserializer= # Deserializer class for values.
|
||||
spring.kafka.listener.ack-count= # Number of records between offset commits when ackMode is "COUNT" or "COUNT_TIME".
|
||||
spring.kafka.listener.ack-mode= # Listener AckMode; see the spring-kafka documentation.
|
||||
|
|
@ -886,6 +894,7 @@ content into your application; rather pick only the properties that you need.
|
|||
spring.kafka.producer.key-serializer= # Serializer class for keys.
|
||||
spring.kafka.producer.retries= # When greater than zero, enables retrying of failed sends.
|
||||
spring.kafka.producer.value-serializer= # Serializer class for values.
|
||||
spring.kafka.properties.*= # Additional properties used to configure the client.
|
||||
spring.kafka.ssl.key-password= # Password of the private key in the key store file.
|
||||
spring.kafka.ssl.keystore-location= # Location of the key store file.
|
||||
spring.kafka.ssl.keystore-password= # Store password for the key store file.
|
||||
|
|
|
|||
|
|
@ -634,6 +634,10 @@ for Gradle and to `${project.name}` for Maven.
|
|||
|`useStartStopDaemon`
|
||||
|If the `start-stop-daemon` command, when it's available, should be used to control the
|
||||
process. Defaults to `true`.
|
||||
|
||||
|`stopWaitTime`
|
||||
|The default value for `STOP_WAIT_TIME`. Only valid for an `init.d` service.
|
||||
Defaults to 60 seconds.
|
||||
|===
|
||||
|
||||
|
||||
|
|
@ -694,6 +698,10 @@ The following environment properties are supported with the default script:
|
|||
|`DEBUG`
|
||||
|if not empty will set the `-x` flag on the shell process, making it easy to see the logic
|
||||
in the script.
|
||||
|
||||
|`STOP_WAIT_TIME`
|
||||
|The time in seconds to wait when stopping the application before forcing a shutdown
|
||||
(`60` by default).
|
||||
|===
|
||||
|
||||
NOTE: The `PID_FOLDER`, `LOG_FOLDER` and `LOG_FILENAME` variables are only valid for an
|
||||
|
|
|
|||
|
|
@ -4604,18 +4604,23 @@ auto configuration supports all HIGH importance properties, some selected MEDIUM
|
|||
and any that do not have a default value.
|
||||
|
||||
Only a subset of the properties supported by Kafka are available via the `KafkaProperties`
|
||||
class. If you wish to configure the producer or consumer with additional properties, you
|
||||
can override the producer factory and/or consumer factory bean, adding additional
|
||||
properties, for example:
|
||||
class. If you wish to configure the producer or consumer with additional properties that
|
||||
are not directly supported, use the following:
|
||||
|
||||
[source,properties,indent=0]
|
||||
----
|
||||
spring.kafka.properties.foo.bar=baz
|
||||
----
|
||||
|
||||
This sets the common `foo.bar` Kafka property to `baz`.
|
||||
|
||||
These properties will be shared by both the consumer and producer factory beans.
|
||||
If you wish to customize these components with different properties, such as to use a
|
||||
different metrics reader for each, you can override the bean definitions, as follows:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Bean
|
||||
public ProducerFactory<?, ?> kafkaProducerFactory(KafkaProperties properties) {
|
||||
Map<String, Object> producerProperties = properties.buildProducerProperties();
|
||||
producerProperties.put("some.property", "some.value");
|
||||
return new DefaultKafkaProducerFactory<Object, Object>(producerProperties);
|
||||
}
|
||||
include::{code-examples}/kafka/KafkaSpecialProducerConsumerConfigExample.java[tag=configuration]
|
||||
----
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright 2016-2016 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.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.kafka;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.kafka.clients.CommonClientConfigs;
|
||||
import org.apache.kafka.common.metrics.KafkaMetric;
|
||||
import org.apache.kafka.common.metrics.MetricsReporter;
|
||||
|
||||
import org.springframework.boot.autoconfigure.kafka.KafkaProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.kafka.core.ConsumerFactory;
|
||||
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
|
||||
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
|
||||
import org.springframework.kafka.core.ProducerFactory;
|
||||
|
||||
/**
|
||||
* Example custom kafka configuration beans used when the user wants to apply different
|
||||
* common properties to the producer and consumer.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 1.5
|
||||
*/
|
||||
public class KafkaSpecialProducerConsumerConfigExample {
|
||||
|
||||
// tag::configuration[]
|
||||
@Configuration
|
||||
public static class CustomKafkaBeans {
|
||||
|
||||
/**
|
||||
* Customized ProducerFactory bean.
|
||||
* @param properties the kafka properties.
|
||||
* @return the bean.
|
||||
*/
|
||||
@Bean
|
||||
public ProducerFactory<?, ?> kafkaProducerFactory(KafkaProperties properties) {
|
||||
Map<String, Object> producerProperties = properties.buildProducerProperties();
|
||||
producerProperties.put(CommonClientConfigs.METRIC_REPORTER_CLASSES_CONFIG,
|
||||
MyProducerMetricsReporter.class);
|
||||
return new DefaultKafkaProducerFactory<Object, Object>(producerProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Customized ConsumerFactory bean.
|
||||
* @param properties the kafka properties.
|
||||
* @return the bean.
|
||||
*/
|
||||
@Bean
|
||||
public ConsumerFactory<?, ?> kafkaConsumerFactory(KafkaProperties properties) {
|
||||
Map<String, Object> consumererProperties = properties
|
||||
.buildConsumerProperties();
|
||||
consumererProperties.put(CommonClientConfigs.METRIC_REPORTER_CLASSES_CONFIG,
|
||||
MyConsumerMetricsReporter.class);
|
||||
return new DefaultKafkaConsumerFactory<Object, Object>(consumererProperties);
|
||||
}
|
||||
|
||||
}
|
||||
// end::configuration[]
|
||||
|
||||
public static class MyConsumerMetricsReporter implements MetricsReporter {
|
||||
|
||||
@Override
|
||||
public void configure(Map<String, ?> configs) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(List<KafkaMetric> metrics) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void metricChange(KafkaMetric metric) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void metricRemoval(KafkaMetric metric) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class MyProducerMetricsReporter implements MetricsReporter {
|
||||
|
||||
@Override
|
||||
public void configure(Map<String, ?> configs) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(List<KafkaMetric> metrics) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void metricChange(KafkaMetric metric) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void metricRemoval(KafkaMetric metric) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -73,6 +73,9 @@ fi
|
|||
# Initialize log file name if not provided by the config file
|
||||
[[ -z "$LOG_FILENAME" ]] && LOG_FILENAME="{{logFilename:${identity}.log}}"
|
||||
|
||||
# Initialize stop wait time if not provided by the config file
|
||||
[[ -z "$STOP_WAIT_TIME" ]] && STOP_WAIT_TIME={{stopWaitTime:60}}
|
||||
|
||||
# ANSI Colors
|
||||
echoRed() { echo $'\e[0;31m'"$1"$'\e[0m'; }
|
||||
echoGreen() { echo $'\e[0;32m'"$1"$'\e[0m'; }
|
||||
|
|
@ -191,9 +194,9 @@ stop() {
|
|||
|
||||
do_stop() {
|
||||
kill "$1" &> /dev/null || { echoRed "Unable to kill process $1"; return 1; }
|
||||
for i in $(seq 1 60); do
|
||||
for i in $(seq 1 $STOP_WAIT_TIME); do
|
||||
isRunning "$1" || { echoGreen "Stopped [$1]"; rm -f "$2"; return 0; }
|
||||
[[ $i -eq 30 ]] && kill "$1" &> /dev/null
|
||||
[[ $i -eq STOP_WAIT_TIME/2 ]] && kill "$1" &> /dev/null
|
||||
sleep 1
|
||||
done
|
||||
echoRed "Unable to kill process $1";
|
||||
|
|
|
|||
|
|
@ -111,6 +111,11 @@ public class DefaultLaunchScriptTests {
|
|||
assertThatPlaceholderCanBeReplaced("confFolder");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopWaitTimeCanBeReplaced() throws Exception {
|
||||
assertThatPlaceholderCanBeReplaced("stopWaitTime");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultForUseStartStopDaemonIsTrue() throws Exception {
|
||||
DefaultLaunchScript script = new DefaultLaunchScript(null, null);
|
||||
|
|
@ -125,6 +130,13 @@ public class DefaultLaunchScriptTests {
|
|||
assertThat(content).contains("MODE=\"auto\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultForStopWaitTimeIs60() throws Exception {
|
||||
DefaultLaunchScript script = new DefaultLaunchScript(null, null);
|
||||
String content = new String(script.toByteArray());
|
||||
assertThat(content).contains("STOP_WAIT_TIME=60");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadFromFile() throws Exception {
|
||||
File file = this.temporaryFolder.newFile();
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ import org.springframework.util.Assert;
|
|||
*/
|
||||
public class ImageBanner implements Banner {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ImageBanner.class);
|
||||
private static final Log logger = LogFactory.getLog(ImageBanner.class);
|
||||
|
||||
private static final double[] RGB_WEIGHT = { 0.2126d, 0.7152d, 0.0722d };
|
||||
|
||||
|
|
@ -76,9 +76,9 @@ public class ImageBanner implements Banner {
|
|||
printBanner(environment, out);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
log.warn("Image banner not printable: " + this.image + " (" + ex.getClass()
|
||||
logger.warn("Image banner not printable: " + this.image + " (" + ex.getClass()
|
||||
+ ": '" + ex.getMessage() + "')");
|
||||
log.debug("Image banner printing failure", ex);
|
||||
logger.debug("Image banner printing failure", ex);
|
||||
}
|
||||
finally {
|
||||
if (headless == null) {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ public class PropertiesConfigurationFactory<T>
|
|||
|
||||
private static final char[] TARGET_NAME_DELIMITERS = { '_', '.' };
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(PropertiesConfigurationFactory.class);
|
||||
|
||||
private boolean ignoreUnknownFields = true;
|
||||
|
||||
|
|
@ -228,8 +229,8 @@ public class PropertiesConfigurationFactory<T>
|
|||
public void bindPropertiesToTarget() throws BindException {
|
||||
Assert.state(this.propertySources != null, "PropertySources should not be null");
|
||||
try {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Property Sources: " + this.propertySources);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Property Sources: " + this.propertySources);
|
||||
|
||||
}
|
||||
this.hasBeenBound = true;
|
||||
|
|
@ -239,8 +240,9 @@ public class PropertiesConfigurationFactory<T>
|
|||
if (this.exceptionIfInvalid) {
|
||||
throw ex;
|
||||
}
|
||||
this.logger.error("Failed to load Properties validation bean. "
|
||||
+ "Your Properties may be invalid.", ex);
|
||||
PropertiesConfigurationFactory.logger
|
||||
.error("Failed to load Properties validation bean. "
|
||||
+ "Your Properties may be invalid.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -340,10 +342,10 @@ public class PropertiesConfigurationFactory<T>
|
|||
dataBinder.validate();
|
||||
BindingResult errors = dataBinder.getBindingResult();
|
||||
if (errors.hasErrors()) {
|
||||
this.logger.error("Properties configuration failed validation");
|
||||
logger.error("Properties configuration failed validation");
|
||||
for (ObjectError error : errors.getAllErrors()) {
|
||||
this.logger
|
||||
.error(this.messageSource != null
|
||||
logger.error(
|
||||
this.messageSource != null
|
||||
? this.messageSource.getMessage(error,
|
||||
Locale.getDefault()) + " (" + error + ")"
|
||||
: error);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ import org.springframework.validation.Validator;
|
|||
public class YamlConfigurationFactory<T>
|
||||
implements FactoryBean<T>, MessageSourceAware, InitializingBean {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private static final Log logger = LogFactory.getLog(YamlConfigurationFactory.class);
|
||||
|
||||
private final Class<?> type;
|
||||
|
||||
|
|
@ -137,8 +137,8 @@ public class YamlConfigurationFactory<T>
|
|||
Assert.state(this.yaml != null, "Yaml document should not be null: "
|
||||
+ "either set it directly or set the resource to load it from");
|
||||
try {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(String.format("Yaml document is %n%s", this.yaml));
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Yaml document is %n%s", this.yaml));
|
||||
}
|
||||
Constructor constructor = new YamlJavaBeanPropertyConstructor(this.type,
|
||||
this.propertyAliases);
|
||||
|
|
@ -151,7 +151,7 @@ public class YamlConfigurationFactory<T>
|
|||
if (this.exceptionIfInvalid) {
|
||||
throw ex;
|
||||
}
|
||||
this.logger.error("Failed to load YAML validation bean. "
|
||||
logger.error("Failed to load YAML validation bean. "
|
||||
+ "Your YAML file may be invalid.", ex);
|
||||
}
|
||||
}
|
||||
|
|
@ -161,13 +161,9 @@ public class YamlConfigurationFactory<T>
|
|||
"configuration");
|
||||
this.validator.validate(this.configuration, errors);
|
||||
if (errors.hasErrors()) {
|
||||
this.logger.error("YAML configuration failed validation");
|
||||
logger.error("YAML configuration failed validation");
|
||||
for (ObjectError error : errors.getAllErrors()) {
|
||||
this.logger
|
||||
.error(this.messageSource != null
|
||||
? this.messageSource.getMessage(error,
|
||||
Locale.getDefault()) + " (" + error + ")"
|
||||
: error);
|
||||
logger.error(getErrorMessage(error));
|
||||
}
|
||||
if (this.exceptionIfInvalid) {
|
||||
BindException summary = new BindException(errors);
|
||||
|
|
@ -176,6 +172,14 @@ public class YamlConfigurationFactory<T>
|
|||
}
|
||||
}
|
||||
|
||||
private Object getErrorMessage(ObjectError error) {
|
||||
if (this.messageSource != null) {
|
||||
Locale locale = Locale.getDefault();
|
||||
return this.messageSource.getMessage(error, locale) + " (" + error + ")";
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
if (this.configuration == null) {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ import org.springframework.util.ReflectionUtils;
|
|||
*/
|
||||
public final class FailureAnalyzers {
|
||||
|
||||
private static final Log log = LogFactory.getLog(FailureAnalyzers.class);
|
||||
private static final Log logger = LogFactory.getLog(FailureAnalyzers.class);
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ public final class FailureAnalyzers {
|
|||
analyzers.add((FailureAnalyzer) constructor.newInstance());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
log.trace("Failed to load " + analyzerName, ex);
|
||||
logger.trace("Failed to load " + analyzerName, ex);
|
||||
}
|
||||
}
|
||||
AnnotationAwareOrderComparator.sort(analyzers);
|
||||
|
|
|
|||
|
|
@ -42,17 +42,17 @@ public final class ClasspathLoggingApplicationListener
|
|||
|
||||
private static final int ORDER = LoggingApplicationListener.DEFAULT_ORDER + 1;
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(ClasspathLoggingApplicationListener.class);
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (event instanceof ApplicationEnvironmentPreparedEvent) {
|
||||
this.logger
|
||||
.debug("Application started with classpath: " + getClasspath());
|
||||
logger.debug("Application started with classpath: " + getClasspath());
|
||||
}
|
||||
else if (event instanceof ApplicationFailedEvent) {
|
||||
this.logger.debug(
|
||||
logger.debug(
|
||||
"Application failed to start with classpath: " + getClasspath());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue