diff --git a/build.gradle b/build.gradle
index 3b4680b6b02..22b0b937d8c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -16,8 +16,9 @@ configure(allprojects) { project ->
ext.aspectjVersion = "1.7.4"
ext.groovyVersion = "1.8.9"
ext.hibernate3Version = "3.6.10.Final"
- ext.hibernate4Version = "4.2.12.Final"
- ext.hibValVersion = "4.3.1.Final"
+ ext.hibernate4Version = "4.3.5.Final"
+ ext.hibVal4Version = "4.3.1.Final"
+ ext.hibVal5Version = "5.1.0.Final"
ext.hsqldbVersion = "2.3.2"
ext.jackson2Version = "2.3.2"
ext.jasperReportsVersion = "5.5.1"
@@ -367,7 +368,7 @@ project("spring-context") {
optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0")
optional("org.eclipse.persistence:javax.persistence:2.0.0")
optional("javax.validation:validation-api:1.0.0.GA")
- optional("org.hibernate:hibernate-validator:${hibValVersion}")
+ optional("org.hibernate:hibernate-validator:${hibVal4Version}")
optional("joda-time:joda-time:${jodaVersion}")
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
@@ -679,6 +680,10 @@ project("spring-orm-hibernate4") {
optional("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
optional("javax.servlet:javax.servlet-api:3.0.1")
optional("aopalliance:aopalliance:1.0")
+ testCompile("javax.validation:validation-api:1.1.0.GA")
+ testCompile("org.hibernate:hibernate-validator:${hibVal5Version}")
+ testCompile("javax.el:javax.el-api:2.2.4")
+ testCompile("org.glassfish.web:javax.el:2.2.4")
}
}
@@ -744,7 +749,7 @@ project("spring-webmvc") {
exclude group: "javax.servlet", module: "javax.servlet"
}
testCompile("javax.validation:validation-api:1.0.0.GA")
- testCompile("org.hibernate:hibernate-validator:${hibValVersion}")
+ testCompile("org.hibernate:hibernate-validator:${hibVal4Version}")
testCompile("org.apache.httpcomponents:httpclient:4.3.3")
testCompile("commons-fileupload:commons-fileupload:1.3.1")
testCompile("commons-io:commons-io:1.3")
@@ -844,7 +849,7 @@ project("spring-test") {
exclude group: 'org.hibernate.javax.persistence', module: 'hibernate-jpa-2.0-api'
}
testCompile("org.hibernate:hibernate-entitymanager:${hibernate3Version}")
- testCompile("org.hibernate:hibernate-validator:${hibValVersion}")
+ testCompile("org.hibernate:hibernate-validator:${hibVal4Version}")
testCompile("com.thoughtworks.xstream:xstream:${xstreamVersion}")
testCompile("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
testCompile("rome:rome:1.0")
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 b6063f77039..86d0026c4e7 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-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -64,7 +64,7 @@ import org.springframework.util.ReflectionUtils;
* into any target dependency of type {@link org.springframework.validation.Validator}!
*
*
As of Spring 4.0, this class supports Bean Validation 1.0 and 1.1, with special support
- * for Hibernate Validator 4.3 and 5.0 (see {@link #setValidationMessageSource}).
+ * for Hibernate Validator 4.3 and 5.x (see {@link #setValidationMessageSource}).
*
*
Note that Bean Validation 1.1's {@code #forExecutables} method isn't supported: We do not
* expect that method to be called by application code; consider {@link MethodValidationInterceptor}
diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MessageSourceResourceBundleLocator.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MessageSourceResourceBundleLocator.java
index e14ac594fab..a610c34662a 100644
--- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MessageSourceResourceBundleLocator.java
+++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MessageSourceResourceBundleLocator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -26,7 +26,7 @@ import org.springframework.context.support.MessageSourceResourceBundle;
import org.springframework.util.Assert;
/**
- * Implementation of Hibernate Validator 4.3/5.0's {@link ResourceBundleLocator} interface,
+ * Implementation of Hibernate Validator 4.3/5.x's {@link ResourceBundleLocator} interface,
* exposing a Spring {@link MessageSource} as localized {@link MessageSourceResourceBundle}.
*
* @author Juergen Hoeller
diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java
index 319095a16d0..a9ce695e8e8 100644
--- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java
+++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -18,7 +18,6 @@ package org.springframework.validation.beanvalidation;
import java.lang.reflect.Method;
import java.util.Set;
-
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
@@ -28,6 +27,7 @@ import javax.validation.ValidatorFactory;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.hibernate.validator.HibernateValidator;
+
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.validation.annotation.Validated;
@@ -47,8 +47,8 @@ import org.springframework.validation.annotation.Validated;
* of that class. By default, JSR-303 will validate against its default group only.
*
*
As of Spring 4.0, this functionality requires either a Bean Validation 1.1 provider
- * (such as Hibernate Validator 5.0) or the Bean Validation 1.0 API with Hibernate Validator
- * 4.2 or 4.3. The actual provider will be autodetected and automatically adapted.
+ * (such as Hibernate Validator 5.x) or the Bean Validation 1.0 API with Hibernate Validator
+ * 4.3. The actual provider will be autodetected and automatically adapted.
*
* @author Juergen Hoeller
* @since 3.1
@@ -147,7 +147,7 @@ public class MethodValidationInterceptor implements MethodInterceptor {
/**
- * Inner class to avoid a hard-coded Hibernate Validator 4.2/4.3 dependency.
+ * Inner class to avoid a hard-coded Hibernate Validator 4.3 dependency.
*/
private static class HibernateValidatorDelegate {
@@ -159,9 +159,11 @@ public class MethodValidationInterceptor implements MethodInterceptor {
public static Object invokeWithinValidation(MethodInvocation invocation, Validator validator, Class>[] groups)
throws Throwable {
- org.hibernate.validator.method.MethodValidator methodValidator = validator.unwrap(org.hibernate.validator.method.MethodValidator.class);
- Set> result = methodValidator.validateAllParameters(
- invocation.getThis(), invocation.getMethod(), invocation.getArguments(), groups);
+ org.hibernate.validator.method.MethodValidator methodValidator =
+ validator.unwrap(org.hibernate.validator.method.MethodValidator.class);
+ Set> result =
+ methodValidator.validateAllParameters(
+ invocation.getThis(), invocation.getMethod(), invocation.getArguments(), groups);
if (!result.isEmpty()) {
throw new org.hibernate.validator.method.MethodConstraintViolationException(result);
}
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 f016ca1d9aa..0e93aa0141f 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -49,8 +49,8 @@ import org.springframework.validation.annotation.Validated;
* as well. By default, JSR-303 will validate against its default group only.
*
* As of Spring 4.0, this functionality requires either a Bean Validation 1.1 provider
- * (such as Hibernate Validator 5.0) or the Bean Validation 1.0 API with Hibernate Validator
- * 4.2 or 4.3. The actual provider will be autodetected and automatically adapted.
+ * (such as Hibernate Validator 5.x) or the Bean Validation 1.0 API with Hibernate Validator
+ * 4.3. The actual provider will be autodetected and automatically adapted.
*
* @author Juergen Hoeller
* @since 3.1
diff --git a/spring-context/src/test/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessorTests.java b/spring-context/src/test/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessorTests.java
index 6d831328c18..1e58e8f0f12 100644
--- a/spring-context/src/test/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessorTests.java
+++ b/spring-context/src/test/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessorTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -30,6 +30,8 @@ import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
/**
+ * Tested against Hibernate Validator 4.3, as of Spring 4.0.
+ *
* @author Juergen Hoeller
* @since 3.0
*/
diff --git a/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java b/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java
index 83b650c6aa8..2bb7ed6375c 100644
--- a/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java
+++ b/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 the original author or authors.
+ * Copyright 2002-2014 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,8 @@ import org.springframework.validation.annotation.Validated;
import static org.junit.Assert.*;
/**
+ * Tested against Hibernate Validator 4.3, as of Spring 4.0.
+ *
* @author Juergen Hoeller
* @since 3.1
*/
@@ -103,7 +105,6 @@ public class MethodValidationTests {
@Validated({MyGroup.class, Default.class})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyStereotype {
-
}
}
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 be4f45213a0..33e291325dd 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-2013 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -46,6 +46,8 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
+ * Tested against Hibernate Validator 4.3, as of Spring 4.0.
+ *
* @author Juergen Hoeller
* @since 3.0
*/
@@ -67,6 +69,7 @@ public class ValidatorFactoryTests {
fail("Invalid constraint violation with path '" + path + "'");
}
}
+ validator.destroy();
}
@Test
@@ -86,6 +89,7 @@ public class ValidatorFactoryTests {
fail("Invalid constraint violation with path '" + path + "'");
}
}
+ validator.destroy();
}
@Test
@@ -133,7 +137,6 @@ public class ValidatorFactoryTests {
assertTrue(errorCodes.contains("NotNull.name"));
assertTrue(errorCodes.contains("NotNull.java.lang.String"));
assertTrue(errorCodes.contains("NotNull"));
- System.out.println(fieldError.getDefaultMessage());
fieldError = result.getFieldError("address.street");
assertEquals("address.street", fieldError.getField());
errorCodes = Arrays.asList(fieldError.getCodes());
@@ -143,7 +146,6 @@ public class ValidatorFactoryTests {
assertTrue(errorCodes.contains("NotNull.street"));
assertTrue(errorCodes.contains("NotNull.java.lang.String"));
assertTrue(errorCodes.contains("NotNull"));
- System.out.println(fieldError.getDefaultMessage());
}
@Test
@@ -161,7 +163,6 @@ public class ValidatorFactoryTests {
assertEquals(2, errorCodes.size());
assertTrue(errorCodes.contains("NameAddressValid.person"));
assertTrue(errorCodes.contains("NameAddressValid"));
- System.out.println(globalError.getDefaultMessage());
}
@Test
@@ -175,16 +176,10 @@ public class ValidatorFactoryTests {
assertEquals(3, result.getErrorCount());
FieldError fieldError = result.getFieldError("name");
assertEquals("name", fieldError.getField());
- System.out.println(Arrays.asList(fieldError.getCodes()));
- System.out.println(fieldError.getDefaultMessage());
fieldError = result.getFieldError("address.street");
assertEquals("address.street", fieldError.getField());
- System.out.println(Arrays.asList(fieldError.getCodes()));
- System.out.println(fieldError.getDefaultMessage());
fieldError = result.getFieldError("addressList[0].street");
assertEquals("addressList[0].street", fieldError.getField());
- System.out.println(Arrays.asList(fieldError.getCodes()));
- System.out.println(fieldError.getDefaultMessage());
}
@Test
@@ -198,16 +193,10 @@ public class ValidatorFactoryTests {
assertEquals(3, result.getErrorCount());
FieldError fieldError = result.getFieldError("name");
assertEquals("name", fieldError.getField());
- System.out.println(Arrays.asList(fieldError.getCodes()));
- System.out.println(fieldError.getDefaultMessage());
fieldError = result.getFieldError("address.street");
assertEquals("address.street", fieldError.getField());
- System.out.println(Arrays.asList(fieldError.getCodes()));
- System.out.println(fieldError.getDefaultMessage());
fieldError = result.getFieldError("addressSet[].street");
assertEquals("addressSet[].street", fieldError.getField());
- System.out.println(Arrays.asList(fieldError.getCodes()));
- System.out.println(fieldError.getDefaultMessage());
}
@Test
@@ -271,6 +260,7 @@ public class ValidatorFactoryTests {
}
}
+
public static class ValidAddress {
@NotNull
@@ -285,6 +275,7 @@ public class ValidatorFactoryTests {
}
}
+
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NameAddressValidator.class)
@@ -297,6 +288,7 @@ public class ValidatorFactoryTests {
Class>[] payload() default {};
}
+
public static class NameAddressValidator implements ConstraintValidator {
@Override
@@ -325,6 +317,7 @@ public class ValidatorFactoryTests {
}
}
+
public static class InnerBean {
private String value;
@@ -337,15 +330,20 @@ public class ValidatorFactoryTests {
}
}
+
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Constraint(validatedBy=InnerValidator.class)
public static @interface InnerValid {
+
String message() default "NOT VALID";
+
Class>[] groups() default { };
+
Class extends Payload>[] payload() default {};
}
+
public static class InnerValidator implements ConstraintValidator {
@Override
diff --git a/spring-orm-hibernate4/src/test/java/org/springframework/validation/hibernatevalidator5/BeanValidationPostProcessorTests.java b/spring-orm-hibernate4/src/test/java/org/springframework/validation/hibernatevalidator5/BeanValidationPostProcessorTests.java
new file mode 100644
index 00000000000..ae5008f7346
--- /dev/null
+++ b/spring-orm-hibernate4/src/test/java/org/springframework/validation/hibernatevalidator5/BeanValidationPostProcessorTests.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2002-2014 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.validation.hibernatevalidator5;
+
+import javax.annotation.PostConstruct;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+import org.junit.Test;
+
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.tests.sample.beans.TestBean;
+import org.springframework.validation.beanvalidation.BeanValidationPostProcessor;
+
+import static org.junit.Assert.*;
+
+/**
+ * Copy of {@link org.springframework.validation.beanvalidation.BeanValidationPostProcessor},
+ * here to be tested against Hibernate Validator 5.
+ *
+ * @author Juergen Hoeller
+ * @since 4.1
+ */
+public class BeanValidationPostProcessorTests {
+
+ @Test
+ public void testNotNullConstraint() {
+ GenericApplicationContext ac = new GenericApplicationContext();
+ ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
+ ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class));
+ ac.registerBeanDefinition("bean", new RootBeanDefinition(NotNullConstrainedBean.class));
+ try {
+ ac.refresh();
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.getRootCause().getMessage().contains("testBean"));
+ assertTrue(ex.getRootCause().getMessage().contains("invalid"));
+ }
+ }
+
+ @Test
+ public void testNotNullConstraintSatisfied() {
+ GenericApplicationContext ac = new GenericApplicationContext();
+ ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
+ ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class));
+ RootBeanDefinition bd = new RootBeanDefinition(NotNullConstrainedBean.class);
+ bd.getPropertyValues().add("testBean", new TestBean());
+ ac.registerBeanDefinition("bean", bd);
+ ac.refresh();
+ }
+
+ @Test
+ public void testNotNullConstraintAfterInitialization() {
+ GenericApplicationContext ac = new GenericApplicationContext();
+ RootBeanDefinition bvpp = new RootBeanDefinition(BeanValidationPostProcessor.class);
+ bvpp.getPropertyValues().add("afterInitialization", true);
+ ac.registerBeanDefinition("bvpp", bvpp);
+ ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class));
+ ac.registerBeanDefinition("bean", new RootBeanDefinition(AfterInitConstraintBean.class));
+ ac.refresh();
+ }
+
+ @Test
+ public void testSizeConstraint() {
+ GenericApplicationContext ac = new GenericApplicationContext();
+ ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
+ RootBeanDefinition bd = new RootBeanDefinition(NotNullConstrainedBean.class);
+ bd.getPropertyValues().add("testBean", new TestBean());
+ bd.getPropertyValues().add("stringValue", "s");
+ ac.registerBeanDefinition("bean", bd);
+ try {
+ ac.refresh();
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.getRootCause().getMessage().contains("stringValue"));
+ assertTrue(ex.getRootCause().getMessage().contains("invalid"));
+ }
+ }
+
+ @Test
+ public void testSizeConstraintSatisfied() {
+ GenericApplicationContext ac = new GenericApplicationContext();
+ ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
+ RootBeanDefinition bd = new RootBeanDefinition(NotNullConstrainedBean.class);
+ bd.getPropertyValues().add("testBean", new TestBean());
+ bd.getPropertyValues().add("stringValue", "ss");
+ ac.registerBeanDefinition("bean", bd);
+ ac.refresh();
+ }
+
+
+ public static class NotNullConstrainedBean {
+
+ @NotNull
+ private TestBean testBean;
+
+ @Size(min = 2)
+ private String stringValue;
+
+ public TestBean getTestBean() {
+ return testBean;
+ }
+
+ public void setTestBean(TestBean testBean) {
+ this.testBean = testBean;
+ }
+
+ public String getStringValue() {
+ return stringValue;
+ }
+
+ public void setStringValue(String stringValue) {
+ this.stringValue = stringValue;
+ }
+
+ @PostConstruct
+ public void init() {
+ assertNotNull("Shouldn't be here after constraint checking", this.testBean);
+ }
+ }
+
+
+ public static class AfterInitConstraintBean {
+
+ @NotNull
+ private TestBean testBean;
+
+ public TestBean getTestBean() {
+ return testBean;
+ }
+
+ public void setTestBean(TestBean testBean) {
+ this.testBean = testBean;
+ }
+
+ @PostConstruct
+ public void init() {
+ this.testBean = new TestBean();
+ }
+ }
+
+}
diff --git a/spring-orm-hibernate4/src/test/java/org/springframework/validation/hibernatevalidator5/MethodValidationTests.java b/spring-orm-hibernate4/src/test/java/org/springframework/validation/hibernatevalidator5/MethodValidationTests.java
new file mode 100644
index 00000000000..5b8cc17084f
--- /dev/null
+++ b/spring-orm-hibernate4/src/test/java/org/springframework/validation/hibernatevalidator5/MethodValidationTests.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2002-2014 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.validation.hibernatevalidator5;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.NotNull;
+import javax.validation.groups.Default;
+
+import org.junit.Test;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.validation.beanvalidation.MethodValidationInterceptor;
+import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
+
+import static org.junit.Assert.*;
+
+/**
+ * Copy of {@link org.springframework.validation.beanvalidation.MethodValidationTests},
+ * here to be tested against Hibernate Validator 5.
+ *
+ * @author Juergen Hoeller
+ * @since 4.1
+ */
+public class MethodValidationTests {
+
+ @Test
+ public void testMethodValidationInterceptor() {
+ MyValidBean bean = new MyValidBean();
+ ProxyFactory proxyFactory = new ProxyFactory(bean);
+ proxyFactory.addAdvice(new MethodValidationInterceptor());
+ doTestProxyValidation((MyValidInterface) proxyFactory.getProxy());
+ }
+
+ @Test
+ public void testMethodValidationPostProcessor() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("mvpp", MethodValidationPostProcessor.class);
+ ac.registerSingleton("bean", MyValidBean.class);
+ ac.refresh();
+ doTestProxyValidation(ac.getBean("bean", MyValidInterface.class));
+ }
+
+
+ private void doTestProxyValidation(MyValidInterface proxy) {
+ assertNotNull(proxy.myValidMethod("value", 5));
+ try {
+ assertNotNull(proxy.myValidMethod("value", 15));
+ fail("Should have thrown MethodConstraintViolationException");
+ }
+ catch (javax.validation.ValidationException ex) {
+ // expected
+ }
+ try {
+ assertNotNull(proxy.myValidMethod(null, 5));
+ fail("Should have thrown MethodConstraintViolationException");
+ }
+ catch (javax.validation.ValidationException ex) {
+ // expected
+ }
+ try {
+ assertNotNull(proxy.myValidMethod("value", 0));
+ fail("Should have thrown MethodConstraintViolationException");
+ }
+ catch (javax.validation.ValidationException ex) {
+ // expected
+ }
+ }
+
+
+ @MyStereotype
+ public static class MyValidBean implements MyValidInterface {
+
+ @Override
+ public Object myValidMethod(String arg1, int arg2) {
+ return (arg2 == 0 ? null : "value");
+ }
+ }
+
+
+ public interface MyValidInterface {
+
+ @NotNull Object myValidMethod(@NotNull(groups = MyGroup.class) String arg1, @Max(10) int arg2);
+ }
+
+
+ public interface MyGroup {
+ }
+
+
+ @Validated({MyGroup.class, Default.class})
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface MyStereotype {
+ }
+
+}
diff --git a/spring-orm-hibernate4/src/test/java/org/springframework/validation/hibernatevalidator5/ValidatorFactoryTests.java b/spring-orm-hibernate4/src/test/java/org/springframework/validation/hibernatevalidator5/ValidatorFactoryTests.java
new file mode 100644
index 00000000000..1f9a63a4ad4
--- /dev/null
+++ b/spring-orm-hibernate4/src/test/java/org/springframework/validation/hibernatevalidator5/ValidatorFactoryTests.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2002-2014 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.validation.hibernatevalidator5;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import javax.validation.Constraint;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.ConstraintViolation;
+import javax.validation.Payload;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+
+import org.hibernate.validator.HibernateValidator;
+import org.junit.Test;
+
+import org.springframework.validation.BeanPropertyBindingResult;
+import org.springframework.validation.Errors;
+import org.springframework.validation.FieldError;
+import org.springframework.validation.ObjectError;
+import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * Copy of {@link org.springframework.validation.beanvalidation.ValidatorFactoryTests},
+ * here to be tested against Hibernate Validator 5.
+ *
+ * @author Juergen Hoeller
+ * @since 4.1
+ */
+public class ValidatorFactoryTests {
+
+ @Test
+ public void testSimpleValidation() throws Exception {
+ LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
+ validator.afterPropertiesSet();
+ ValidPerson person = new ValidPerson();
+ Set> result = validator.validate(person);
+ assertEquals(2, result.size());
+ for (ConstraintViolation cv : result) {
+ String path = cv.getPropertyPath().toString();
+ if ("name".equals(path) || "address.street".equals(path)) {
+ assertTrue(cv.getConstraintDescriptor().getAnnotation() instanceof NotNull);
+ }
+ else {
+ fail("Invalid constraint violation with path '" + path + "'");
+ }
+ }
+ validator.destroy();
+ }
+
+ @Test
+ public void testSimpleValidationWithCustomProvider() throws Exception {
+ LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
+ validator.setProviderClass(HibernateValidator.class);
+ validator.afterPropertiesSet();
+ ValidPerson person = new ValidPerson();
+ Set> result = validator.validate(person);
+ assertEquals(2, result.size());
+ for (ConstraintViolation cv : result) {
+ String path = cv.getPropertyPath().toString();
+ if ("name".equals(path) || "address.street".equals(path)) {
+ assertTrue(cv.getConstraintDescriptor().getAnnotation() instanceof NotNull);
+ }
+ else {
+ fail("Invalid constraint violation with path '" + path + "'");
+ }
+ }
+ validator.destroy();
+ }
+
+ @Test
+ public void testSimpleValidationWithClassLevel() throws Exception {
+ LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
+ validator.afterPropertiesSet();
+ ValidPerson person = new ValidPerson();
+ person.setName("Juergen");
+ person.getAddress().setStreet("Juergen's Street");
+ Set> result = validator.validate(person);
+ assertEquals(1, result.size());
+ Iterator> iterator = result.iterator();
+ ConstraintViolation> cv = iterator.next();
+ assertEquals("", cv.getPropertyPath().toString());
+ assertTrue(cv.getConstraintDescriptor().getAnnotation() instanceof NameAddressValid);
+ }
+
+ @Test
+ public void testSpringValidationFieldType() throws Exception {
+ LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
+ validator.afterPropertiesSet();
+ ValidPerson person = new ValidPerson();
+ person.setName("Phil");
+ person.getAddress().setStreet("Phil's Street");
+ BeanPropertyBindingResult errors = new BeanPropertyBindingResult(person, "person");
+ validator.validate(person, errors);
+ assertEquals(1, errors.getErrorCount());
+ assertThat("Field/Value type mismatch", errors.getFieldError("address").getRejectedValue(),
+ instanceOf(ValidAddress.class));
+ }
+
+ @Test
+ 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);
+ assertEquals(2, result.getErrorCount());
+ FieldError fieldError = result.getFieldError("name");
+ assertEquals("name", fieldError.getField());
+ List errorCodes = Arrays.asList(fieldError.getCodes());
+ assertEquals(4, errorCodes.size());
+ assertTrue(errorCodes.contains("NotNull.person.name"));
+ assertTrue(errorCodes.contains("NotNull.name"));
+ assertTrue(errorCodes.contains("NotNull.java.lang.String"));
+ assertTrue(errorCodes.contains("NotNull"));
+ fieldError = result.getFieldError("address.street");
+ assertEquals("address.street", fieldError.getField());
+ errorCodes = Arrays.asList(fieldError.getCodes());
+ assertEquals(5, errorCodes.size());
+ assertTrue(errorCodes.contains("NotNull.person.address.street"));
+ assertTrue(errorCodes.contains("NotNull.address.street"));
+ assertTrue(errorCodes.contains("NotNull.street"));
+ assertTrue(errorCodes.contains("NotNull.java.lang.String"));
+ assertTrue(errorCodes.contains("NotNull"));
+ }
+
+ @Test
+ public void testSpringValidationWithClassLevel() throws Exception {
+ LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
+ validator.afterPropertiesSet();
+ ValidPerson person = new ValidPerson();
+ 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 errorCodes = Arrays.asList(globalError.getCodes());
+ assertEquals(2, errorCodes.size());
+ assertTrue(errorCodes.contains("NameAddressValid.person"));
+ assertTrue(errorCodes.contains("NameAddressValid"));
+ }
+
+ @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");
+ validator.validate(person, result);
+ assertEquals(3, result.getErrorCount());
+ FieldError fieldError = result.getFieldError("name");
+ assertEquals("name", fieldError.getField());
+ fieldError = result.getFieldError("address.street");
+ assertEquals("address.street", fieldError.getField());
+ fieldError = result.getFieldError("addressList[0].street");
+ assertEquals("addressList[0].street", fieldError.getField());
+ }
+
+ @Test
+ 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");
+ validator.validate(person, result);
+ assertEquals(3, result.getErrorCount());
+ FieldError fieldError = result.getFieldError("name");
+ assertEquals("name", fieldError.getField());
+ fieldError = result.getFieldError("address.street");
+ assertEquals("address.street", fieldError.getField());
+ fieldError = result.getFieldError("addressSet[].street");
+ assertEquals("addressSet[].street", fieldError.getField());
+ }
+
+ @Test
+ public void testInnerBeanValidation() throws Exception {
+ LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
+ validator.afterPropertiesSet();
+
+ MainBean mainBean = new MainBean();
+ Errors errors = new BeanPropertyBindingResult(mainBean, "mainBean");
+ validator.validate(mainBean, errors);
+ Object rejected = errors.getFieldValue("inner.value");
+ assertNull(rejected);
+ }
+
+
+ @NameAddressValid
+ public static class ValidPerson {
+
+ @NotNull
+ private String name;
+
+ @Valid
+ private ValidAddress address = new ValidAddress();
+
+ @Valid
+ private List addressList = new LinkedList();
+
+ @Valid
+ private Set addressSet = new LinkedHashSet();
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public ValidAddress getAddress() {
+ return address;
+ }
+
+ public void setAddress(ValidAddress address) {
+ this.address = address;
+ }
+
+ public List getAddressList() {
+ return addressList;
+ }
+
+ public void setAddressList(List addressList) {
+ this.addressList = addressList;
+ }
+
+ public Set getAddressSet() {
+ return addressSet;
+ }
+
+ public void setAddressSet(Set addressSet) {
+ this.addressSet = addressSet;
+ }
+ }
+
+
+ public static class ValidAddress {
+
+ @NotNull
+ private String street;
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+ }
+
+
+ @Target(ElementType.TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @Constraint(validatedBy = NameAddressValidator.class)
+ public @interface NameAddressValid {
+
+ String message() default "Street must not contain name";
+
+ Class>[] groups() default {};
+
+ Class>[] payload() default {};
+ }
+
+
+ public static class NameAddressValidator implements ConstraintValidator {
+
+ @Override
+ public void initialize(NameAddressValid constraintAnnotation) {
+ }
+
+ @Override
+ public boolean isValid(ValidPerson value, ConstraintValidatorContext context) {
+ boolean valid = (value.name == null || !value.address.street.contains(value.name));
+ if (!valid && "Phil".equals(value.name)) {
+ context.buildConstraintViolationWithTemplate(
+ context.getDefaultConstraintMessageTemplate()).addNode("address").addConstraintViolation().disableDefaultConstraintViolation();
+ }
+ return valid;
+ }
+ }
+
+
+ public static class MainBean {
+
+ @InnerValid
+ private InnerBean inner = new InnerBean();
+
+ public InnerBean getInner() {
+ return inner;
+ }
+ }
+
+
+ public static class InnerBean {
+
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+ public void setValue(String value) {
+ this.value = value;
+ }
+ }
+
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.FIELD)
+ @Constraint(validatedBy=InnerValidator.class)
+ public static @interface InnerValid {
+
+ String message() default "NOT VALID";
+
+ Class>[] groups() default { };
+
+ Class extends Payload>[] payload() default {};
+ }
+
+
+ public static class InnerValidator implements ConstraintValidator {
+
+ @Override
+ public void initialize(InnerValid constraintAnnotation) {
+ }
+
+ @Override
+ public boolean isValid(InnerBean bean, ConstraintValidatorContext context) {
+ context.disableDefaultConstraintViolation();
+ if (bean.getValue() == null) {
+ context.buildConstraintViolationWithTemplate("NULL"). addNode("value").addConstraintViolation();
+ return false;
+ }
+ return true;
+ }
+ }
+
+}