For the benefit of anyone searching this mailing list due to a similar problem in future:
My problem was due to using the wrong (default) classloader: ClassLoader loader = new URLClassLoader(urls); The issue was resolved by switching to: ClassLoader loader = new URLClassLoader(urls, ParserApp.class.getClassLoader()); On Tue, Aug 28, 2012 at 5:23 PM, Thomas McDermott <[email protected]>wrote: > Dear all, > > I have difficulty finding annotations on classes loaded from a Maven > plugin (I am using JDK 1.7 and Maven 3.0.4). > > I have a Class ParserApp > with a method processAllClassFiles(rootClassFolder) > which processes all the ".class" files in the folder tree under > rootClassFolder. > > In short, the method processAllClassFiles can load class files and find > annotations when run from a unit test in eclipse > or when called from the commandline; however when the method is wrapped in > a MavenMojo plugin the class file is loaded > but the annotations are not found. > > The following snippets from the ParserApp class provide some further > details of the problem. > > Given a path to a .class file obtained from searching a rootFolder > Files.walkFileTree(Paths.get(rootFolder), ... > > Path file = "./target/test-classes/com/example/AnnotatedPojo.class"; > > > ---------------------------------------------------------------------------------------- > Content of AnnotatedPojo.java: > > package com.example.pojos; > import com.example.annotation.*; > @AnnotationDefinition(value = "ValueOfTheAnnotation") > public class AnnotatedPojo { > } > > ---------------------------------------------------------------------------------------- > > I use the javassist library > <dependency> > <groupId>javassist</groupId> > <artifactId>javassist</artifactId> > <version>3.12.1.GA</version> > </dependency> > to parse the .classfile and find and display the "AnnotationDefinition" > annotation > > DataInputStream dstream = new DataInputStream(new > BufferedInputStream(new FileInputStream(file.toFile()))); > ClassFile classFile = new ClassFile(dstream); > String className = classFile.getName(); > System.out.println("class name = "+className); > AnnotationsAttribute visible = (AnnotationsAttribute) > classfile.getAttribute(AnnotationsAttribute.visibleTag); > if (visible != null) { > System.out.println("visible="+visible.getName()); > System.out.println("num_annotations="+visible.numAnnotations()); > > System.out.println("annotation[0]="+visible.getAnnotations()[0].toString()); > } > > This gives the expected output: > > class name = com.example.pojos.AnnotatedPojo > visible=RuntimeVisibleAnnotations > num_annotations=1 > > annotation[0][email protected](value="ValueOfTheAnnotation") > > > > ---------------------------------------------------------------------------------------- > Content of AnnotationDefinition.java: > > package com.example.annotation; > import java.lang.annotation.*; > @Target({ ElementType.TYPE }) > @Retention(RetentionPolicy.RUNTIME) > @Documented > public @interface AnnotationDefinition { > String value(); > } > > ---------------------------------------------------------------------------------------- > > > Now I attempt to load the class and find the annotation by reflection: > > > URL[] urls = { (new File(rootFolder)).toURI().toURL() }; > ClassLoader loader = new URLClassLoader(urls); > Class<?> cls = loader.loadClass(className); > > System.out.println("\nclass loaded in ParseApp.execute()= " + > cls.getName()); > Annotation[] annotations = cls.getAnnotations(); > if (annotations.length > 0) { > for (Annotation annotation : annotations) { > System.out.println("\t" + annotation); > } > } else { > System.out.println("\t" + "no annotations found"); > } > > > This also gives the expected output: > > class loaded in ParseApp.execute()= com.example.pojos.AnnotatedPojo > Annotations: > > @com.example.annotation.AnnotationDefinition(value=ValueOfTheAnnotation) > > > The problem occurs when I call the above ParserApp.processAllClassFiles > method from inside a maven plugin > > > /** > * Parse .class files. > * > * @goal process-classes > * > * @phase process-classes > * > * @requiresDependencyResolution compile+runtime > * @requiresProject false > * > * > */ > > public class ParserMojo extends AbstractMojo { > ... > /** > * > * @parameter expression="${project.compileClasspathElements}" > * @required > * @readonly > */ > private List<?> classpathElements; > > @Override > public void execute() throws MojoExecutionException { > > getLog().info("Processing class files in " + rootClassFolders[0]); > for (Object cpe:classpathElements) { > getLog().info((CharSequence) cpe.toString()); > } > > getLog().info("---------------------------------------------------------"); > > try { > ParserApp.processAllClassFiles(rootClassFolder); > } catch (IOException e) { > e.printStackTrace(); > } > } > } > > > The relevant part of the output is: > > [INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ > using-maven-plugin-test --- > [INFO] Nothing to compile - all classes are up to date > [INFO] > [INFO] --- process-classes-maven-plugin:1.0.1-SNAPSHOT:process-classes (0) > @ using-maven-plugin-test --- > [INFO] Processing class files in > C:\Users\tmcd\workspaces\minimal_plugin_classloader\using-the-maven-plugin\target\classes > [INFO] > C:\Users\tmcd\workspaces\minimal_plugin_classloader\using-the-maven-plugin\target\classes > [INFO] > C:\Users\tmcd\.m2\repository\com\example\process-classes-maven-plugin\1.0.1-SNAPSHOT\process-classes-maven-plugin-1.0.1-SNAPSHOT.jar > [INFO] > C:\Users\tmcd\.m2\repository\org\apache\maven\maven-plugin-api\2.0\maven-plugin-api-2.0.jar > [INFO] > C:\Users\tmcd\.m2\repository\com\example\annotation-processor\1.0.1-SNAPSHOT\annotation-processor-1.0.1-SNAPSHOT.jar > [INFO] C:\Users\tmcd\.m2\repository\javassist\javassist\3.12.1.GA > \javassist-3.12.1.GA.jar > [INFO] > C:\Users\tmcd\.m2\repository\com\example\required-annotations\1.0.1-SNAPSHOT\required-annotations-1.0.1-SNAPSHOT.jar > [INFO] --------------------------------------------------------- > > > processing com.example.pojos.AnnotatedPojo > class name = com.example.pojos.AnnotatedPojo > visible=RuntimeVisibleAnnotations > num_annotations=1 > > annotation[0][email protected](value="ValueOfTheAnnotation") > > class loaded in ParseApp.execute()= com.example.pojos.AnnotatedPojo > Annotations: > no annotations found > > > Note: the jar containing the annotation is > "required-annotations-1.0.1-SNAPSHOT.jar" in in > "${project.compileClasspathElements}" > > The annotation is found in the .class bytecode > num_annotations=1 > > annotation[0][email protected](value="ValueOfTheAnnotation" > > BUT the annotation is nolonger found in the loaded class: > > class loaded in ParseApp.execute()= com.example.pojos.AnnotatedPojo > Annotations: > no annotations found > > > The plugin jar > process-classes-maven-plugin-1.0.1-SNAPSHOT.jar > has a dependency on > annotation-processor-1.0.1-SNAPSHOT.jar (which contains the > ParserApp class) > which has a dependency on > required-annotations-1.0.1-SNAPSHOT.jar > > I have tried placing the dependency on the required annotation > > <dependency> > <groupId>com.example</groupId> > <artifactId>required-annotations</artifactId> > <version>1.0.1-SNAPSHOT</version> > </dependency> > > directly into the plugin pom > and also into the <build><plugins> section of the independent project > which uses the plugin > > <build> > <plugins> > <plugin> > <groupId>com.example</groupId> > <artifactId>process-classes-maven-plugin</artifactId> > <version>${project.version}</version> > <executions> > <execution> > <id>0</id> > <phase>process-classes</phase> > <goals> > <goal>process-classes</goal> > </goals> > </execution> > </executions> > <dependencies> > <dependency> > <groupId>com.example</groupId> > <artifactId>required-annotations</artifactId> > <version>1.0.1-SNAPSHOT</version> > </dependency> > </dependencies> > </plugin> > <plugin> > <groupId>org.apache.maven.plugins</groupId> > <artifactId>maven-compiler-plugin</artifactId> > <version>2.5.1</version> > <configuration> > <source>1.7</source> > <target>1.7</target> > </configuration> > </plugin> > </plugins> > </build> > > However I am still failing to find the annotation in the loaded class file. > I assume the problem has something to do with loading the files inside the > maven container? > > Any advice for solving this problem would be appreciated. > > Best regards, > > Tom McDermott > > > > >
