Liam Miller-Cushon created BVAL-129:
---------------------------------------
Summary: JDK8 - Annotations on synthetic bridge methods break bval
Key: BVAL-129
URL: https://issues.apache.org/jira/browse/BVAL-129
Project: BVal
Issue Type: Bug
Components: jsr303
Affects Versions: 0.5, 1.1.0-alpha
Environment: JDK8
Reporter: Liam Miller-Cushon
As of jdk8, the java compiler now copies annotations onto synthetic bridge
methods. See https://bugs.openjdk.java.net/browse/JDK-6695379 for more
information about the change. When javac creates synthetic copies of methods
the method signatures are erased. This violates assumptions made by bval.
Consider the following example:
===
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { MyValidator.class })
public @interface SomeAnnotation { … }
public static class MyValidator implements ConstraintValidator<SomeAnnotation,
String> { … }
public interface Id<T> {
T getId();
}
public static class ObjectToValidate implements Id<String> {
@SomeAnnotation
public String getId() { return null; }
}
===
The compiler creates a bridge method for ObjectToValidate.getId with the erased
return type of Object. Prior to jdk8 this method had no annotations and was
ignored by bval, but with the change in jdk8 the validation fails:
$ export
JAVA_HOME=/Library/Java/JavaVirtualMachinesLibrary/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/
&& mvn clean package exec:java -Dexec.mainClass="Test"
…
SUCCESS
$ export
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/ && mvn
clean package exec:java -Dexec.mainClass="Test"
...
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:293)
at java.lang.Thread.run(Thread.java:744)
Caused by: javax.validation.UnexpectedTypeException: No validator could be
found for type java.lang.Object. See: @SomeAnnotation at public
java.lang.Object Test$ObjectToValidate.getId()
at
org.apache.bval.jsr303.AnnotationProcessor.checkOneType(AnnotationProcessor.java:326)
at
org.apache.bval.jsr303.AnnotationProcessor.getConstraintValidator(AnnotationProcessor.java:301)
at
org.apache.bval.jsr303.AnnotationProcessor.applyConstraint(AnnotationProcessor.java:241)
at
org.apache.bval.jsr303.AnnotationProcessor.processAnnotation(AnnotationProcessor.java:149)
at
org.apache.bval.jsr303.AnnotationProcessor.processAnnotations(AnnotationProcessor.java:90)
at
org.apache.bval.jsr303.Jsr303MetaBeanFactory.processClass(Jsr303MetaBeanFactory.java:156)
at
org.apache.bval.jsr303.Jsr303MetaBeanFactory.buildMetaBean(Jsr303MetaBeanFactory.java:95)
at
org.apache.bval.MetaBeanBuilder.buildForClass(MetaBeanBuilder.java:131)
at
org.apache.bval.MetaBeanManager.findForClass(MetaBeanManager.java:102)
at
org.apache.bval.jsr303.ClassValidator.validate(ClassValidator.java:140)
at Test.main(Test.java:33)
... 6 more
Proposed solution:
To preserve the behaviour bval had pre-jdk8, it can simply ignore the synthetic
bridge methods. The following patch would accomplish this:
===
--- src/main/java/org/apache/bval/jsr303/Jsr303MetaBeanFactory.java
+++ src/main/java/org/apache/bval/jsr303/Jsr303MetaBeanFactory.java
@@ -139,6 +139,9 @@
}
final Method[] methods =
doPrivileged(SecureActions.getDeclaredMethods(beanClass));
for (Method method : methods) {
+ if (method.isSynthetic() || method.isBridge()) {
+ continue;
+ }
String propName = null;
if (method.getParameterTypes().length == 0) {
propName = MethodAccess.getPropertyName(method);
===
--
This message was sent by Atlassian JIRA
(v6.2#6252)