summaryrefslogtreecommitdiff
path: root/spring-context
diff options
context:
space:
mode:
authorEmmanuel Bourg <ebourg@apache.org>2017-07-04 11:41:53 +0200
committerEmmanuel Bourg <ebourg@apache.org>2017-07-04 11:41:53 +0200
commit16cac1f52d8e8159e0e688b2fda3f89291cec969 (patch)
tree027fd3c0b671bf73a45f27af2a16881c4098f7e7 /spring-context
parent5b251f9ca7596793d669a9a36eb0d83ccd56f983 (diff)
New upstream version 4.3.9
Diffstat (limited to 'spring-context')
-rw-r--r--spring-context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java15
-rw-r--r--spring-context/src/main/java/org/springframework/context/EnvironmentAware.java5
-rw-r--r--spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java53
-rw-r--r--spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java2
-rw-r--r--spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java28
-rw-r--r--spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java4
-rw-r--r--spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java23
-rw-r--r--spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java38
-rw-r--r--spring-context/src/test/java/org/springframework/validation/beanvalidation/SpringValidatorAdapterTests.java12
-rw-r--r--spring-context/src/test/java/org/springframework/validation/beanvalidation/ValidatorFactoryTests.java66
10 files changed, 194 insertions, 52 deletions
diff --git a/spring-context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java b/spring-context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java
index 2a029280..1f6ecc41 100644
--- a/spring-context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java
+++ b/spring-context/src/main/java/org/springframework/context/ConfigurableApplicationContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2017 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.
@@ -103,18 +103,19 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
void setParent(ApplicationContext parent);
/**
- * Return the Environment for this application context in configurable form.
+ * Set the {@code Environment} for this application context.
+ * @param environment the new environment
* @since 3.1
*/
- @Override
- ConfigurableEnvironment getEnvironment();
+ void setEnvironment(ConfigurableEnvironment environment);
/**
- * Set the {@code Environment} for this application context.
- * @param environment the new environment
+ * Return the {@code Environment} for this application context in configurable
+ * form, allowing for further customization.
* @since 3.1
*/
- void setEnvironment(ConfigurableEnvironment environment);
+ @Override
+ ConfigurableEnvironment getEnvironment();
/**
* Add a new BeanFactoryPostProcessor that will get applied to the internal
diff --git a/spring-context/src/main/java/org/springframework/context/EnvironmentAware.java b/spring-context/src/main/java/org/springframework/context/EnvironmentAware.java
index 0d943429..7a7640ed 100644
--- a/spring-context/src/main/java/org/springframework/context/EnvironmentAware.java
+++ b/spring-context/src/main/java/org/springframework/context/EnvironmentAware.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2011 the original author or authors.
+ * Copyright 2002-2017 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.
@@ -25,11 +25,12 @@ import org.springframework.core.env.Environment;
*
* @author Chris Beams
* @since 3.1
+ * @see org.springframework.core.env.EnvironmentCapable
*/
public interface EnvironmentAware extends Aware {
/**
- * Set the {@code Environment} that this object runs in.
+ * Set the {@code Environment} that this component runs in.
*/
void setEnvironment(Environment environment);
diff --git a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
index cabf3800..6791f436 100644
--- a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
+++ b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2017 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.
@@ -281,8 +281,22 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
/**
- * {@inheritDoc}
- * <p>If {@code null}, a new environment will be initialized via
+ * Set the {@code Environment} for this application context.
+ * <p>Default value is determined by {@link #createEnvironment()}. Replacing the
+ * default with this method is one option but configuration through {@link
+ * #getEnvironment()} should also be considered. In either case, such modifications
+ * should be performed <em>before</em> {@link #refresh()}.
+ * @see org.springframework.context.support.AbstractApplicationContext#createEnvironment
+ */
+ @Override
+ public void setEnvironment(ConfigurableEnvironment environment) {
+ this.environment = environment;
+ }
+
+ /**
+ * Return the {@code Environment} for this application context in configurable
+ * form, allowing for further customization.
+ * <p>If none specified, a default environment will be initialized via
* {@link #createEnvironment()}.
*/
@Override
@@ -294,16 +308,12 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
}
/**
- * {@inheritDoc}
- * <p>Default value is determined by {@link #createEnvironment()}. Replacing the
- * default with this method is one option but configuration through {@link
- * #getEnvironment()} should also be considered. In either case, such modifications
- * should be performed <em>before</em> {@link #refresh()}.
- * @see org.springframework.context.support.AbstractApplicationContext#createEnvironment
+ * Create and return a new {@link StandardEnvironment}.
+ * <p>Subclasses may override this method in order to supply
+ * a custom {@link ConfigurableEnvironment} implementation.
*/
- @Override
- public void setEnvironment(ConfigurableEnvironment environment) {
- this.environment = environment;
+ protected ConfigurableEnvironment createEnvironment() {
+ return new StandardEnvironment();
}
/**
@@ -444,7 +454,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
//---------------------------------------------------------------------
/**
- * {@inheritDoc}
+ * Set the parent of this application context.
* <p>The parent {@linkplain ApplicationContext#getEnvironment() environment} is
* {@linkplain ConfigurableEnvironment#merge(ConfigurableEnvironment) merged} with
* this (child) application context environment if the parent is non-{@code null} and
@@ -495,15 +505,6 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
return this.applicationListeners;
}
- /**
- * Create and return a new {@link StandardEnvironment}.
- * <p>Subclasses may override this method in order to supply
- * a custom {@link ConfigurableEnvironment} implementation.
- */
- protected ConfigurableEnvironment createEnvironment() {
- return new StandardEnvironment();
- }
-
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
@@ -935,13 +936,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
/**
* DisposableBean callback for destruction of this instance.
- * Only called when the ApplicationContext itself is running
- * as a bean in another BeanFactory or ApplicationContext,
- * which is rather unusual.
- * <p>The {@code close} method is the native way to
- * shut down an ApplicationContext.
+ * <p>The {@link #close()} method is the native way to shut down
+ * an ApplicationContext, which this method simply delegates to.
* @see #close()
- * @see org.springframework.beans.factory.access.SingletonBeanFactoryLocator
*/
@Override
public void destroy() {
diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
index fcf17665..77de2543 100644
--- a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
+++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
@@ -221,6 +221,7 @@ public class ScheduledAnnotationBeanPostProcessor
this.registrar.setTaskScheduler(resolveSchedulerBean(TaskScheduler.class, false));
}
catch (NoUniqueBeanDefinitionException ex) {
+ logger.debug("Could not find unique TaskScheduler bean", ex);
try {
this.registrar.setTaskScheduler(resolveSchedulerBean(TaskScheduler.class, true));
}
@@ -241,6 +242,7 @@ public class ScheduledAnnotationBeanPostProcessor
this.registrar.setScheduler(resolveSchedulerBean(ScheduledExecutorService.class, false));
}
catch (NoUniqueBeanDefinitionException ex2) {
+ logger.debug("Could not find unique ScheduledExecutorService bean", ex2);
try {
this.registrar.setScheduler(resolveSchedulerBean(ScheduledExecutorService.class, true));
}
diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java
index 33d53bf9..97006cf4 100644
--- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java
+++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2017 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.
@@ -31,6 +31,7 @@ import javax.validation.ConstraintValidatorFactory;
import javax.validation.MessageInterpolator;
import javax.validation.TraversableResolver;
import javax.validation.Validation;
+import javax.validation.ValidationException;
import javax.validation.ValidationProviderResolver;
import javax.validation.Validator;
import javax.validation.ValidatorContext;
@@ -74,6 +75,7 @@ import org.springframework.util.ReflectionUtils;
* instead. If you really need programmatic {@code #forExecutables} access, inject this class as
* a {@link ValidatorFactory} and call {@link #getValidator()} on it, then {@code #forExecutables}
* on the returned native {@link Validator} reference instead of directly on this class.
+ * Alternatively, call {@code #unwrap(Validator.class) which will also provide the native object.
*
* <p>This class is also being used by Spring's MVC configuration namespace, in case of the
* {@code javax.validation} API being present but no explicit Validator having been configured.
@@ -397,6 +399,30 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
return this.validatorFactory.getConstraintValidatorFactory();
}
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T unwrap(Class<T> type) {
+ if (type == null || !ValidatorFactory.class.isAssignableFrom(type)) {
+ try {
+ return super.unwrap(type);
+ }
+ catch (ValidationException ex) {
+ // ignore - we'll try ValidatorFactory unwrapping next
+ }
+ }
+ try {
+ return this.validatorFactory.unwrap(type);
+ }
+ catch (ValidationException ex) {
+ // ignore if just being asked for ValidatorFactory
+ if (ValidatorFactory.class == type) {
+ return (T) this.validatorFactory;
+ }
+ throw ex;
+ }
+ }
+
+
public void close() {
if (closeMethod != null && this.validatorFactory != null) {
ReflectionUtils.invokeMethod(closeMethod, this.validatorFactory);
diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java
index a2972a13..e1d4eff5 100644
--- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java
+++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.java
@@ -85,9 +85,13 @@ public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvis
* <p>Default is the default ValidatorFactory's default Validator.
*/
public void setValidator(Validator validator) {
+ // Unwrap to the native Validator with forExecutables support
if (validator instanceof LocalValidatorFactoryBean) {
this.validator = ((LocalValidatorFactoryBean) validator).getValidator();
}
+ else if (validator instanceof SpringValidatorAdapter) {
+ this.validator = validator.unwrap(Validator.class);
+ }
else {
this.validator = validator;
}
diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java
index a2a2125a..3614dfe0 100644
--- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java
+++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java
@@ -25,6 +25,8 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.validation.ConstraintViolation;
+import javax.validation.ValidationException;
+import javax.validation.Validator;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstraintDescriptor;
@@ -39,13 +41,19 @@ import org.springframework.validation.ObjectError;
import org.springframework.validation.SmartValidator;
/**
- * Adapter that takes a JSR-303 {@code javax.validator.Validator}
- * and exposes it as a Spring {@link org.springframework.validation.Validator}
+ * Adapter that takes a JSR-303 {@code javax.validator.Validator} and
+ * exposes it as a Spring {@link org.springframework.validation.Validator}
* while also exposing the original JSR-303 Validator interface itself.
*
* <p>Can be used as a programmatic wrapper. Also serves as base class for
* {@link CustomValidatorBean} and {@link LocalValidatorFactoryBean}.
*
+ * <p>Note that Bean Validation 1.1's {@code #forExecutables} method isn't supported
+ * on this adapter: We do not expect that method to be called by application code;
+ * consider {@link MethodValidationInterceptor} instead. If you really need programmatic
+ * {@code #forExecutables} access, call {@code #unwrap(Validator.class) which will
+ * provide the native {@link Validator} object with {@code #forExecutables} support.
+ *
* @author Juergen Hoeller
* @since 3.0
*/
@@ -297,7 +305,16 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> type) {
Assert.state(this.targetValidator != null, "No target Validator set");
- return (type != null ? this.targetValidator.unwrap(type) : (T) this.targetValidator);
+ try {
+ return (type != null ? this.targetValidator.unwrap(type) : (T) this.targetValidator);
+ }
+ catch (ValidationException ex) {
+ // ignore if just being asked for plain Validator
+ if (javax.validation.Validator.class == type) {
+ return (T) this.targetValidator;
+ }
+ throw ex;
+ }
}
diff --git a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java
index 3e5cf952..e1106af7 100644
--- a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java
+++ b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java
@@ -23,6 +23,7 @@ import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.junit.Ignore;
@@ -43,6 +44,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.Ordered;
+import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
@@ -181,9 +183,23 @@ public class EnableAsyncTests {
}
@Test
- public void customExecutorIsPropagated() throws InterruptedException {
+ public void customExecutorBean() throws InterruptedException {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
- ctx.register(CustomExecutorAsyncConfig.class);
+ ctx.register(CustomExecutorBean.class);
+ ctx.refresh();
+
+ AsyncBean asyncBean = ctx.getBean(AsyncBean.class);
+ asyncBean.work();
+ Thread.sleep(500);
+ assertThat(asyncBean.getThreadOfExecution().getName(), startsWith("Custom-"));
+
+ ctx.close();
+ }
+
+ @Test
+ public void customExecutorConfig() throws InterruptedException {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.register(CustomExecutorConfig.class);
ctx.refresh();
AsyncBean asyncBean = ctx.getBean(AsyncBean.class);
@@ -382,7 +398,23 @@ public class EnableAsyncTests {
@Configuration
@EnableAsync
- static class CustomExecutorAsyncConfig implements AsyncConfigurer {
+ static class CustomExecutorBean {
+
+ @Bean
+ public AsyncBean asyncBean() {
+ return new AsyncBean();
+ }
+
+ @Bean
+ public Executor taskExecutor() {
+ return Executors.newSingleThreadExecutor(new CustomizableThreadFactory("Custom-"));
+ }
+ }
+
+
+ @Configuration
+ @EnableAsync
+ static class CustomExecutorConfig implements AsyncConfigurer {
@Bean
public AsyncBean asyncBean() {
diff --git a/spring-context/src/test/java/org/springframework/validation/beanvalidation/SpringValidatorAdapterTests.java b/spring-context/src/test/java/org/springframework/validation/beanvalidation/SpringValidatorAdapterTests.java
index de7bc833..307acc59 100644
--- a/spring-context/src/test/java/org/springframework/validation/beanvalidation/SpringValidatorAdapterTests.java
+++ b/spring-context/src/test/java/org/springframework/validation/beanvalidation/SpringValidatorAdapterTests.java
@@ -27,6 +27,7 @@ import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import javax.validation.Validation;
+import javax.validation.Validator;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
@@ -51,8 +52,9 @@ import static org.junit.Assert.*;
*/
public class SpringValidatorAdapterTests {
- private final SpringValidatorAdapter validatorAdapter = new SpringValidatorAdapter(
- Validation.buildDefaultValidatorFactory().getValidator());
+ private final Validator nativeValidator = Validation.buildDefaultValidatorFactory().getValidator();
+
+ private final SpringValidatorAdapter validatorAdapter = new SpringValidatorAdapter(nativeValidator);
private final StaticMessageSource messageSource = new StaticMessageSource();
@@ -66,6 +68,12 @@ public class SpringValidatorAdapterTests {
}
+ @Test
+ public void testUnwrap() {
+ Validator nativeValidator = validatorAdapter.unwrap(Validator.class);
+ assertSame(this.nativeValidator, nativeValidator);
+ }
+
@Test // SPR-13406
public void testNoStringArgumentValue() {
TestBean testBean = new TestBean();
diff --git a/spring-context/src/test/java/org/springframework/validation/beanvalidation/ValidatorFactoryTests.java b/spring-context/src/test/java/org/springframework/validation/beanvalidation/ValidatorFactoryTests.java
index 26138af5..d5a4fb79 100644
--- a/spring-context/src/test/java/org/springframework/validation/beanvalidation/ValidatorFactoryTests.java
+++ b/spring-context/src/test/java/org/springframework/validation/beanvalidation/ValidatorFactoryTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2017 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.
@@ -33,11 +33,18 @@ import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintViolation;
import javax.validation.Payload;
import javax.validation.Valid;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.HibernateValidator;
+import org.hibernate.validator.HibernateValidatorFactory;
import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.core.env.Environment;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
@@ -47,10 +54,9 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
- * Tested against Hibernate Validator 4.3, as of Spring 4.0.
+ * Tests against Hibernate Validator 5.x.
*
* @author Juergen Hoeller
- * @since 3.0
*/
public class ValidatorFactoryTests {
@@ -58,6 +64,7 @@ public class ValidatorFactoryTests {
public void testSimpleValidation() throws Exception {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
+
ValidPerson person = new ValidPerson();
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
assertEquals(2, result.size());
@@ -70,6 +77,12 @@ public class ValidatorFactoryTests {
fail("Invalid constraint violation with path '" + path + "'");
}
}
+
+ Validator nativeValidator = validator.unwrap(Validator.class);
+ assertTrue(nativeValidator.getClass().getName().startsWith("org.hibernate"));
+ assertTrue(validator.unwrap(ValidatorFactory.class) instanceof HibernateValidatorFactory);
+ assertTrue(validator.unwrap(HibernateValidatorFactory.class) instanceof HibernateValidatorFactory);
+
validator.destroy();
}
@@ -78,6 +91,7 @@ public class ValidatorFactoryTests {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setProviderClass(HibernateValidator.class);
validator.afterPropertiesSet();
+
ValidPerson person = new ValidPerson();
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
assertEquals(2, result.size());
@@ -90,6 +104,12 @@ public class ValidatorFactoryTests {
fail("Invalid constraint violation with path '" + path + "'");
}
}
+
+ Validator nativeValidator = validator.unwrap(Validator.class);
+ assertTrue(nativeValidator.getClass().getName().startsWith("org.hibernate"));
+ assertTrue(validator.unwrap(ValidatorFactory.class) instanceof HibernateValidatorFactory);
+ assertTrue(validator.unwrap(HibernateValidatorFactory.class) instanceof HibernateValidatorFactory);
+
validator.destroy();
}
@@ -112,6 +132,7 @@ public class ValidatorFactoryTests {
public void testSpringValidationFieldType() throws Exception {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
+
ValidPerson person = new ValidPerson();
person.setName("Phil");
person.getAddress().setStreet("Phil's Street");
@@ -126,6 +147,7 @@ public class ValidatorFactoryTests {
public void testSpringValidation() throws Exception {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
+
ValidPerson person = new ValidPerson();
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
validator.validate(person, result);
@@ -153,6 +175,7 @@ public class ValidatorFactoryTests {
public void testSpringValidationWithClassLevel() throws Exception {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
+
ValidPerson person = new ValidPerson();
person.setName("Juergen");
person.getAddress().setStreet("Juergen's Street");
@@ -167,9 +190,31 @@ public class ValidatorFactoryTests {
}
@Test
+ public void testSpringValidationWithAutowiredValidator() throws Exception {
+ ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
+ LocalValidatorFactoryBean.class);
+ LocalValidatorFactoryBean validator = ctx.getBean(LocalValidatorFactoryBean.class);
+
+ ValidPerson person = new ValidPerson();
+ person.expectsAutowiredValidator = true;
+ person.setName("Juergen");
+ person.getAddress().setStreet("Juergen's Street");
+ BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
+ validator.validate(person, result);
+ assertEquals(1, result.getErrorCount());
+ ObjectError globalError = result.getGlobalError();
+ List<String> errorCodes = Arrays.asList(globalError.getCodes());
+ assertEquals(2, errorCodes.size());
+ assertTrue(errorCodes.contains("NameAddressValid.person"));
+ assertTrue(errorCodes.contains("NameAddressValid"));
+ ctx.close();
+ }
+
+ @Test
public void testSpringValidationWithErrorInListElement() throws Exception {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
+
ValidPerson person = new ValidPerson();
person.getAddressList().add(new ValidAddress());
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
@@ -187,6 +232,7 @@ public class ValidatorFactoryTests {
public void testSpringValidationWithErrorInSetElement() throws Exception {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
+
ValidPerson person = new ValidPerson();
person.getAddressSet().add(new ValidAddress());
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
@@ -235,10 +281,12 @@ public class ValidatorFactoryTests {
private ValidAddress address = new ValidAddress();
@Valid
- private List<ValidAddress> addressList = new LinkedList<ValidAddress>();
+ private List<ValidAddress> addressList = new LinkedList<>();
@Valid
- private Set<ValidAddress> addressSet = new LinkedHashSet<ValidAddress>();
+ private Set<ValidAddress> addressSet = new LinkedHashSet<>();
+
+ public boolean expectsAutowiredValidator = false;
public String getName() {
return name;
@@ -304,12 +352,18 @@ public class ValidatorFactoryTests {
public static class NameAddressValidator implements ConstraintValidator<NameAddressValid, ValidPerson> {
+ @Autowired
+ private Environment environment;
+
@Override
public void initialize(NameAddressValid constraintAnnotation) {
}
@Override
public boolean isValid(ValidPerson value, ConstraintValidatorContext context) {
+ if (value.expectsAutowiredValidator) {
+ assertNotNull(this.environment);
+ }
boolean valid = (value.name == null || !value.address.street.contains(value.name));
if (!valid && "Phil".equals(value.name)) {
context.buildConstraintViolationWithTemplate(
@@ -378,7 +432,7 @@ public class ValidatorFactoryTests {
public boolean isValid(InnerBean bean, ConstraintValidatorContext context) {
context.disableDefaultConstraintViolation();
if (bean.getValue() == null) {
- context.buildConstraintViolationWithTemplate("NULL"). addNode("value").addConstraintViolation();
+ context.buildConstraintViolationWithTemplate("NULL").addNode("value").addConstraintViolation();
return false;
}
return true;