Control: tag -1 ftbfs upstream fixed-upstream patch
The cleanest way to fix this would be upgrading Spring to 5.0 or later,
which drops the build-dependency on hibernate-validator 4.x and strictly
requires validation-api 1.1 and hibernate-validator 5.x.
In case that's not possible in the near term, I attach here a patch
consisting of changes backported from upstream to remove the code
depending on hibernate-validator 4.x.
I did successfully run the unit tests of o.s.validation.beanvalidation.*
with my patch applied, but it needed so much hacking that I don't
entirely trust the result. I have not yet tested an actual application
using the bean validation feature from the installed package, and I
won't open an MR until I've done that.
>From db567eaf8d24df19d5667b0477db42ad46246c86 Mon Sep 17 00:00:00 2001
From: Ryan Tandy <r...@nardis.ca>
Date: Mon, 18 Nov 2019 21:50:19 +0000
Subject: [PATCH] Fix FTBFS with Hibernate Validator 5.x
---
debian/changelog | 7 +
debian/control | 4 +-
debian/maven.rules | 2 +-
.../0054-disable-hibernate-validator-4.patch | 315 ++++++++++++++++++
debian/patches/series | 1 +
5 files changed, 326 insertions(+), 3 deletions(-)
create mode 100644 debian/patches/0054-disable-hibernate-validator-4.patch
diff --git a/debian/changelog b/debian/changelog
index addf891d..a58e294d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+libspring-java (4.3.22-4.1) UNRELEASED; urgency=medium
+
+ * Fix FTBFS with libhibernate-validator-java 5.x: Upgrade to Bean Validation
+ 1.1 and remove Hibernate Validator 4.x support. (Closes: #941685)
+
+ -- Ryan Tandy <r...@nardis.ca> Mon, 18 Nov 2019 19:48:22 +0000
+
libspring-java (4.3.22-4) unstable; urgency=medium
* Team upload.
diff --git a/debian/control b/debian/control
index b7d5a178..ba1cdd91 100644
--- a/debian/control
+++ b/debian/control
@@ -43,7 +43,7 @@ Build-Depends-Indep: bsh,
libgeronimo-jcache-1.0-spec-java,
libgeronimo-jms-1.1-spec-java,
libgeronimo-jta-1.2-spec-java,
- libgeronimo-validation-1.0-spec-java,
+ libgeronimo-validation-1.1-spec-java,
libhessian-java,
libhibernate-validator-java (>= 4.3.2),
libhibernate3-java (>= 3.5),
@@ -156,7 +156,7 @@ Recommends: libasm-java (>= 5.0),
libcglib-java (>= 3.1),
libgeronimo-ejb-3.2-spec-java,
libgeronimo-jms-1.1-spec-java,
- libgeronimo-validation-1.0-spec-java,
+ libgeronimo-validation-1.1-spec-java,
libjodatime-java,
libspring-instrument-java (= ${source:Version}),
libtomcat9-java
diff --git a/debian/maven.rules b/debian/maven.rules
index c5658212..00a46097 100644
--- a/debian/maven.rules
+++ b/debian/maven.rules
@@ -10,7 +10,7 @@ javax.portlet portlet-api * * * *
s/javax.resource/org.apache.geronimo.specs/ s/connector-api/geronimo-j2ee-connector_1.5_spec/ * s/.*/debian/ * *
s/javax.servlet.jsp.jstl/org.apache.taglibs/ s/javax.servlet.jsp.jstl-api/taglibs-standard-spec/ * s/.*/debian/ * *
s/javax.transaction/org.apache.geronimo.specs/ s/javax.transaction-api/geronimo-jta_1.2_spec/ * s/.*/debian/ * *
-s/javax.validation/org.apache.geronimo.specs/ s/validation-api/geronimo-validation_1.0_spec/ * s/.*/debian/ * *
+s/javax.validation/org.apache.geronimo.specs/ s/validation-api/geronimo-validation_1.1_spec/ * s/.*/debian/ * *
junit junit * s/.*/4.x/ * *
log4j log4j * s/.*/1.2.x/ * *
org.apache.tomcat s/catalina/tomcat-catalina/ * s/.*/9.x/ * *
diff --git a/debian/patches/0054-disable-hibernate-validator-4.patch b/debian/patches/0054-disable-hibernate-validator-4.patch
new file mode 100644
index 00000000..59927894
--- /dev/null
+++ b/debian/patches/0054-disable-hibernate-validator-4.patch
@@ -0,0 +1,315 @@
+Description: Fix compilation failure with Hibernate Validator 5.x
+ Backport parts of upstream commit 54004e0d78dd92c62429999b77befbc9d9fcdb68
+ to remove Hibernate Validator 4.x dependency and use Bean Validation 1.1
+ directly.
+Author: Ryan Tandy <r...@nardis.ca>
+Forwarded: not-needed
+Bug-Debian: https://bugs.debian.org/941685
+--- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java
++++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java
+@@ -24,11 +24,13 @@
+ import java.lang.reflect.Proxy;
+ import java.util.Arrays;
+ import java.util.HashMap;
++import java.util.List;
+ import java.util.Map;
+ import java.util.Properties;
+ import javax.validation.Configuration;
+ import javax.validation.ConstraintValidatorFactory;
+ import javax.validation.MessageInterpolator;
++import javax.validation.ParameterNameProvider;
+ import javax.validation.TraversableResolver;
+ import javax.validation.Validation;
+ import javax.validation.ValidationException;
+@@ -67,15 +69,8 @@
+ * you will almost always use the default Validator anyway. This can also be injected directly
+ * into any target dependency of type {@link org.springframework.validation.Validator}!
+ *
+- * <p><b>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.x</b> (see {@link #setValidationMessageSource}).
+- *
+- * <p>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}
+- * 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><b>As of Spring 5.0, this class requires Bean Validation 1.1, with special support
++ * for Hibernate Validator 5.x</b> (see {@link #setValidationMessageSource}).
+ *
+ * <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.
+@@ -90,10 +85,6 @@
+ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
+ implements ValidatorFactory, ApplicationContextAware, InitializingBean, DisposableBean {
+
+- // Bean Validation 1.1 close() method available?
+- private static final Method closeMethod = ClassUtils.getMethodIfAvailable(ValidatorFactory.class, "close");
+-
+-
+ @SuppressWarnings("rawtypes")
+ private Class providerClass;
+
+@@ -312,55 +303,23 @@
+ }
+
+ private void configureParameterNameProviderIfPossible(Configuration<?> configuration) {
+- try {
+- Class<?> parameterNameProviderClass =
+- ClassUtils.forName("javax.validation.ParameterNameProvider", getClass().getClassLoader());
+- Method parameterNameProviderMethod =
+- Configuration.class.getMethod("parameterNameProvider", parameterNameProviderClass);
+- final Object defaultProvider = ReflectionUtils.invokeMethod(
+- Configuration.class.getMethod("getDefaultParameterNameProvider"), configuration);
+- final ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;
+- Object parameterNameProvider = Proxy.newProxyInstance(getClass().getClassLoader(),
+- new Class<?>[] {parameterNameProviderClass}, new InvocationHandler() {
+- @Override
+- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+- if (method.getName().equals("getParameterNames")) {
+- String[] result = null;
+- if (args[0] instanceof Constructor) {
+- result = discoverer.getParameterNames((Constructor<?>) args[0]);
+- }
+- else if (args[0] instanceof Method) {
+- result = discoverer.getParameterNames((Method) args[0]);
+- }
+- if (result != null) {
+- return Arrays.asList(result);
+- }
+- else {
+- try {
+- return method.invoke(defaultProvider, args);
+- }
+- catch (InvocationTargetException ex) {
+- throw ex.getTargetException();
+- }
+- }
+- }
+- else {
+- // toString, equals, hashCode
+- try {
+- return method.invoke(this, args);
+- }
+- catch (InvocationTargetException ex) {
+- throw ex.getTargetException();
+- }
+- }
+- }
+- });
+- ReflectionUtils.invokeMethod(parameterNameProviderMethod, configuration, parameterNameProvider);
+-
+- }
+- catch (Throwable ex) {
+- // Bean Validation 1.1 API not available - simply not applying the ParameterNameDiscoverer
+- }
++ // TODO: inner class
++ final ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;
++ final ParameterNameProvider defaultProvider = configuration.getDefaultParameterNameProvider();
++ configuration.parameterNameProvider(new ParameterNameProvider() {
++ @Override
++ public List<String> getParameterNames(Constructor<?> constructor) {
++ String[] paramNames = discoverer.getParameterNames(constructor);
++ return (paramNames != null ? Arrays.asList(paramNames) :
++ defaultProvider.getParameterNames(constructor));
++ }
++ @Override
++ public List<String> getParameterNames(Method method) {
++ String[] paramNames = discoverer.getParameterNames(method);
++ return (paramNames != null ? Arrays.asList(paramNames) :
++ defaultProvider.getParameterNames(method));
++ }
++ });
+ }
+
+ /**
+@@ -428,9 +387,14 @@
+ }
+
+
++ @Override
++ public ParameterNameProvider getParameterNameProvider() {
++ return this.validatorFactory.getParameterNameProvider();
++ }
++
+ public void close() {
+- if (closeMethod != null && this.validatorFactory != null) {
+- ReflectionUtils.invokeMethod(closeMethod, this.validatorFactory);
++ if (this.validatorFactory != null) {
++ this.validatorFactory.close();
+ }
+ }
+
+--- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java
++++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java
+@@ -26,7 +26,6 @@
+
+ import org.aopalliance.intercept.MethodInterceptor;
+ import org.aopalliance.intercept.MethodInvocation;
+-import org.hibernate.validator.HibernateValidator;
+
+ import org.springframework.beans.factory.FactoryBean;
+ import org.springframework.beans.factory.SmartFactoryBean;
+@@ -50,9 +49,8 @@
+ * at the type level of the containing target class, applying to all public service methods
+ * of that class. By default, JSR-303 will validate against its default group only.
+ *
+- * <p>As of Spring 4.0, this functionality requires either a Bean Validation 1.1 provider
+- * (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.
++ * <p>As of Spring 5.0, this functionality requires a Bean Validation 1.1 provider
++ * (such as Hibernate Validator 5.x).
+ *
+ * @author Juergen Hoeller
+ * @since 3.1
+@@ -90,8 +88,7 @@
+ * Create a new MethodValidationInterceptor using a default JSR-303 validator underneath.
+ */
+ public MethodValidationInterceptor() {
+- this(forExecutablesMethod != null ? Validation.buildDefaultValidatorFactory() :
+- HibernateValidatorDelegate.buildValidatorFactory());
++ this(Validation.buildDefaultValidatorFactory());
+ }
+
+ /**
+@@ -121,52 +118,36 @@
+
+ Class<?>[] groups = determineValidationGroups(invocation);
+
+- if (forExecutablesMethod != null) {
+- // Standard Bean Validation 1.1 API
+- Object execVal;
+- try {
+- execVal = ReflectionUtils.invokeMethod(forExecutablesMethod, this.validator);
+- }
+- catch (AbstractMethodError err) {
+- // Probably an adapter (maybe a lazy-init proxy) without BV 1.1 support
+- Validator nativeValidator = this.validator.unwrap(Validator.class);
+- execVal = ReflectionUtils.invokeMethod(forExecutablesMethod, nativeValidator);
+- // If successful, store native Validator for further use
+- this.validator = nativeValidator;
+- }
+-
+- Method methodToValidate = invocation.getMethod();
+- Set<ConstraintViolation<?>> result;
+-
+- try {
+- result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateParametersMethod,
+- execVal, invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
+- }
+- catch (IllegalArgumentException ex) {
+- // Probably a generic type mismatch between interface and impl as reported in SPR-12237 / HV-1011
+- // Let's try to find the bridged method on the implementation class...
+- methodToValidate = BridgeMethodResolver.findBridgedMethod(
+- ClassUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()));
+- result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateParametersMethod,
+- execVal, invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
+- }
+- if (!result.isEmpty()) {
+- throw new ConstraintViolationException(result);
+- }
+-
+- Object returnValue = invocation.proceed();
+- result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateReturnValueMethod,
+- execVal, invocation.getThis(), methodToValidate, returnValue, groups);
+- if (!result.isEmpty()) {
+- throw new ConstraintViolationException(result);
+- }
+- return returnValue;
+- }
+-
+- else {
+- // Hibernate Validator 4.3's native API
+- return HibernateValidatorDelegate.invokeWithinValidation(invocation, this.validator, groups);
++ // Standard Bean Validation 1.1 API
++ Object execVal = ReflectionUtils.invokeMethod(forExecutablesMethod, this.validator);
++ Method methodToValidate = invocation.getMethod();
++ Set<ConstraintViolation<?>> result;
++
++ try {
++ result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateParametersMethod,
++ execVal, invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
++ }
++ catch (IllegalArgumentException ex) {
++ // Probably a generic type mismatch between interface and impl as reported in SPR-12237 / HV-1011
++ // Let's try to find the bridged method on the implementation class...
++ methodToValidate = BridgeMethodResolver.findBridgedMethod(
++ ClassUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()));
++ result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateParametersMethod,
++ execVal, invocation.getThis(), methodToValidate, invocation.getArguments(), groups);
+ }
++ if (!result.isEmpty()) {
++ throw new ConstraintViolationException(result);
++ }
++
++ Object returnValue = invocation.proceed();
++
++ result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateReturnValueMethod,
++ execVal, invocation.getThis(), methodToValidate, returnValue, groups);
++ if (!result.isEmpty()) {
++ throw new ConstraintViolationException(result);
++ }
++
++ return returnValue;
+ }
+
+ private boolean isFactoryBeanMetadataMethod(Method method) {
+@@ -205,36 +186,4 @@
+ return (validatedAnn != null ? validatedAnn.value() : new Class<?>[0]);
+ }
+
+-
+- /**
+- * Inner class to avoid a hard-coded Hibernate Validator 4.3 dependency.
+- */
+- private static class HibernateValidatorDelegate {
+-
+- public static ValidatorFactory buildValidatorFactory() {
+- return Validation.byProvider(HibernateValidator.class).configure().buildValidatorFactory();
+- }
+-
+- @SuppressWarnings("deprecation")
+- 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<org.hibernate.validator.method.MethodConstraintViolation<Object>> result =
+- methodValidator.validateAllParameters(
+- invocation.getThis(), invocation.getMethod(), invocation.getArguments(), groups);
+- if (!result.isEmpty()) {
+- throw new org.hibernate.validator.method.MethodConstraintViolationException(result);
+- }
+- Object returnValue = invocation.proceed();
+- result = methodValidator.validateReturnValue(
+- invocation.getThis(), invocation.getMethod(), returnValue, groups);
+- if (!result.isEmpty()) {
+- throw new org.hibernate.validator.method.MethodConstraintViolationException(result);
+- }
+- return returnValue;
+- }
+- }
+-
+ }
+--- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java
++++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java
+@@ -27,6 +27,7 @@
+ import javax.validation.ConstraintViolation;
+ import javax.validation.ValidationException;
+ import javax.validation.Validator;
++import javax.validation.executable.ExecutableValidator;
+ import javax.validation.metadata.BeanDescriptor;
+ import javax.validation.metadata.ConstraintDescriptor;
+
+@@ -320,6 +321,11 @@
+ }
+ }
+
++ @Override
++ public ExecutableValidator forExecutables() {
++ return this.targetValidator.forExecutables();
++ }
++
+
+ /**
+ * Wrapper for a String attribute which can be resolved via a {@code MessageSource},
diff --git a/debian/patches/series b/debian/patches/series
index c1b2e38f..cd82afb3 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -21,3 +21,4 @@
0051-reproducible-build-source-date.patch
0052-no-jasperreports.patch
0053-ignore-reactor.patch
+0054-disable-hibernate-validator-4.patch
--
2.24.0