i am working on a standalone application build with maven, and i add the dependencies to the target jar in a lib folder using maven-dependency-plugin with maven-assembly-plugin the application runs fine from eclipse with no problems, but when trying to run the generated jar file from command line, i am getting following exception:
Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/context/support/ClassPathXmlApplicationContext
at com.spring.sample.MainClass.main(MainClass.java:11)
Caused by: java.lang.ClassNotFoundException: org.springframework.context.support.ClassPathXmlApplicationContext
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
i looked inside the generated jar lib folder, and i found that the spring-context-support.jar is already there, so i am wondering why i am getting such exception.
here's my maven build configuration:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.myapp.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>install</id>
<phase>install</phase>
<goals>
<goal>sources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>create-my-bundle</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
You've got kind of a mess of a POM there, and you're building two jars.
One of the jars is built by first copying your dependencies into target/classes/lib
--a questionable practice to begin with--and letting the default execution of the jar plugin build its normal jar. This jar has all your code in it like a normal jar but also has all your dependency jars inside it at /lib
. It also has a manifest that specifies a Main-Class
and a Class-Path
listing all the required jars at a relative path of lib/...jar
. It sounds like this is the one you're trying to run. The reason it can't find the classes it needs is that a class path for a standalone Java app is a list of folders or jar files on the file system that contain class files. In other words, it won't find jar files inside another jar file, which is what this you have. For this to work how you expect, you'd need a lib
directory right next to your jar file which has all the dependencies in it. This is what's causing your present problem.
The other jar is built by the assembly plugin. Because of your earlier antics with the dependency plugin, this one should also have all the dependency jars in it at /lib
, which I've already explained won't accomplish anything, but because of how the jar-with-dependencies
descriptor works, it will also have extracted all those jars and put all of their classes into your jar along with your own classes. If you were to run this jar, you'd probably get past the ClassNotFoundException, but there are well-known problems with "fat jars" like this that mean you shouldn't do this unless you have some really compelling reasons for it. One such problem is described in the following question:
Maven and Spring = Unable to create application context: Unable to locate Spring NamespaceHandler