Created attachment 35912 [details] TEST-org.apache.catalina.startup.TestContextConfig.APR.txt Running unit tests for Tomcat 7.0.87 (release candidate) with Java 6. The following tests unexpectedly fail: TEST-org.apache.catalina.startup.TestContextConfig.APR.txt TEST-org.apache.catalina.startup.TestContextConfig.BIO.txt TEST-org.apache.catalina.startup.TestContextConfig.NIO.txt See attached log file. Tomcat fails to start in testBug54448and54450 test. Stacktrace: [[[ Caused by: java.lang.NoSuchMethodError: javax.annotation.Resource.lookup()Ljava/lang/String; at org.apache.catalina.startup.WebAnnotationSet.addResource(WebAnnotationSet.java:339) at org.apache.catalina.startup.WebAnnotationSet.loadFieldsAnnotation(WebAnnotationSet.java:274) at org.apache.catalina.startup.WebAnnotationSet.loadApplicationServletAnnotations(WebAnnotationSet.java:135) at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:67) at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:417) at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:881) at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:388) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5566) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) ]]] This is regression from code added in r1827367.
(In reply to Konstantin Kolinko from comment #0) > Caused by: java.lang.NoSuchMethodError: > javax.annotation.Resource.lookup()Ljava/lang/String; > > This is regression from code added in r1827367. 1. The method javax.annotation.Resource.lookup() is documented as @since Common Annotations 1.1 See https://docs.oracle.com/javase/7/docs/api/javax/annotation/Resource.html#lookup() 2. jdk1.6.0_45 has a copy of this annotation class WITHOUT this method. The source code for the class is present in src.zip bundled with JDK. 3. Tomcat 7 has its own copy of this annotation, in \java\javax\annotation\Resource.java This copy has been updated to Commons Annotations 1.1 and has the lookup() method. My guess is that thanks to (3.) the code compiles successfully, but (2.) causes it to failure at runtime. A quick fix is to revert r1827367. A bigger question is why do we bundle classes that are already provided by the JRE. Comparing the classes in Java 6 and the classes in annotations-api.jar of Tomcat, a difference is that Tomcat has classes in the following package - javax.annotation.security The rest of differences are Common Annotations 1.0 vs 1.1.
(In reply to Konstantin Kolinko from comment #1) > Comparing the classes in Java 6 and the classes in annotations-api.jar of > Tomcat, a difference is that Tomcat has classes in the following package > - javax.annotation.security > > The rest of differences are Common Annotations 1.0 vs 1.1. rt.jar of Java 6 has the following javax.annotation classes: Generated.class PostConstruct.class PreDestroy.class Resource.class Resource$AuthenticationType.class Resources.class annotations-api.jar of Tomcat has the following additional classes and packages: 1) in javax.annotation: ManagedBean.class - @since Common Annotations 1.1 2) package javax.annotation.security. - I wonder why Java 6 is it. These classes are documented as @since Common Annotations 1.0. 3) package javax.annotation.sql - @since Common Annotations 1.1
Looking into WebAnnotationSet class, the problematic code is triggered only when - Annotation scanning has been performed - It found a @Resource annotation and tries to process it. A web application is not affected by this issue if any of the following is true: - It does not have @Resource annotations. - It does not perform annotation scanning (it is marked as metadata-complete). - Tomcat runs on Java 7 or later. E.g. standard applications bundled with Tomcat 7 (the examples app) are not affected.
For reference: Java EE 6 requires Common Annotations 1.1 Java SE 6 ships with Common Annotations 1.0 Still thinking about how this might be fixed.
The expected way to enable Common Annotations 1.1 when running on Java 6 is via the Endorsed Standards Override Mechanism. I looked at various other ways to do this but they all broke for at least one use case. Apart from BZ 50019, there has been no request for Common Annotations 1.1 support in Tomcat 7 and no problems reported, that I can recall, because it is not present. I am therefore thinking along the the lines of making the changes in WebAnnotationSet that were introduced in r1827367 conditional on Tomcat running on Java 7 or Tomcat running on Java 6 that has been configured with Common Annotations 1.1.
(In reply to Konstantin Kolinko from comment #2) > (In reply to Konstantin Kolinko from comment #1) > > Comparing the classes in Java 6 and the classes in annotations-api.jar of > > Tomcat, a difference is that Tomcat has classes in the following package > > - javax.annotation.security > > > > The rest of differences are Common Annotations 1.0 vs 1.1. > > rt.jar of Java 6 has the following javax.annotation classes: > > Generated.class > PostConstruct.class > PreDestroy.class > Resource.class > Resource$AuthenticationType.class > Resources.class > > annotations-api.jar of Tomcat has the following additional classes and > packages: > > 1) in javax.annotation: ManagedBean.class > - @since Common Annotations 1.1 > > 2) package javax.annotation.security. > - I wonder why Java 6 is it. These classes are documented as @since Common > Annotations 1.0. > > 3) package javax.annotation.sql > - @since Common Annotations 1.1 Comparing Java 6 with Java 7 and 8: the missing classes (ManagedBean) and the two packages (security, sql) are missing in Java 7 and Java 8 as well. Java 6(.45)/7(.80)/8(.172) all have only the following classes: > Generated.class > PostConstruct.class > PreDestroy.class > Resource.class > Resource$AuthenticationType.class > Resources.class The rest of Commons Annotations 1.1 classes are missing. BTW, Commons Annotations 1.3 spec (latest), jsr-250.pdf: [quote] 1.3 Compatibility The annotations defined in this specification may be included individually as needed in products that make use of them. Other Java specifications will require support for subsets of these annotations. Products that support these Java specifications must include the required annotations. [/quote] That is why JRE only has a subset of the classes.
Looking at the (lack of) dependencies between the annotations, it should be safe to load the Java SE provided ones from Java SE and the remainder from Tomcat's JAR without risk of conflict. I've been testing the solution I proposed in comment #5 and it is looking good. I should be able to commit it shortly.
(In reply to Mark Thomas from comment #5) I pondered about the Endorsed Standards Override Mechanism as well. I think this means instructing users (via RUNNING.txt or via RELEASE-NOTES) to copy annotations-api.jar from "${catalina.home|/lib" into "${catalina.home|/endorsed" when running on Java 6. Changing or distribution zip/tar archives (moving the file permanently / by default) does not make sense, as newer versions of Java can have newer versions of the classes, even newer that those bundled with Tomcat.
Patch applied. Docs updated. Will be in 7.0.88.
(In reply to Mark Thomas from comment #9) > Patch applied. Docs updated. Will be in 7.0.88. Looks good. I amended the docs a bit. Several notes, for a record: 1. Looking into commit history of javax.annotation classes in Tomcat 7: - The commit that updates Common Annotations 1.0 -> 1.1 is r1521045 (fixed bug 55534). The only change of existing annotation classes in that commit is adding lookup() element on @Resource annotation. There is also r1797343 that added missing @Documented annotation. This is not a change between versions, as those annotations are already present in Commons Annotations 1.0 - as can be seen in Java 6 javadoc for javax.annotation classes. Thus addition of "luokup" is the only difference. 2. When running with Java 6, the value of "luokup" element on a @Resource annotation, if present, will be silently ignored. - This is covered by Java Language Specification, 13.5.7 Evolution of Annotation Types. https://docs.oracle.com/javase/specs/jls/se6/html/binaryComp.html#13.5.7 - Technically: looking into source code for Open JDK 6, I confirm that it is silently skipped. Trace: - java.lang.Class#initAnnotationsIfNecessary() -> sun.reflect.annotation.AnnotationParser -> AnnotationParser#parseAnnotation() -> L237 "// Member is no longer present in annotation type; ignore it" http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/sun/reflect/annotation/AnnotationParser.java#236