NoClassDefFoundError: org/junit/AfterClass during annotation processing
I am generating code with CodeModel during annotation processing with maven. That code is for JUnit testing:
JMethod tearDownClass = testClass.method(
JMod.PUBLIC | JMod.STATIC, Void.class, "tearDownClass");
tearDownClass._throws(Exception.class);
tearDownClass.annotate(AfterClass.class); <- java.lang.NoClassDefFoundError
Yet, the compilation process throws a java.lang.NoClassDefFoundError : org/junit/AfterClass
when it tries to retrieve the AfterClass.class
, which is an annotation itself.
The dependency to JUnit is defined as following:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
</dependency>
so AfterClass.class
should be available in my code.
How do I solve this one?
Unclear
The code calling codemodel is in a compiled library where junit is not a 'test' dependency. However, the code calling the generating code has the same junit dependency, but as a test dependency.
If I change that latter dependency to 'not-a-test' dependency, the issue disappears. Why do I have to define this dependency as 'not-a-test' though only the library calling codemodel is explicitely using it?
EDIT
Here is the dependency tree:
net.dwst:codegentest:jar:1.0.0
+- junit:junit:jar:4.8.2:compile
+- org.sonatype.maven.plugin:emma-maven-plugin:jar:1.2:test
| +- emma:emma:jar:2.0.5312:test
| \- org.apache.maven.reporting:maven-reporting-impl:jar:2.0.4:test
| +- commons-validator:commons-validator:jar:1.2.0:test
| | +- commons-beanutils:commons-beanutils:jar:1.7.0:test
| | +- commons-digester:commons-digester:jar:1.6:test
| | | \- commons-collections:commons-collections:jar:2.1:test
| | \- commons-logging:commons-logging:jar:1.0.4:test
| +- org.apache.maven.doxia:doxia-core:jar:1.0-alpha-7:test
| +- oro:oro:jar:2.0.7:test
| \- org.apache.maven.doxia:doxia-site-renderer:jar:1.0-alpha-7:test
| +- org.codehaus.plexus:plexus-i18n:jar:1.0-beta-6:test
| +- org.codehaus.plexus:plexus-velocity:jar:1.1.2:test
| | +- commons-logging:commons-logging-api:jar:1.0.4:test
| | \- velocity:velocity:jar:1.4:test
| | \- velocity:velocity-dep:jar:1.4:test
| \- org.apache.maven.doxia:doxia-decoration-model:jar:1.0-alpha-7:test
+- net.dwst:generics:jar:1.3.0:compile
| +- org.swinglabs:swing-layout:jar:1.0.3:compile
| \- com.sun.codemodel:codemodel:jar:2.4.1:compile
+- net.flat:flat:jar:1.3.0:compile
| \- com.pyx4me:proguard-maven-plugin:jar:2.0.4:compile
| +- ant:ant:jar:1.6.5:compile
| +- org.apache.maven:maven-archiver:jar:2.3:compile
| +- org.codehaus.plexus:plexus-archiver:jar:1.0-alpha-9:compile
| \- org.codehaus.plexus:plexus-io:jar:1.0-alpha-1:compile
+- org.codehaus.mojo:build-helper-maven-plugin:jar:1.7:compile
| +- org.apache.maven:maven-model:jar:2.0.6:compile
| +- org.apache.maven:maven-project:jar:2.0.6:compile
| | +- org.apache.maven:maven-settings:jar:2.0.6:compile
| | +- org.apache.maven:maven-profile:jar:2.0.6:compile
| | +- org.apache.maven:maven-artifact-manager:jar:2.0.6:compile
| | +- org.apache.maven:maven-plugin-registry:jar:2.0.6:compile
| | \- org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1:compile
| +- org.apache.ma开发者_高级运维ven:maven-core:jar:2.0.6:compile
| | +- org.apache.maven.wagon:wagon-file:jar:1.0-beta-2:runtime
| | +- org.apache.maven:maven-plugin-parameter-documenter:jar:2.0.6:compile
| | +- org.apache.maven.wagon:wagon-http-lightweight:jar:1.0-beta-2:runtime
| | | +- org.apache.maven.wagon:wagon-http-shared:jar:1.0-beta-2:runtime
| | | \- xml-apis:xml-apis:jar:1.0.b2:runtime
| | +- org.apache.maven.reporting:maven-reporting-api:jar:2.0.8:compile
| | | \- org.apache.maven.doxia:doxia-sink-api:jar:1.0-alpha-7:compile
| | +- org.apache.maven.wagon:wagon-provider-api:jar:1.0-beta-2:compile
| | +- org.apache.maven:maven-repository-metadata:jar:2.0.6:compile
| | +- org.apache.maven:maven-error-diagnostics:jar:2.0.6:compile
| | +- commons-cli:commons-cli:jar:1.0:compile
| | +- org.apache.maven.wagon:wagon-ssh-external:jar:1.0-beta-2:runtime
| | | \- org.apache.maven.wagon:wagon-ssh-common:jar:1.0-beta-2:runtime
| | +- org.apache.maven:maven-plugin-descriptor:jar:2.0.6:compile
| | +- org.codehaus.plexus:plexus-interactivity-api:jar:1.0-alpha-4:compile
| | +- org.apache.maven:maven-monitor:jar:2.0.6:compile
| | +- org.apache.maven.wagon:wagon-ssh:jar:1.0-beta-2:runtime
| | | \- com.jcraft:jsch:jar:0.1.27:runtime
| | \- classworlds:classworlds:jar:1.1:compile
| +- org.apache.maven:maven-plugin-api:jar:2.0.6:compile
| +- org.apache.maven:maven-artifact:jar:2.0.6:compile
| \- org.codehaus.plexus:plexus-utils:jar:1.5.8:compile
\- org.bsc.maven:maven-processor-plugin:jar:2.0.3:compile
\- org.jfrog.maven.annomojo:maven-plugin-tools-anno:jar:1.4.0:compile
+- org.jfrog.maven.annomojo:maven-plugin-anno:jar:1.4.0:compile
+- org.apache.maven.plugin-tools:maven-plugin-tools-api:jar:2.6:compile
| \- jtidy:jtidy:jar:4aug2000r7-dev:compile
\- com.sun:tools:jar:1.5.0:system
Very strange:
+- net.dwst:generics:jar:1.3.0:compile
| +- org.swinglabs:swing-layout:jar:1.0.3:compile
| \- com.sun.codemodel:codemodel:jar:2.4.1:compile
does not contain org.junit
, yes this library's pom.xml has:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
</dependency>
...
If I understand your situation correctly, what you have is two libraries (A and B):
A is the code that calls codemodel. This has a dependency on junit 4.8.2 (compile scope).
B is the code that calls A (the generating code). This has a dependency on junit 4.8.2 (test scope).
B has a dependency on A, obviously.
From Maven Dependency Scope, we have the following line,
Each of the scopes (except for import) affects transitive dependencies in different ways, as is demonstrated in the table below. If a dependency is set to the scope in the left column, transitive dependencies of that dependency with the scope across the top row will result in a dependency in the main project with the scope listed at the intersection. If no scope is listed, it means the dependency will be omitted.
A transitive dependency is one that comes from a direct dependency. So library X depends upon library Y. Library Y depends upon library Z. So Z is a transitive dependency of library X.
In your case, B both directly depends upon junit (with test scope) and has a transitive dependency through A on junit (with compile scope). If we read the table, we can see that this means that the scope that takes precendence is test. This is why your code is failing to find AfterClass.class, because it won't be included.
Your best bet is to set the scope to compile as you have already tried.
精彩评论