1

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>
Mahmoud Saleh
  • 33,303
  • 119
  • 337
  • 498

2 Answers2

2

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

Community
  • 1
  • 1
Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
  • thanks for such valuable answer, so what i get from it so far, is that maven can't load dependencies from inside a jar, but from an outside folder in the file system, and in order to do that i need to use this library http://one-jar.sourceforge.net/ ? – Mahmoud Saleh Dec 24 '11 at 12:53
  • and to make everything clear, what is the minimum configuration required to gather all dependencies in an external lib folder in file system. – Mahmoud Saleh Dec 24 '11 at 12:54
  • It's not Maven loading the dependencies. It's Java. Java always works like this. One-JAR is one way of packaging and running an app all from one jar. As to your second comment, maven assembly plugin will do that. You'd simply write a descriptor that puts all the compile-scoped dependencies into a `lib` folder. See [dependencySet](http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html#class_dependencySet). – Ryan Stewart Dec 24 '11 at 17:44
  • i was able to gather all dependencies in an external folder on file system with maven dependency plugin using above configuration too. – Mahmoud Saleh Dec 24 '11 at 20:08
0

The class is located in spring-context.jar. Add that dependency in the pom.xml.

Umesh Rajbhandari
  • 1,222
  • 9
  • 9
  • no, it's in spring-context-support.jar which is already added http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/context/support/ClassPathXmlApplicationContext.html – Mahmoud Saleh Dec 24 '11 at 02:50