Maven java.lang.NoClassDefFoundError

Usually you get this error in Maven because there are jars that exist in compile dependency scope but not in runtime scope.

So a successful compilation doesn't guarantee a successful execution. This may be a surprise for many people, because if a dependency is needed at compile time, it is also needed at runtime, many of us would think this should be default.

The following command will display the dependencies of compile scope.

 
mvn -DincludeScope=compile dependency:build-classpath
 

The compile scope is displayed as below.

 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ GetPage ---
[WARNING] The artifact xml-apis:xml-apis:jar:2.0.2 has been relocated to xml-apis:xml-apis:jar:1.0.b2
[INFO] mygroup:GetPage:jar:1
[INFO] +- antlr:antlr:jar:2.7.4:system
[INFO] +- org.mozilla.intl:chardet:jar:1.0:system
[INFO] +- commons-codec:commons-codec:jar:1.6:system
[INFO] +- cpdetector:cpdetector:jar:1.0.10:system
[INFO] +- net.sf.cssbox:jstyleparser:jar:1.16:system
[INFO] +- ch.qos.logback:logback-core:jar:0.9.9:system
[INFO] +- net.sourceforge.nekohtml:nekohtml:jar:1.9.13:system
[INFO] +- org.slf4j:slf4j-api:jar:1.5.2:system
[INFO] +- org.slf4j:slf4j-nop:jar:1.5.2:system
[INFO] +- xerces:xercesImpl:jar:2.9.0:system
[INFO] \- xml-apis:xml-apis:jar:1.3.02:system
[INFO] ------------------------------------------------------------------------
 

To check the runtime scope dependencies, run the following command

 
mvn -DincludeScope=compile dependency:build-classpath
 

The output suggests that "No dependencies found", that's why java.lang.NoClassDefFoundError is thrown.

 
[INFO] --- maven-dependency-plugin:2.8:build-classpath (default-cli) @ GetPage ---
[WARNING] The artifact xml-apis:xml-apis:jar:2.0.2 has been relocated to xml-apis:xml-apis:jar:1.0.b2
[INFO] No dependencies found.
[INFO] Dependencies classpath:
 
[INFO] ------------------------------------------------------------------------
 

There is no dependencies found because all our dependencies here are system scoped. Here is what official documentation say about system scope:

A dependency with provided scope is added to the classpath used for compilation and test, but not the runtime classpath. The system scope is similar to provided except that you have to provide the JAR which contains it explicitly

Like provided scope, dependencies with system scope is only visible for compilation and test.

One of the solution is to declare the runtime classpath scope as compile

 
mvn exec:java -Dexec.classpathScope=compile -Dexec.mainClass="test.Test"