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 com.codahale.metrics.MetricRegistry;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.boot.actuate.endpoint.MetricReaderPublicMetrics;
|
import org.springframework.boot.actuate.endpoint.MetricReaderPublicMetrics;
|
||||||
import org.springframework.boot.actuate.metrics.CounterService;
|
import org.springframework.boot.actuate.metrics.CounterService;
|
||||||
import org.springframework.boot.actuate.metrics.GaugeService;
|
import org.springframework.boot.actuate.metrics.GaugeService;
|
||||||
import org.springframework.boot.actuate.metrics.dropwizard.DropwizardMetricServices;
|
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.actuate.metrics.reader.MetricRegistryMetricReader;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
|
@ -41,6 +43,13 @@ import org.springframework.context.annotation.Configuration;
|
||||||
@AutoConfigureBefore(MetricRepositoryAutoConfiguration.class)
|
@AutoConfigureBefore(MetricRepositoryAutoConfiguration.class)
|
||||||
public class MetricsDropwizardAutoConfiguration {
|
public class MetricsDropwizardAutoConfiguration {
|
||||||
|
|
||||||
|
private final ReservoirFactory reservoirFactory;
|
||||||
|
|
||||||
|
public MetricsDropwizardAutoConfiguration(
|
||||||
|
ObjectProvider<ReservoirFactory> reservoirFactory) {
|
||||||
|
this.reservoirFactory = reservoirFactory.getIfAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public MetricRegistry metricRegistry() {
|
public MetricRegistry metricRegistry() {
|
||||||
|
|
@ -52,7 +61,12 @@ public class MetricsDropwizardAutoConfiguration {
|
||||||
GaugeService.class })
|
GaugeService.class })
|
||||||
public DropwizardMetricServices dropwizardMetricServices(
|
public DropwizardMetricServices dropwizardMetricServices(
|
||||||
MetricRegistry metricRegistry) {
|
MetricRegistry metricRegistry) {
|
||||||
return new DropwizardMetricServices(metricRegistry);
|
if (this.reservoirFactory == null) {
|
||||||
|
return new DropwizardMetricServices(metricRegistry);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new DropwizardMetricServices(metricRegistry, this.reservoirFactory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@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.ConditionalOnCloudPlatform;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.autoconfigure.security.IgnoredRequestCustomizer;
|
import org.springframework.boot.autoconfigure.security.IgnoredRequestCustomizer;
|
||||||
|
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||||
import org.springframework.boot.cloud.CloudPlatform;
|
import org.springframework.boot.cloud.CloudPlatform;
|
||||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
@ -83,10 +84,14 @@ public class CloudFoundryActuatorAutoConfiguration {
|
||||||
|
|
||||||
private CloudFoundrySecurityService getCloudFoundrySecurityService(
|
private CloudFoundrySecurityService getCloudFoundrySecurityService(
|
||||||
RestTemplateBuilder restTemplateBuilder, Environment environment) {
|
RestTemplateBuilder restTemplateBuilder, Environment environment) {
|
||||||
|
RelaxedPropertyResolver cloudFoundryProperties = new RelaxedPropertyResolver(
|
||||||
|
environment, "management.cloudfoundry.");
|
||||||
String cloudControllerUrl = environment.getProperty("vcap.application.cf_api");
|
String cloudControllerUrl = environment.getProperty("vcap.application.cf_api");
|
||||||
|
boolean skipSslValidation = cloudFoundryProperties
|
||||||
|
.getProperty("skip-ssl-validation", Boolean.class, false);
|
||||||
return cloudControllerUrl == null ? null
|
return cloudControllerUrl == null ? null
|
||||||
: new CloudFoundrySecurityService(restTemplateBuilder,
|
: new CloudFoundrySecurityService(restTemplateBuilder, cloudControllerUrl,
|
||||||
cloudControllerUrl);
|
skipSslValidation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CorsConfiguration getCorsConfiguration() {
|
private CorsConfiguration getCorsConfiguration() {
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,8 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||||
*/
|
*/
|
||||||
class CloudFoundrySecurityInterceptor extends 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;
|
private final TokenValidator tokenValidator;
|
||||||
|
|
||||||
|
|
@ -74,7 +75,7 @@ class CloudFoundrySecurityInterceptor extends HandlerInterceptorAdapter {
|
||||||
check(request, mvcEndpoint);
|
check(request, mvcEndpoint);
|
||||||
}
|
}
|
||||||
catch (CloudFoundryAuthorizationException ex) {
|
catch (CloudFoundryAuthorizationException ex) {
|
||||||
this.logger.error(ex);
|
logger.error(ex);
|
||||||
response.setContentType(MediaType.APPLICATION_JSON.toString());
|
response.setContentType(MediaType.APPLICATION_JSON.toString());
|
||||||
response.getWriter()
|
response.getWriter()
|
||||||
.write("{\"security_error\":\"" + ex.getMessage() + "\"}");
|
.write("{\"security_error\":\"" + ex.getMessage() + "\"}");
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,14 @@ class CloudFoundrySecurityService {
|
||||||
private String uaaUrl;
|
private String uaaUrl;
|
||||||
|
|
||||||
CloudFoundrySecurityService(RestTemplateBuilder restTemplateBuilder,
|
CloudFoundrySecurityService(RestTemplateBuilder restTemplateBuilder,
|
||||||
String cloudControllerUrl) {
|
String cloudControllerUrl, boolean skipSslValidation) {
|
||||||
Assert.notNull(restTemplateBuilder, "RestTemplateBuilder must not be null");
|
Assert.notNull(restTemplateBuilder, "RestTemplateBuilder must not be null");
|
||||||
Assert.notNull(cloudControllerUrl, "CloudControllerUrl must not be null");
|
Assert.notNull(cloudControllerUrl, "CloudControllerUrl must not be null");
|
||||||
this.restTemplate = restTemplateBuilder
|
if (skipSslValidation) {
|
||||||
.requestFactory(SkipSslVerificationHttpRequestFactory.class).build();
|
restTemplateBuilder = restTemplateBuilder
|
||||||
|
.requestFactory(SkipSslVerificationHttpRequestFactory.class);
|
||||||
|
}
|
||||||
|
this.restTemplate = restTemplateBuilder.build();
|
||||||
this.cloudControllerUrl = cloudControllerUrl;
|
this.cloudControllerUrl = cloudControllerUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,16 @@
|
||||||
package org.springframework.boot.actuate.endpoint.mvc;
|
package org.springframework.boot.actuate.endpoint.mvc;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
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.http.HttpStatus;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.cors.CorsUtils;
|
import org.springframework.web.cors.CorsUtils;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||||
|
|
@ -34,10 +39,15 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||||
*/
|
*/
|
||||||
public class MvcEndpointSecurityInterceptor extends HandlerInterceptorAdapter {
|
public class MvcEndpointSecurityInterceptor extends HandlerInterceptorAdapter {
|
||||||
|
|
||||||
|
private static final Log logger = LogFactory
|
||||||
|
.getLog(MvcEndpointSecurityInterceptor.class);
|
||||||
|
|
||||||
private final boolean secure;
|
private final boolean secure;
|
||||||
|
|
||||||
private final List<String> roles;
|
private final List<String> roles;
|
||||||
|
|
||||||
|
private AtomicBoolean loggedUnauthorizedAttempt = new AtomicBoolean();
|
||||||
|
|
||||||
public MvcEndpointSecurityInterceptor(boolean secure, List<String> roles) {
|
public MvcEndpointSecurityInterceptor(boolean secure, List<String> roles) {
|
||||||
this.secure = secure;
|
this.secure = secure;
|
||||||
this.roles = roles;
|
this.roles = roles;
|
||||||
|
|
@ -59,17 +69,30 @@ public class MvcEndpointSecurityInterceptor extends HandlerInterceptorAdapter {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setFailureResponseStatus(request, response);
|
sendFailureResponse(request, response);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFailureResponseStatus(HttpServletRequest request,
|
private void sendFailureResponse(HttpServletRequest request,
|
||||||
HttpServletResponse response) {
|
HttpServletResponse response) throws Exception {
|
||||||
if (request.getUserPrincipal() != null) {
|
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 {
|
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.Gauge;
|
||||||
import com.codahale.metrics.Histogram;
|
import com.codahale.metrics.Histogram;
|
||||||
import com.codahale.metrics.Meter;
|
import com.codahale.metrics.Meter;
|
||||||
|
import com.codahale.metrics.Metric;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
|
import com.codahale.metrics.Reservoir;
|
||||||
import com.codahale.metrics.Timer;
|
import com.codahale.metrics.Timer;
|
||||||
|
|
||||||
import org.springframework.boot.actuate.metrics.CounterService;
|
import org.springframework.boot.actuate.metrics.CounterService;
|
||||||
import org.springframework.boot.actuate.metrics.GaugeService;
|
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
|
* 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 MetricRegistry registry;
|
||||||
|
|
||||||
|
private final ReservoirFactory reservoirFactory;
|
||||||
|
|
||||||
private final ConcurrentMap<String, SimpleGauge> gauges = new ConcurrentHashMap<String, SimpleGauge>();
|
private final ConcurrentMap<String, SimpleGauge> gauges = new ConcurrentHashMap<String, SimpleGauge>();
|
||||||
|
|
||||||
private final ConcurrentHashMap<String, String> names = new ConcurrentHashMap<String, String>();
|
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
|
* @param registry the underlying metric registry
|
||||||
*/
|
*/
|
||||||
public DropwizardMetricServices(MetricRegistry 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.registry = registry;
|
||||||
|
this.reservoirFactory = (reservoirFactory == null ? ReservoirFactory.NONE
|
||||||
|
: reservoirFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -90,14 +109,10 @@ public class DropwizardMetricServices implements CounterService, GaugeService {
|
||||||
@Override
|
@Override
|
||||||
public void submit(String name, double value) {
|
public void submit(String name, double value) {
|
||||||
if (name.startsWith("histogram")) {
|
if (name.startsWith("histogram")) {
|
||||||
long longValue = (long) value;
|
submitHistogram(name, value);
|
||||||
Histogram metric = this.registry.histogram(name);
|
|
||||||
metric.update(longValue);
|
|
||||||
}
|
}
|
||||||
else if (name.startsWith("timer")) {
|
else if (name.startsWith("timer")) {
|
||||||
long longValue = (long) value;
|
submitTimer(name, value);
|
||||||
Timer metric = this.registry.timer(name);
|
|
||||||
metric.update(longValue, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
name = wrapGaugeName(name);
|
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) {
|
private void setGaugeValue(String name, double value) {
|
||||||
// NOTE: Dropwizard provides no way to do this atomically
|
// NOTE: Dropwizard provides no way to do this atomically
|
||||||
SimpleGauge gauge = this.gauges.get(name);
|
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.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
|
||||||
|
|
@ -117,6 +118,22 @@ public class CloudFoundryActuatorAutoConfigurationTests {
|
||||||
assertThat(cloudControllerUrl).isEqualTo("http://my-cloud-controller.com");
|
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
|
@Test
|
||||||
public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent()
|
public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,9 @@ import org.springframework.boot.test.web.client.MockServerRestTemplateCustomizer
|
||||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
import org.springframework.test.web.client.MockRestServiceServer;
|
import org.springframework.test.web.client.MockRestServiceServer;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
|
||||||
|
|
@ -63,10 +65,33 @@ public class CloudFoundrySecurityServiceTests {
|
||||||
public void setup() throws Exception {
|
public void setup() throws Exception {
|
||||||
MockServerRestTemplateCustomizer mockServerCustomizer = new MockServerRestTemplateCustomizer();
|
MockServerRestTemplateCustomizer mockServerCustomizer = new MockServerRestTemplateCustomizer();
|
||||||
RestTemplateBuilder builder = new RestTemplateBuilder(mockServerCustomizer);
|
RestTemplateBuilder builder = new RestTemplateBuilder(mockServerCustomizer);
|
||||||
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER);
|
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER,
|
||||||
|
false);
|
||||||
this.server = mockServerCustomizer.getServer();
|
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
|
@Test
|
||||||
public void getAccessLevelWhenSpaceDeveloperShouldReturnFull() throws Exception {
|
public void getAccessLevelWhenSpaceDeveloperShouldReturnFull() throws Exception {
|
||||||
String responseBody = "{\"read_sensitive_data\": true,\"read_basic_data\": true}";
|
String responseBody = "{\"read_sensitive_data\": true,\"read_basic_data\": true}";
|
||||||
|
|
|
||||||
|
|
@ -16,19 +16,26 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.endpoint.mvc;
|
package org.springframework.boot.actuate.endpoint.mvc;
|
||||||
|
|
||||||
|
import java.security.Principal;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
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.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
|
||||||
import org.springframework.mock.web.MockServletContext;
|
import org.springframework.mock.web.MockServletContext;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link MvcEndpointSecurityInterceptor}.
|
* Tests for {@link MvcEndpointSecurityInterceptor}.
|
||||||
|
|
@ -37,6 +44,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*/
|
*/
|
||||||
public class MvcEndpointSecurityInterceptorTests {
|
public class MvcEndpointSecurityInterceptorTests {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public OutputCapture output = new OutputCapture();
|
||||||
|
|
||||||
private MvcEndpointSecurityInterceptor securityInterceptor;
|
private MvcEndpointSecurityInterceptor securityInterceptor;
|
||||||
|
|
||||||
private TestMvcEndpoint mvcEndpoint;
|
private TestMvcEndpoint mvcEndpoint;
|
||||||
|
|
@ -47,7 +57,7 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||||
|
|
||||||
private MockHttpServletRequest request;
|
private MockHttpServletRequest request;
|
||||||
|
|
||||||
private MockHttpServletResponse response;
|
private HttpServletResponse response;
|
||||||
|
|
||||||
private MockServletContext servletContext;
|
private MockServletContext servletContext;
|
||||||
|
|
||||||
|
|
@ -62,7 +72,7 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||||
this.handlerMethod = new HandlerMethod(this.mvcEndpoint, "invoke");
|
this.handlerMethod = new HandlerMethod(this.mvcEndpoint, "invoke");
|
||||||
this.servletContext = new MockServletContext();
|
this.servletContext = new MockServletContext();
|
||||||
this.request = new MockHttpServletRequest(this.servletContext);
|
this.request = new MockHttpServletRequest(this.servletContext);
|
||||||
this.response = new MockHttpServletResponse();
|
this.response = mock(HttpServletResponse.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -87,11 +97,30 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sensitiveEndpointIfRoleIsNotPresentShouldNotAllowAccess()
|
public void sensitiveEndpointIfNotAuthenticatedShouldNotAllowAccess()
|
||||||
throws Exception {
|
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");
|
this.servletContext.declareRoles("HERO");
|
||||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
||||||
this.handlerMethod)).isFalse();
|
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> {
|
private static class TestEndpoint extends AbstractEndpoint<Object> {
|
||||||
|
|
|
||||||
|
|
@ -20,22 +20,41 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.codahale.metrics.Gauge;
|
import com.codahale.metrics.Gauge;
|
||||||
|
import com.codahale.metrics.Histogram;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
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.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.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link DropwizardMetricServices}.
|
* Tests for {@link DropwizardMetricServices}.
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @author Lucas Saldanha
|
||||||
*/
|
*/
|
||||||
public class DropwizardMetricServicesTests {
|
public class DropwizardMetricServicesTests {
|
||||||
|
|
||||||
private final MetricRegistry registry = new MetricRegistry();
|
private MetricRegistry registry = new MetricRegistry();
|
||||||
|
|
||||||
private final DropwizardMetricServices writer = new DropwizardMetricServices(
|
@Mock
|
||||||
this.registry);
|
private ReservoirFactory reservoirFactory;
|
||||||
|
|
||||||
|
private DropwizardMetricServices writer;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
this.writer = new DropwizardMetricServices(this.registry, this.reservoirFactory);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void incrementCounter() {
|
public void incrementCounter() {
|
||||||
|
|
@ -78,6 +97,20 @@ public class DropwizardMetricServicesTests {
|
||||||
assertThat(this.registry.timer("timer.foo").getCount()).isEqualTo(2);
|
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
|
@Test
|
||||||
public void setPredefinedHistogram() {
|
public void setPredefinedHistogram() {
|
||||||
this.writer.submit("histogram.foo", 2.1);
|
this.writer.submit("histogram.foo", 2.1);
|
||||||
|
|
@ -85,6 +118,18 @@ public class DropwizardMetricServicesTests {
|
||||||
assertThat(this.registry.histogram("histogram.foo").getCount()).isEqualTo(2);
|
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
|
* 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
|
* 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.jdbc.datasource.DataSourceTransactionManager;
|
||||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -40,6 +41,7 @@ import org.springframework.util.StringUtils;
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Kazuki Shimizu
|
||||||
*/
|
*/
|
||||||
public class BasicBatchConfigurer implements BatchConfigurer {
|
public class BasicBatchConfigurer implements BatchConfigurer {
|
||||||
|
|
||||||
|
|
@ -150,6 +152,12 @@ public class BasicBatchConfigurer implements BatchConfigurer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PlatformTransactionManager createTransactionManager() {
|
protected PlatformTransactionManager createTransactionManager() {
|
||||||
|
AbstractPlatformTransactionManager transactionManager = createAppropriateTransactionManager();
|
||||||
|
this.properties.getTransaction().applyTo(transactionManager);
|
||||||
|
return transactionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbstractPlatformTransactionManager createAppropriateTransactionManager() {
|
||||||
if (this.entityManagerFactory != null) {
|
if (this.entityManagerFactory != null) {
|
||||||
return new JpaTransactionManager(this.entityManagerFactory);
|
return new JpaTransactionManager(this.entityManagerFactory);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.springframework.jdbc.core.JdbcOperations;
|
import org.springframework.jdbc.core.JdbcOperations;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -57,6 +58,7 @@ import org.springframework.util.StringUtils;
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Eddú Meléndez
|
* @author Eddú Meléndez
|
||||||
|
* @author Kazuki Shimizu
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass({ JobLauncher.class, DataSource.class, JdbcOperations.class })
|
@ConditionalOnClass({ JobLauncher.class, DataSource.class, JdbcOperations.class })
|
||||||
|
|
@ -133,7 +135,8 @@ public class BatchAutoConfiguration {
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConditionalOnClass(name = "javax.persistence.EntityManagerFactory")
|
@EnableConfigurationProperties(BatchProperties.class)
|
||||||
|
@ConditionalOnClass(value = PlatformTransactionManager.class, name = "javax.persistence.EntityManagerFactory")
|
||||||
@ConditionalOnMissingBean(BatchConfigurer.class)
|
@ConditionalOnMissingBean(BatchConfigurer.class)
|
||||||
@Configuration
|
@Configuration
|
||||||
protected static class JpaBatchConfiguration {
|
protected static class JpaBatchConfiguration {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.batch;
|
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.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration properties for Spring Batch.
|
* Configuration properties for Spring Batch.
|
||||||
|
|
@ -46,6 +48,9 @@ public class BatchProperties {
|
||||||
|
|
||||||
private final Job job = new Job();
|
private final Job job = new Job();
|
||||||
|
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private final TransactionProperties transaction = new TransactionProperties();
|
||||||
|
|
||||||
public String getSchema() {
|
public String getSchema() {
|
||||||
return this.schema;
|
return this.schema;
|
||||||
}
|
}
|
||||||
|
|
@ -54,6 +59,14 @@ public class BatchProperties {
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTablePrefix() {
|
||||||
|
return this.tablePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTablePrefix(String tablePrefix) {
|
||||||
|
this.tablePrefix = tablePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
public Initializer getInitializer() {
|
public Initializer getInitializer() {
|
||||||
return this.initializer;
|
return this.initializer;
|
||||||
}
|
}
|
||||||
|
|
@ -62,12 +75,8 @@ public class BatchProperties {
|
||||||
return this.job;
|
return this.job;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTablePrefix(String tablePrefix) {
|
public TransactionProperties getTransaction() {
|
||||||
this.tablePrefix = tablePrefix;
|
return this.transaction;
|
||||||
}
|
|
||||||
|
|
||||||
public String getTablePrefix() {
|
|
||||||
return this.tablePrefix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Initializer {
|
public class Initializer {
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
||||||
* @author Josh Long
|
* @author Josh Long
|
||||||
* @author Vince Bickers
|
* @author Vince Bickers
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Kazuki Shimizu
|
||||||
* @since 1.4.0
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass(SessionFactory.class)
|
@ConditionalOnClass({ SessionFactory.class, PlatformTransactionManager.class })
|
||||||
@ConditionalOnMissingBean(SessionFactory.class)
|
@ConditionalOnMissingBean(SessionFactory.class)
|
||||||
@EnableConfigurationProperties(Neo4jProperties.class)
|
@EnableConfigurationProperties(Neo4jProperties.class)
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
|
@ -87,8 +88,12 @@ public class Neo4jDataAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||||
public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory) {
|
public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory,
|
||||||
return new Neo4jTransactionManager(sessionFactory);
|
Neo4jProperties properties) {
|
||||||
|
Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(
|
||||||
|
sessionFactory);
|
||||||
|
properties.getTransaction().applyTo(transactionManager);
|
||||||
|
return transactionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[] getPackagesToScan(ApplicationContext applicationContext) {
|
private String[] getPackagesToScan(ApplicationContext applicationContext) {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ import org.neo4j.ogm.config.Configuration;
|
||||||
import org.neo4j.ogm.config.DriverConfiguration;
|
import org.neo4j.ogm.config.DriverConfiguration;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
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.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
@ -69,6 +71,9 @@ public class Neo4jProperties implements ApplicationContextAware {
|
||||||
|
|
||||||
private final Embedded embedded = new Embedded();
|
private final Embedded embedded = new Embedded();
|
||||||
|
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private final TransactionProperties transaction = new TransactionProperties();
|
||||||
|
|
||||||
private ClassLoader classLoader = Neo4jProperties.class.getClassLoader();
|
private ClassLoader classLoader = Neo4jProperties.class.getClassLoader();
|
||||||
|
|
||||||
public String getUri() {
|
public String getUri() {
|
||||||
|
|
@ -107,6 +112,10 @@ public class Neo4jProperties implements ApplicationContextAware {
|
||||||
return this.embedded;
|
return this.embedded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TransactionProperties getTransaction() {
|
||||||
|
return this.transaction;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
|
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
|
||||||
this.classLoader = ctx.getClassLoader();
|
this.classLoader = ctx.getClassLoader();
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.data.redis;
|
package org.springframework.boot.autoconfigure.data.redis;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -55,6 +57,7 @@ import org.springframework.util.StringUtils;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Eddú Meléndez
|
* @author Eddú Meléndez
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Marco Aust
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
|
@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
|
||||||
|
|
@ -91,10 +94,9 @@ public class RedisAutoConfiguration {
|
||||||
|
|
||||||
protected final JedisConnectionFactory applyProperties(
|
protected final JedisConnectionFactory applyProperties(
|
||||||
JedisConnectionFactory factory) {
|
JedisConnectionFactory factory) {
|
||||||
factory.setHostName(this.properties.getHost());
|
configureConnection(factory);
|
||||||
factory.setPort(this.properties.getPort());
|
if (this.properties.isSsl()) {
|
||||||
if (this.properties.getPassword() != null) {
|
factory.setUseSsl(true);
|
||||||
factory.setPassword(this.properties.getPassword());
|
|
||||||
}
|
}
|
||||||
factory.setDatabase(this.properties.getDatabase());
|
factory.setDatabase(this.properties.getDatabase());
|
||||||
if (this.properties.getTimeout() > 0) {
|
if (this.properties.getTimeout() > 0) {
|
||||||
|
|
@ -103,6 +105,43 @@ public class RedisAutoConfiguration {
|
||||||
return factory;
|
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() {
|
protected final RedisSentinelConfiguration getSentinelConfig() {
|
||||||
if (this.sentinelConfiguration != null) {
|
if (this.sentinelConfiguration != null) {
|
||||||
return this.sentinelConfiguration;
|
return this.sentinelConfiguration;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Eddú Meléndez
|
* @author Eddú Meléndez
|
||||||
|
* @author Marco Aust
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties(prefix = "spring.redis")
|
@ConfigurationProperties(prefix = "spring.redis")
|
||||||
public class RedisProperties {
|
public class RedisProperties {
|
||||||
|
|
@ -35,6 +36,11 @@ public class RedisProperties {
|
||||||
*/
|
*/
|
||||||
private int database = 0;
|
private int database = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis url, which will overrule host, port and password if set.
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redis server host.
|
* Redis server host.
|
||||||
*/
|
*/
|
||||||
|
|
@ -50,6 +56,11 @@ public class RedisProperties {
|
||||||
*/
|
*/
|
||||||
private int port = 6379;
|
private int port = 6379;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable SSL.
|
||||||
|
*/
|
||||||
|
private boolean ssl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection timeout in milliseconds.
|
* Connection timeout in milliseconds.
|
||||||
*/
|
*/
|
||||||
|
|
@ -69,6 +80,14 @@ public class RedisProperties {
|
||||||
this.database = database;
|
this.database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return this.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
public String getHost() {
|
public String getHost() {
|
||||||
return this.host;
|
return this.host;
|
||||||
}
|
}
|
||||||
|
|
@ -93,6 +112,14 @@ public class RedisProperties {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSsl() {
|
||||||
|
return this.ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSsl(boolean ssl) {
|
||||||
|
this.ssl = ssl;
|
||||||
|
}
|
||||||
|
|
||||||
public void setTimeout(int timeout) {
|
public void setTimeout(int timeout) {
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,9 @@ import javax.sql.DataSource;
|
||||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||||
import org.springframework.beans.factory.BeanCreationException;
|
import org.springframework.beans.factory.BeanCreationException;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
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.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||||
import org.springframework.boot.jdbc.DatabaseDriver;
|
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||||
import org.springframework.context.EnvironmentAware;
|
import org.springframework.context.EnvironmentAware;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
|
@ -157,6 +159,9 @@ public class DataSourceProperties
|
||||||
|
|
||||||
private String uniqueName;
|
private String uniqueName;
|
||||||
|
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private final TransactionProperties transaction = new TransactionProperties();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
|
|
@ -473,6 +478,10 @@ public class DataSourceProperties
|
||||||
this.xa = xa;
|
this.xa = xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TransactionProperties getTransaction() {
|
||||||
|
return this.transaction;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XA Specific datasource settings.
|
* 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.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
|
|
@ -39,10 +40,12 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Kazuki Shimizu
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class })
|
@ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class })
|
||||||
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
|
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
|
||||||
|
@EnableConfigurationProperties(DataSourceProperties.class)
|
||||||
public class DataSourceTransactionManagerAutoConfiguration {
|
public class DataSourceTransactionManagerAutoConfiguration {
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
|
@ -57,8 +60,12 @@ public class DataSourceTransactionManagerAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||||
public DataSourceTransactionManager transactionManager() {
|
public DataSourceTransactionManager transactionManager(
|
||||||
return new DataSourceTransactionManager(this.dataSource);
|
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.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.kafka.listener.AbstractMessageListenerContainer.AckMode;
|
import org.springframework.kafka.listener.AbstractMessageListenerContainer.AckMode;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration properties for Spring for Apache Kafka.
|
* Configuration properties for Spring for Apache Kafka.
|
||||||
|
|
@ -47,18 +48,6 @@ import org.springframework.kafka.listener.AbstractMessageListenerContainer.AckMo
|
||||||
@ConfigurationProperties(prefix = "spring.kafka")
|
@ConfigurationProperties(prefix = "spring.kafka")
|
||||||
public class KafkaProperties {
|
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
|
* Comma-delimited list of host:port pairs to use for establishing the initial
|
||||||
* connection to the Kafka cluster.
|
* connection to the Kafka cluster.
|
||||||
|
|
@ -71,6 +60,45 @@ public class KafkaProperties {
|
||||||
*/
|
*/
|
||||||
private String clientId;
|
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() {
|
public Consumer getConsumer() {
|
||||||
return this.consumer;
|
return this.consumer;
|
||||||
}
|
}
|
||||||
|
|
@ -91,22 +119,6 @@ public class KafkaProperties {
|
||||||
return this.template;
|
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() {
|
private Map<String, Object> buildCommonProperties() {
|
||||||
Map<String, Object> properties = new HashMap<String, Object>();
|
Map<String, Object> properties = new HashMap<String, Object>();
|
||||||
if (this.bootstrapServers != null) {
|
if (this.bootstrapServers != null) {
|
||||||
|
|
@ -135,6 +147,9 @@ public class KafkaProperties {
|
||||||
properties.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG,
|
properties.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG,
|
||||||
this.ssl.getTruststorePassword());
|
this.ssl.getTruststorePassword());
|
||||||
}
|
}
|
||||||
|
if (!CollectionUtils.isEmpty(this.properties)) {
|
||||||
|
properties.putAll(this.properties);
|
||||||
|
}
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,9 +162,9 @@ public class KafkaProperties {
|
||||||
* instance
|
* instance
|
||||||
*/
|
*/
|
||||||
public Map<String, Object> buildConsumerProperties() {
|
public Map<String, Object> buildConsumerProperties() {
|
||||||
Map<String, Object> props = buildCommonProperties();
|
Map<String, Object> properties = buildCommonProperties();
|
||||||
props.putAll(this.consumer.buildProperties());
|
properties.putAll(this.consumer.buildProperties());
|
||||||
return props;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -161,9 +176,9 @@ public class KafkaProperties {
|
||||||
* instance
|
* instance
|
||||||
*/
|
*/
|
||||||
public Map<String, Object> buildProducerProperties() {
|
public Map<String, Object> buildProducerProperties() {
|
||||||
Map<String, Object> props = buildCommonProperties();
|
Map<String, Object> properties = buildCommonProperties();
|
||||||
props.putAll(this.producer.buildProperties());
|
properties.putAll(this.producer.buildProperties());
|
||||||
return props;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String resourceToPath(Resource resource) {
|
private static String resourceToPath(Resource resource) {
|
||||||
|
|
@ -240,6 +255,11 @@ public class KafkaProperties {
|
||||||
*/
|
*/
|
||||||
private Class<?> valueDeserializer = StringDeserializer.class;
|
private Class<?> valueDeserializer = StringDeserializer.class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of records returned in a single call to poll().
|
||||||
|
*/
|
||||||
|
private Integer maxPollRecords;
|
||||||
|
|
||||||
public Ssl getSsl() {
|
public Ssl getSsl() {
|
||||||
return this.ssl;
|
return this.ssl;
|
||||||
}
|
}
|
||||||
|
|
@ -332,6 +352,14 @@ public class KafkaProperties {
|
||||||
this.valueDeserializer = valueDeserializer;
|
this.valueDeserializer = valueDeserializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getMaxPollRecords() {
|
||||||
|
return this.maxPollRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxPollRecords(Integer maxPollRecords) {
|
||||||
|
this.maxPollRecords = maxPollRecords;
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String, Object> buildProperties() {
|
public Map<String, Object> buildProperties() {
|
||||||
Map<String, Object> properties = new HashMap<String, Object>();
|
Map<String, Object> properties = new HashMap<String, Object>();
|
||||||
if (this.autoCommitInterval != null) {
|
if (this.autoCommitInterval != null) {
|
||||||
|
|
@ -395,6 +423,10 @@ public class KafkaProperties {
|
||||||
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
|
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
|
||||||
this.valueDeserializer);
|
this.valueDeserializer);
|
||||||
}
|
}
|
||||||
|
if (this.maxPollRecords != null) {
|
||||||
|
properties.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG,
|
||||||
|
this.maxPollRecords);
|
||||||
|
}
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Kazuki Shimizu
|
||||||
*/
|
*/
|
||||||
@EnableConfigurationProperties(JpaProperties.class)
|
@EnableConfigurationProperties(JpaProperties.class)
|
||||||
@Import(DataSourceInitializedPublisher.Registrar.class)
|
@Import(DataSourceInitializedPublisher.Registrar.class)
|
||||||
|
|
@ -82,7 +83,9 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware {
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||||
public PlatformTransactionManager transactionManager() {
|
public PlatformTransactionManager transactionManager() {
|
||||||
return new JpaTransactionManager();
|
JpaTransactionManager transactionManager = new JpaTransactionManager();
|
||||||
|
this.properties.getTransaction().applyTo(transactionManager);
|
||||||
|
return transactionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import java.util.Map;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection;
|
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.ConfigurationProperties;
|
||||||
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||||
import org.springframework.orm.jpa.vendor.Database;
|
import org.springframework.orm.jpa.vendor.Database;
|
||||||
|
|
@ -67,6 +68,9 @@ public class JpaProperties {
|
||||||
|
|
||||||
private Hibernate hibernate = new Hibernate();
|
private Hibernate hibernate = new Hibernate();
|
||||||
|
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private final TransactionProperties transaction = new TransactionProperties();
|
||||||
|
|
||||||
public Map<String, String> getProperties() {
|
public Map<String, String> getProperties() {
|
||||||
return this.properties;
|
return this.properties;
|
||||||
}
|
}
|
||||||
|
|
@ -125,6 +129,10 @@ public class JpaProperties {
|
||||||
return this.hibernate.getAdditionalProperties(this.properties, dataSource);
|
return this.hibernate.getAdditionalProperties(this.properties, dataSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TransactionProperties getTransaction() {
|
||||||
|
return this.transaction;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Hibernate {
|
public static class Hibernate {
|
||||||
|
|
||||||
private static final String USE_NEW_ID_GENERATOR_MAPPINGS = "hibernate.id."
|
private static final String USE_NEW_ID_GENERATOR_MAPPINGS = "hibernate.id."
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.security.oauth2.client;
|
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 javax.annotation.Resource;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
@ -76,7 +70,7 @@ import org.springframework.util.StringUtils;
|
||||||
public class OAuth2RestOperationsConfiguration {
|
public class OAuth2RestOperationsConfiguration {
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClientCredentials
|
@Conditional(ClientCredentialsCondition.class)
|
||||||
protected static class SingletonScopedConfiguration {
|
protected static class SingletonScopedConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|
@ -96,7 +90,7 @@ public class OAuth2RestOperationsConfiguration {
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnBean(OAuth2ClientConfiguration.class)
|
@ConditionalOnBean(OAuth2ClientConfiguration.class)
|
||||||
@ConditionalOnNotClientCredentials
|
@Conditional(NoClientCredentialsCondition.class)
|
||||||
@Import(OAuth2ProtectedResourceDetailsConfiguration.class)
|
@Import(OAuth2ProtectedResourceDetailsConfiguration.class)
|
||||||
protected static class SessionScopedConfiguration {
|
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
|
||||||
* 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
|
||||||
* 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
|
||||||
* OAuth2ClientContextFilter until we need to refresh the access token. To handle
|
// refresh tokens you need to @EnableOAuth2Client
|
||||||
* refresh tokens you need to {@code @EnableOAuth2Client}
|
|
||||||
*/
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnMissingBean(OAuth2ClientConfiguration.class)
|
@ConditionalOnMissingBean(OAuth2ClientConfiguration.class)
|
||||||
@ConditionalOnNotClientCredentials
|
@Conditional(NoClientCredentialsCondition.class)
|
||||||
@Import(OAuth2ProtectedResourceDetailsConfiguration.class)
|
@Import(OAuth2ProtectedResourceDetailsConfiguration.class)
|
||||||
protected static class RequestScopedConfiguration {
|
protected static class RequestScopedConfiguration {
|
||||||
|
|
||||||
|
|
@ -182,22 +174,24 @@ public class OAuth2RestOperationsConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Conditional(ClientCredentialsCondition.class)
|
/**
|
||||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
* Condition to check for no client credentials.
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
*/
|
||||||
@Documented
|
static class NoClientCredentialsCondition extends NoneNestedConditions {
|
||||||
public static @interface ConditionalOnClientCredentials {
|
|
||||||
|
NoClientCredentialsCondition() {
|
||||||
}
|
super(ConfigurationPhase.PARSE_CONFIGURATION);
|
||||||
|
}
|
||||||
@Conditional(NotClientCredentialsCondition.class)
|
|
||||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
@Conditional(ClientCredentialsCondition.class)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
static class ClientCredentialsActivated {
|
||||||
@Documented
|
}
|
||||||
public static @interface ConditionalOnNotClientCredentials {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Condition to check for client credentials.
|
||||||
|
*/
|
||||||
static class ClientCredentialsCondition extends AnyNestedCondition {
|
static class ClientCredentialsCondition extends AnyNestedCondition {
|
||||||
|
|
||||||
ClientCredentialsCondition() {
|
ClientCredentialsCondition() {
|
||||||
|
|
@ -211,17 +205,6 @@ public class OAuth2RestOperationsConfiguration {
|
||||||
@ConditionalOnNotWebApplication
|
@ConditionalOnNotWebApplication
|
||||||
static class NoWebApplication {
|
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 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.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
@ -43,8 +40,6 @@ import org.springframework.social.oauth2.AccessGrant;
|
||||||
*/
|
*/
|
||||||
public class SpringSocialTokenServices implements ResourceServerTokenServices {
|
public class SpringSocialTokenServices implements ResourceServerTokenServices {
|
||||||
|
|
||||||
protected final Log logger = LogFactory.getLog(getClass());
|
|
||||||
|
|
||||||
private final OAuth2ConnectionFactory<?> connectionFactory;
|
private final OAuth2ConnectionFactory<?> connectionFactory;
|
||||||
|
|
||||||
private final String clientId;
|
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 Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Kazuki Shimizu
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableConfigurationProperties(AtomikosProperties.class)
|
@EnableConfigurationProperties({ AtomikosProperties.class, JtaProperties.class })
|
||||||
@ConditionalOnClass({ JtaTransactionManager.class, UserTransactionManager.class })
|
@ConditionalOnClass({ JtaTransactionManager.class, UserTransactionManager.class })
|
||||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||||
class AtomikosJtaConfiguration {
|
class AtomikosJtaConfiguration {
|
||||||
|
|
@ -111,7 +112,10 @@ class AtomikosJtaConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
public JtaTransactionManager transactionManager(UserTransaction userTransaction,
|
public JtaTransactionManager transactionManager(UserTransaction userTransaction,
|
||||||
TransactionManager transactionManager) {
|
TransactionManager transactionManager) {
|
||||||
return new JtaTransactionManager(userTransaction, transactionManager);
|
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(
|
||||||
|
userTransaction, transactionManager);
|
||||||
|
this.jtaProperties.getTransaction().applyTo(jtaTransactionManager);
|
||||||
|
return jtaTransactionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import org.springframework.boot.ApplicationHome;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
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.XAConnectionFactoryWrapper;
|
||||||
import org.springframework.boot.jta.XADataSourceWrapper;
|
import org.springframework.boot.jta.XADataSourceWrapper;
|
||||||
import org.springframework.boot.jta.bitronix.BitronixDependentBeanFactoryPostProcessor;
|
import org.springframework.boot.jta.bitronix.BitronixDependentBeanFactoryPostProcessor;
|
||||||
|
|
@ -46,9 +47,11 @@ import org.springframework.util.StringUtils;
|
||||||
* @author Josh Long
|
* @author Josh Long
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Kazuki Shimizu
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@EnableConfigurationProperties(JtaProperties.class)
|
||||||
@ConditionalOnClass({ JtaTransactionManager.class, BitronixContext.class })
|
@ConditionalOnClass({ JtaTransactionManager.class, BitronixContext.class })
|
||||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||||
class BitronixJtaConfiguration {
|
class BitronixJtaConfiguration {
|
||||||
|
|
@ -105,7 +108,10 @@ class BitronixJtaConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
public JtaTransactionManager transactionManager(
|
public JtaTransactionManager transactionManager(
|
||||||
TransactionManager transactionManager) {
|
TransactionManager transactionManager) {
|
||||||
return new JtaTransactionManager(transactionManager);
|
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(
|
||||||
|
transactionManager);
|
||||||
|
this.jtaProperties.getTransaction().applyTo(jtaTransactionManager);
|
||||||
|
return jtaTransactionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConditionalOnClass(Message.class)
|
@ConditionalOnClass(Message.class)
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import org.springframework.transaction.jta.JtaTransactionManager;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Kazuki Shimizu
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
|
@ -40,9 +41,18 @@ import org.springframework.transaction.jta.JtaTransactionManager;
|
||||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||||
class JndiJtaConfiguration {
|
class JndiJtaConfiguration {
|
||||||
|
|
||||||
|
private final JtaProperties jtaProperties;
|
||||||
|
|
||||||
|
JndiJtaConfiguration(JtaProperties jtaProperties) {
|
||||||
|
this.jtaProperties = jtaProperties;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public JtaTransactionManager transactionManager() {
|
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;
|
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.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,6 +44,9 @@ public class JtaProperties {
|
||||||
*/
|
*/
|
||||||
private String transactionManagerId;
|
private String transactionManagerId;
|
||||||
|
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private final TransactionProperties transaction = new TransactionProperties();
|
||||||
|
|
||||||
public void setLogDir(String logDir) {
|
public void setLogDir(String logDir) {
|
||||||
this.logDir = logDir;
|
this.logDir = logDir;
|
||||||
}
|
}
|
||||||
|
|
@ -58,4 +63,8 @@ public class JtaProperties {
|
||||||
this.transactionManagerId = transactionManagerId;
|
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.ApplicationHome;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
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.XAConnectionFactoryWrapper;
|
||||||
import org.springframework.boot.jta.XADataSourceWrapper;
|
import org.springframework.boot.jta.XADataSourceWrapper;
|
||||||
import org.springframework.boot.jta.narayana.NarayanaBeanFactoryPostProcessor;
|
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>.
|
* JTA Configuration for <a href="http://narayana.io/">Narayana</a>.
|
||||||
*
|
*
|
||||||
* @author Gytis Trikleris
|
* @author Gytis Trikleris
|
||||||
|
* @author Kazuki Shimizu
|
||||||
* @since 1.4.0
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass({ JtaTransactionManager.class,
|
@ConditionalOnClass({ JtaTransactionManager.class,
|
||||||
com.arjuna.ats.jta.UserTransaction.class, XAResourceRecoveryRegistry.class })
|
com.arjuna.ats.jta.UserTransaction.class, XAResourceRecoveryRegistry.class })
|
||||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||||
|
@EnableConfigurationProperties(JtaProperties.class)
|
||||||
public class NarayanaJtaConfiguration {
|
public class NarayanaJtaConfiguration {
|
||||||
|
|
||||||
private final JtaProperties jtaProperties;
|
private final JtaProperties jtaProperties;
|
||||||
|
|
@ -116,7 +119,10 @@ public class NarayanaJtaConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
public JtaTransactionManager transactionManager(UserTransaction userTransaction,
|
public JtaTransactionManager transactionManager(UserTransaction userTransaction,
|
||||||
TransactionManager transactionManager) {
|
TransactionManager transactionManager) {
|
||||||
return new JtaTransactionManager(userTransaction, transactionManager);
|
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(
|
||||||
|
userTransaction, transactionManager);
|
||||||
|
this.jtaProperties.getTransaction().applyTo(jtaTransactionManager);
|
||||||
|
return jtaTransactionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,8 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.jdbc.BadSqlGrammarException;
|
import org.springframework.jdbc.BadSqlGrammarException;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||||
|
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
@ -68,6 +70,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Vedran Pavic
|
* @author Vedran Pavic
|
||||||
|
* @author Kazuki Shimizu
|
||||||
*/
|
*/
|
||||||
public class BatchAutoConfigurationTests {
|
public class BatchAutoConfigurationTests {
|
||||||
|
|
||||||
|
|
@ -267,6 +270,43 @@ public class BatchAutoConfigurationTests {
|
||||||
.queryForList("select * from BATCH_JOB_EXECUTION");
|
.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
|
@Configuration
|
||||||
protected static class EmptyConfiguration {
|
protected static class EmptyConfiguration {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
|
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
|
||||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
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.data.neo4j.web.support.OpenSessionInViewInterceptor;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
|
||||||
|
|
@ -53,6 +54,7 @@ import static org.mockito.Mockito.verify;
|
||||||
* @author Michael Hunger
|
* @author Michael Hunger
|
||||||
* @author Vince Bickers
|
* @author Vince Bickers
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Kazuki Shimizu
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class Neo4jDataAutoConfigurationTests {
|
public class Neo4jDataAutoConfigurationTests {
|
||||||
|
|
@ -73,10 +75,21 @@ public class Neo4jDataAutoConfigurationTests {
|
||||||
.hasSize(1);
|
.hasSize(1);
|
||||||
assertThat(this.context.getBeansOfType(SessionFactory.class)).hasSize(1);
|
assertThat(this.context.getBeansOfType(SessionFactory.class)).hasSize(1);
|
||||||
assertThat(this.context.getBeansOfType(Neo4jOperations.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))
|
assertThat(this.context.getBeansOfType(OpenSessionInViewInterceptor.class))
|
||||||
.isEmpty();
|
.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
|
@Test
|
||||||
public void customSessionFactory() {
|
public void customSessionFactory() {
|
||||||
load(CustomSessionFactory.class);
|
load(CustomSessionFactory.class);
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* @author Christian Dupuis
|
* @author Christian Dupuis
|
||||||
* @author Christoph Strobl
|
* @author Christoph Strobl
|
||||||
* @author Eddú Meléndez
|
* @author Eddú Meléndez
|
||||||
|
* @author Marco Aust
|
||||||
*/
|
*/
|
||||||
public class RedisAutoConfigurationTests {
|
public class RedisAutoConfigurationTests {
|
||||||
|
|
||||||
|
|
@ -75,6 +76,21 @@ public class RedisAutoConfigurationTests {
|
||||||
.isEqualTo(1);
|
.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
|
@Test
|
||||||
public void testRedisConfigurationWithPool() throws Exception {
|
public void testRedisConfigurationWithPool() throws Exception {
|
||||||
load("spring.redis.host:foo", "spring.redis.pool.max-idle:1");
|
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.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
@ -106,6 +107,21 @@ public class DataSourceTransactionManagerAutoConfigurationTests {
|
||||||
.isNotNull();
|
.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
|
@EnableTransactionManagement
|
||||||
protected static class SwitchTransactionsOn {
|
protected static class SwitchTransactionsOn {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,13 +60,16 @@ public class KafkaAutoConfigurationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void consumerProperties() {
|
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.key-password=p1",
|
||||||
"spring.kafka.ssl.keystore-location=classpath:ksLoc",
|
"spring.kafka.ssl.keystore-location=classpath:ksLoc",
|
||||||
"spring.kafka.ssl.keystore-password=p2",
|
"spring.kafka.ssl.keystore-password=p2",
|
||||||
"spring.kafka.ssl.truststore-location=classpath:tsLoc",
|
"spring.kafka.ssl.truststore-location=classpath:tsLoc",
|
||||||
"spring.kafka.ssl.truststore-password=p3",
|
"spring.kafka.ssl.truststore-password=p3",
|
||||||
"spring.kafka.consumer.auto-commit-interval=123",
|
"spring.kafka.consumer.auto-commit-interval=123",
|
||||||
|
"spring.kafka.consumer.max-poll-records=42",
|
||||||
"spring.kafka.consumer.auto-offset-reset=earliest",
|
"spring.kafka.consumer.auto-offset-reset=earliest",
|
||||||
"spring.kafka.consumer.client-id=ccid", // test override common
|
"spring.kafka.consumer.client-id=ccid", // test override common
|
||||||
"spring.kafka.consumer.enable-auto-commit=false",
|
"spring.kafka.consumer.enable-auto-commit=false",
|
||||||
|
|
@ -109,6 +112,10 @@ public class KafkaAutoConfigurationTests {
|
||||||
.isEqualTo(LongDeserializer.class);
|
.isEqualTo(LongDeserializer.class);
|
||||||
assertThat(configs.get(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG))
|
assertThat(configs.get(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG))
|
||||||
.isEqualTo(IntegerDeserializer.class);
|
.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
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -81,20 +81,24 @@ public class AutoConfigurationReportLoggingInitializerTests {
|
||||||
|
|
||||||
given(this.log.isDebugEnabled()).willReturn(debug);
|
given(this.log.isDebugEnabled()).willReturn(debug);
|
||||||
willAnswer(new Answer<Object>() {
|
willAnswer(new Answer<Object>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||||
return AutoConfigurationReportLoggingInitializerTests.this.debugLog
|
return AutoConfigurationReportLoggingInitializerTests.this.debugLog
|
||||||
.add(String.valueOf(invocation.getArguments()[0]));
|
.add(String.valueOf(invocation.getArguments()[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
}).given(this.log).debug(anyObject());
|
}).given(this.log).debug(anyObject());
|
||||||
|
|
||||||
given(this.log.isInfoEnabled()).willReturn(info);
|
given(this.log.isInfoEnabled()).willReturn(info);
|
||||||
willAnswer(new Answer<Object>() {
|
willAnswer(new Answer<Object>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||||
return AutoConfigurationReportLoggingInitializerTests.this.infoLog
|
return AutoConfigurationReportLoggingInitializerTests.this.infoLog
|
||||||
.add(String.valueOf(invocation.getArguments()[0]));
|
.add(String.valueOf(invocation.getArguments()[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
}).given(this.log).info(anyObject());
|
}).given(this.log).info(anyObject());
|
||||||
|
|
||||||
LogFactory.releaseAll();
|
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.orm.jpa.hibernate.SpringJtaPlatform;
|
||||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
@ -48,6 +49,7 @@ import static org.mockito.Mockito.mock;
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Kazuki Shimizu
|
||||||
*/
|
*/
|
||||||
public class HibernateJpaAutoConfigurationTests
|
public class HibernateJpaAutoConfigurationTests
|
||||||
extends AbstractJpaAutoConfigurationTests {
|
extends AbstractJpaAutoConfigurationTests {
|
||||||
|
|
@ -134,6 +136,19 @@ public class HibernateJpaAutoConfigurationTests
|
||||||
.isEqualTo(TestJtaPlatform.class.getName());
|
.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 {
|
public static class TestJtaPlatform implements JtaPlatform {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.aop.support.AopUtils;
|
import org.springframework.aop.support.AopUtils;
|
||||||
|
|
@ -196,8 +195,8 @@ public class OAuth2AutoConfigurationTests {
|
||||||
"security.oauth2.client.clientId=client",
|
"security.oauth2.client.clientId=client",
|
||||||
"security.oauth2.client.grantType=client_credentials");
|
"security.oauth2.client.grantType=client_credentials");
|
||||||
this.context.refresh();
|
this.context.refresh();
|
||||||
assertThat(this.context.getBean(OAuth2ClientContext.class).getAccessTokenRequest())
|
OAuth2ClientContext bean = this.context.getBean(OAuth2ClientContext.class);
|
||||||
.isNotNull();
|
assertThat(bean.getAccessTokenRequest()).isNotNull();
|
||||||
assertThat(countBeans(ClientCredentialsResourceDetails.class)).isEqualTo(1);
|
assertThat(countBeans(ClientCredentialsResourceDetails.class)).isEqualTo(1);
|
||||||
assertThat(countBeans(OAuth2ClientContext.class)).isEqualTo(1);
|
assertThat(countBeans(OAuth2ClientContext.class)).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
@ -211,17 +210,15 @@ public class OAuth2AutoConfigurationTests {
|
||||||
"security.oauth2.client.clientId=client",
|
"security.oauth2.client.clientId=client",
|
||||||
"security.oauth2.client.grantType=client_credentials");
|
"security.oauth2.client.grantType=client_credentials");
|
||||||
this.context.refresh();
|
this.context.refresh();
|
||||||
// Thr primary context is fine (not session scoped):
|
// The primary context is fine (not session scoped):
|
||||||
assertThat(this.context.getBean(OAuth2ClientContext.class).getAccessTokenRequest())
|
OAuth2ClientContext bean = this.context.getBean(OAuth2ClientContext.class);
|
||||||
.isNotNull();
|
assertThat(bean.getAccessTokenRequest()).isNotNull();
|
||||||
assertThat(countBeans(ClientCredentialsResourceDetails.class)).isEqualTo(1);
|
assertThat(countBeans(ClientCredentialsResourceDetails.class)).isEqualTo(1);
|
||||||
/*
|
// Kind of a bug (should ideally be 1), but the cause is in Spring OAuth2 (there
|
||||||
* 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
|
||||||
* 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,
|
||||||
* 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
|
||||||
* it will still just about work (because of the @Primary annotation on the
|
// Boot-created instance of OAuth2ClientContext).
|
||||||
* Boot-created instance of OAuth2ClientContext).
|
|
||||||
*/
|
|
||||||
assertThat(countBeans(OAuth2ClientContext.class)).isEqualTo(2);
|
assertThat(countBeans(OAuth2ClientContext.class)).isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ import static org.mockito.Mockito.mock;
|
||||||
* @author Josh Long
|
* @author Josh Long
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Kazuki Shimizu
|
||||||
*/
|
*/
|
||||||
public class JtaAutoConfigurationTests {
|
public class JtaAutoConfigurationTests {
|
||||||
|
|
||||||
|
|
@ -245,6 +246,34 @@ public class JtaAutoConfigurationTests {
|
||||||
assertThat(dataSource.getMaxPoolSize()).isEqualTo(10);
|
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
|
@Configuration
|
||||||
@EnableConfigurationProperties(JtaProperties.class)
|
@EnableConfigurationProperties(JtaProperties.class)
|
||||||
public static class JtaPropertiesConfiguration {
|
public static class JtaPropertiesConfiguration {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,9 @@ import java.util.jar.Attributes;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.jar.Manifest;
|
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.boot.devtools.settings.DevToolsSettings;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
|
@ -41,6 +44,8 @@ import org.springframework.util.StringUtils;
|
||||||
*/
|
*/
|
||||||
final class ChangeableUrls implements Iterable<URL> {
|
final class ChangeableUrls implements Iterable<URL> {
|
||||||
|
|
||||||
|
private static final Log logger = LogFactory.getLog(ChangeableUrls.class);
|
||||||
|
|
||||||
private final List<URL> urls;
|
private final List<URL> urls;
|
||||||
|
|
||||||
private ChangeableUrls(URL... urls) {
|
private ChangeableUrls(URL... urls) {
|
||||||
|
|
@ -52,6 +57,9 @@ final class ChangeableUrls implements Iterable<URL> {
|
||||||
reloadableUrls.add(url);
|
reloadableUrls.add(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Matching URLs for reloading : " + reloadableUrls);
|
||||||
|
}
|
||||||
this.urls = Collections.unmodifiableList(reloadableUrls);
|
this.urls = Collections.unmodifiableList(reloadableUrls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,9 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Pattern;
|
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.UrlResource;
|
||||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
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";
|
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 static DevToolsSettings settings;
|
||||||
|
|
||||||
private final List<Pattern> restartIncludePatterns = new ArrayList<Pattern>();
|
private final List<Pattern> restartIncludePatterns = new ArrayList<Pattern>();
|
||||||
|
|
@ -105,6 +110,12 @@ public class DevToolsSettings {
|
||||||
settings.add(PropertiesLoaderUtils
|
settings.add(PropertiesLoaderUtils
|
||||||
.loadProperties(new UrlResource(urls.nextElement())));
|
.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;
|
return settings;
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
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.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.password= # Login password of the server.
|
||||||
spring.data.neo4j.repositories.enabled=true # Enable Neo4j repositories.
|
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.uri= # URI used by the driver. Auto-detected by default.
|
||||||
spring.data.neo4j.username= # Login user of the server.
|
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.separator=; # Statement separator in SQL initialization scripts.
|
||||||
spring.datasource.sql-script-encoding= # SQL scripts encoding.
|
spring.datasource.sql-script-encoding= # SQL scripts encoding.
|
||||||
spring.datasource.tomcat.*= # Tomcat datasource specific settings
|
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.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.url= # JDBC url of the database.
|
||||||
spring.datasource.username=
|
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.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.properties.*= # Additional native properties to set on the JPA provider.
|
||||||
spring.jpa.show-sql=false # Enable logging of SQL statements.
|
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])
|
# JTA ({sc-spring-boot-autoconfigure}/transaction/jta/JtaAutoConfiguration.{sc-ext}[JtaAutoConfiguration])
|
||||||
spring.jta.enabled=true # Enable JTA support.
|
spring.jta.enabled=true # Enable JTA support.
|
||||||
spring.jta.log-dir= # Transaction logs directory.
|
spring.jta.log-dir= # Transaction logs directory.
|
||||||
|
spring.jta.transaction.*= # Transaction manager settings
|
||||||
spring.jta.transaction-manager-id= # Transaction manager unique identifier.
|
spring.jta.transaction-manager-id= # Transaction manager unique identifier.
|
||||||
|
|
||||||
# ATOMIKOS ({sc-spring-boot}/jta/atomikos/AtomikosProperties.{sc-ext}[AtomikosProperties])
|
# 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.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.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.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.host=localhost # Redis server host.
|
||||||
spring.redis.password= # Login password of the redis server.
|
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-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-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.
|
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.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.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.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])
|
# 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.
|
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.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.heartbeat-interval= # Expected time in milliseconds between heartbeats to the consumer coordinator.
|
||||||
spring.kafka.consumer.key-deserializer= # Deserializer class for keys.
|
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.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-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.
|
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.key-serializer= # Serializer class for keys.
|
||||||
spring.kafka.producer.retries= # When greater than zero, enables retrying of failed sends.
|
spring.kafka.producer.retries= # When greater than zero, enables retrying of failed sends.
|
||||||
spring.kafka.producer.value-serializer= # Serializer class for values.
|
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.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-location= # Location of the key store file.
|
||||||
spring.kafka.ssl.keystore-password= # Store password for 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`
|
|`useStartStopDaemon`
|
||||||
|If the `start-stop-daemon` command, when it's available, should be used to control the
|
|If the `start-stop-daemon` command, when it's available, should be used to control the
|
||||||
process. Defaults to `true`.
|
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`
|
|`DEBUG`
|
||||||
|if not empty will set the `-x` flag on the shell process, making it easy to see the logic
|
|if not empty will set the `-x` flag on the shell process, making it easy to see the logic
|
||||||
in the script.
|
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
|
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.
|
and any that do not have a default value.
|
||||||
|
|
||||||
Only a subset of the properties supported by Kafka are available via the `KafkaProperties`
|
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
|
class. If you wish to configure the producer or consumer with additional properties that
|
||||||
can override the producer factory and/or consumer factory bean, adding additional
|
are not directly supported, use the following:
|
||||||
properties, for example:
|
|
||||||
|
[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]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
@Bean
|
include::{code-examples}/kafka/KafkaSpecialProducerConsumerConfigExample.java[tag=configuration]
|
||||||
public ProducerFactory<?, ?> kafkaProducerFactory(KafkaProperties properties) {
|
|
||||||
Map<String, Object> producerProperties = properties.buildProducerProperties();
|
|
||||||
producerProperties.put("some.property", "some.value");
|
|
||||||
return new DefaultKafkaProducerFactory<Object, Object>(producerProperties);
|
|
||||||
}
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
# Initialize log file name if not provided by the config file
|
||||||
[[ -z "$LOG_FILENAME" ]] && LOG_FILENAME="{{logFilename:${identity}.log}}"
|
[[ -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
|
# ANSI Colors
|
||||||
echoRed() { echo $'\e[0;31m'"$1"$'\e[0m'; }
|
echoRed() { echo $'\e[0;31m'"$1"$'\e[0m'; }
|
||||||
echoGreen() { echo $'\e[0;32m'"$1"$'\e[0m'; }
|
echoGreen() { echo $'\e[0;32m'"$1"$'\e[0m'; }
|
||||||
|
|
@ -191,9 +194,9 @@ stop() {
|
||||||
|
|
||||||
do_stop() {
|
do_stop() {
|
||||||
kill "$1" &> /dev/null || { echoRed "Unable to kill process $1"; return 1; }
|
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; }
|
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
|
sleep 1
|
||||||
done
|
done
|
||||||
echoRed "Unable to kill process $1";
|
echoRed "Unable to kill process $1";
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,11 @@ public class DefaultLaunchScriptTests {
|
||||||
assertThatPlaceholderCanBeReplaced("confFolder");
|
assertThatPlaceholderCanBeReplaced("confFolder");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void stopWaitTimeCanBeReplaced() throws Exception {
|
||||||
|
assertThatPlaceholderCanBeReplaced("stopWaitTime");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defaultForUseStartStopDaemonIsTrue() throws Exception {
|
public void defaultForUseStartStopDaemonIsTrue() throws Exception {
|
||||||
DefaultLaunchScript script = new DefaultLaunchScript(null, null);
|
DefaultLaunchScript script = new DefaultLaunchScript(null, null);
|
||||||
|
|
@ -125,6 +130,13 @@ public class DefaultLaunchScriptTests {
|
||||||
assertThat(content).contains("MODE=\"auto\"");
|
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
|
@Test
|
||||||
public void loadFromFile() throws Exception {
|
public void loadFromFile() throws Exception {
|
||||||
File file = this.temporaryFolder.newFile();
|
File file = this.temporaryFolder.newFile();
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ import org.springframework.util.Assert;
|
||||||
*/
|
*/
|
||||||
public class ImageBanner implements Banner {
|
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 };
|
private static final double[] RGB_WEIGHT = { 0.2126d, 0.7152d, 0.0722d };
|
||||||
|
|
||||||
|
|
@ -76,9 +76,9 @@ public class ImageBanner implements Banner {
|
||||||
printBanner(environment, out);
|
printBanner(environment, out);
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
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() + "')");
|
+ ": '" + ex.getMessage() + "')");
|
||||||
log.debug("Image banner printing failure", ex);
|
logger.debug("Image banner printing failure", ex);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (headless == null) {
|
if (headless == null) {
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,8 @@ public class PropertiesConfigurationFactory<T>
|
||||||
|
|
||||||
private static final char[] TARGET_NAME_DELIMITERS = { '_', '.' };
|
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;
|
private boolean ignoreUnknownFields = true;
|
||||||
|
|
||||||
|
|
@ -228,8 +229,8 @@ public class PropertiesConfigurationFactory<T>
|
||||||
public void bindPropertiesToTarget() throws BindException {
|
public void bindPropertiesToTarget() throws BindException {
|
||||||
Assert.state(this.propertySources != null, "PropertySources should not be null");
|
Assert.state(this.propertySources != null, "PropertySources should not be null");
|
||||||
try {
|
try {
|
||||||
if (this.logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
this.logger.trace("Property Sources: " + this.propertySources);
|
logger.trace("Property Sources: " + this.propertySources);
|
||||||
|
|
||||||
}
|
}
|
||||||
this.hasBeenBound = true;
|
this.hasBeenBound = true;
|
||||||
|
|
@ -239,8 +240,9 @@ public class PropertiesConfigurationFactory<T>
|
||||||
if (this.exceptionIfInvalid) {
|
if (this.exceptionIfInvalid) {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
this.logger.error("Failed to load Properties validation bean. "
|
PropertiesConfigurationFactory.logger
|
||||||
+ "Your Properties may be invalid.", ex);
|
.error("Failed to load Properties validation bean. "
|
||||||
|
+ "Your Properties may be invalid.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,10 +342,10 @@ public class PropertiesConfigurationFactory<T>
|
||||||
dataBinder.validate();
|
dataBinder.validate();
|
||||||
BindingResult errors = dataBinder.getBindingResult();
|
BindingResult errors = dataBinder.getBindingResult();
|
||||||
if (errors.hasErrors()) {
|
if (errors.hasErrors()) {
|
||||||
this.logger.error("Properties configuration failed validation");
|
logger.error("Properties configuration failed validation");
|
||||||
for (ObjectError error : errors.getAllErrors()) {
|
for (ObjectError error : errors.getAllErrors()) {
|
||||||
this.logger
|
logger.error(
|
||||||
.error(this.messageSource != null
|
this.messageSource != null
|
||||||
? this.messageSource.getMessage(error,
|
? this.messageSource.getMessage(error,
|
||||||
Locale.getDefault()) + " (" + error + ")"
|
Locale.getDefault()) + " (" + error + ")"
|
||||||
: error);
|
: error);
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ import org.springframework.validation.Validator;
|
||||||
public class YamlConfigurationFactory<T>
|
public class YamlConfigurationFactory<T>
|
||||||
implements FactoryBean<T>, MessageSourceAware, InitializingBean {
|
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;
|
private final Class<?> type;
|
||||||
|
|
||||||
|
|
@ -137,8 +137,8 @@ public class YamlConfigurationFactory<T>
|
||||||
Assert.state(this.yaml != null, "Yaml document should not be null: "
|
Assert.state(this.yaml != null, "Yaml document should not be null: "
|
||||||
+ "either set it directly or set the resource to load it from");
|
+ "either set it directly or set the resource to load it from");
|
||||||
try {
|
try {
|
||||||
if (this.logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
this.logger.trace(String.format("Yaml document is %n%s", this.yaml));
|
logger.trace(String.format("Yaml document is %n%s", this.yaml));
|
||||||
}
|
}
|
||||||
Constructor constructor = new YamlJavaBeanPropertyConstructor(this.type,
|
Constructor constructor = new YamlJavaBeanPropertyConstructor(this.type,
|
||||||
this.propertyAliases);
|
this.propertyAliases);
|
||||||
|
|
@ -151,7 +151,7 @@ public class YamlConfigurationFactory<T>
|
||||||
if (this.exceptionIfInvalid) {
|
if (this.exceptionIfInvalid) {
|
||||||
throw ex;
|
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);
|
+ "Your YAML file may be invalid.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,13 +161,9 @@ public class YamlConfigurationFactory<T>
|
||||||
"configuration");
|
"configuration");
|
||||||
this.validator.validate(this.configuration, errors);
|
this.validator.validate(this.configuration, errors);
|
||||||
if (errors.hasErrors()) {
|
if (errors.hasErrors()) {
|
||||||
this.logger.error("YAML configuration failed validation");
|
logger.error("YAML configuration failed validation");
|
||||||
for (ObjectError error : errors.getAllErrors()) {
|
for (ObjectError error : errors.getAllErrors()) {
|
||||||
this.logger
|
logger.error(getErrorMessage(error));
|
||||||
.error(this.messageSource != null
|
|
||||||
? this.messageSource.getMessage(error,
|
|
||||||
Locale.getDefault()) + " (" + error + ")"
|
|
||||||
: error);
|
|
||||||
}
|
}
|
||||||
if (this.exceptionIfInvalid) {
|
if (this.exceptionIfInvalid) {
|
||||||
BindException summary = new BindException(errors);
|
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
|
@Override
|
||||||
public Class<?> getObjectType() {
|
public Class<?> getObjectType() {
|
||||||
if (this.configuration == null) {
|
if (this.configuration == null) {
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ import org.springframework.util.ReflectionUtils;
|
||||||
*/
|
*/
|
||||||
public final class FailureAnalyzers {
|
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;
|
private final ClassLoader classLoader;
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ public final class FailureAnalyzers {
|
||||||
analyzers.add((FailureAnalyzer) constructor.newInstance());
|
analyzers.add((FailureAnalyzer) constructor.newInstance());
|
||||||
}
|
}
|
||||||
catch (Throwable ex) {
|
catch (Throwable ex) {
|
||||||
log.trace("Failed to load " + analyzerName, ex);
|
logger.trace("Failed to load " + analyzerName, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnnotationAwareOrderComparator.sort(analyzers);
|
AnnotationAwareOrderComparator.sort(analyzers);
|
||||||
|
|
|
||||||
|
|
@ -42,17 +42,17 @@ public final class ClasspathLoggingApplicationListener
|
||||||
|
|
||||||
private static final int ORDER = LoggingApplicationListener.DEFAULT_ORDER + 1;
|
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
|
@Override
|
||||||
public void onApplicationEvent(ApplicationEvent event) {
|
public void onApplicationEvent(ApplicationEvent event) {
|
||||||
if (this.logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
if (event instanceof ApplicationEnvironmentPreparedEvent) {
|
if (event instanceof ApplicationEnvironmentPreparedEvent) {
|
||||||
this.logger
|
logger.debug("Application started with classpath: " + getClasspath());
|
||||||
.debug("Application started with classpath: " + getClasspath());
|
|
||||||
}
|
}
|
||||||
else if (event instanceof ApplicationFailedEvent) {
|
else if (event instanceof ApplicationFailedEvent) {
|
||||||
this.logger.debug(
|
logger.debug(
|
||||||
"Application failed to start with classpath: " + getClasspath());
|
"Application failed to start with classpath: " + getClasspath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue