Maven not setting classpath for dependencies properly

橙三吉。 提交于 2019-12-03 07:03:20

问题


OS name: "linux" version: "2.6.32-27-generic" arch: "i386" Family: "unix"

Apache Maven 2.2.1 (r801777; 2009-08-06 12:16:01-0700)

Java version: 1.6.0_20

I am trying to use the mysql dependency in with maven in ubuntu. If I move the "mysql-connector-java-5.1.14.jar" file that maven downloaded into my $JAVA_HOME/jre/lib/ext/ folder, everything is fine when I run the jar.

I think I should be able to just specify the dependency in the pom.xml file and maven should take care of setting the classpath for the dependency jars automatically. Is this incorrect?

My pom.xml file looks like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.ion.common</groupId>
  <artifactId>TestPreparation</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>TestPrep</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>

        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <mainClass>com.ion.common.App</mainClass>
            </manifest>
          </archive>
        </configuration>

      </plugin>
    </plugins>
  </build>

  <dependencies>

    <!-- JUnit testing dependency -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <!-- MySQL database driver -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.14</version>
      <scope>compile</scope>
    </dependency>

  </dependencies>
</project>

The command "mvn package" builds it without any problems, and I can run it, but when the application attempts to access the database, this error is presented:

java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
        at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:186)
        at com.ion.common.Functions.databases(Functions.java:107)
        at com.ion.common.App.main(App.java:31)

The line it is failing on is:

Class.forName("com.mysql.jdbc.Driver");

Can anyone tell me what I'm doing wrong or how to fix it?


回答1:


Raghuram gave me a push in the right direction. The way to get maven to take care of copying the jars automatically is to add this code inside the tag in the pom.xml file:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
      <execution>
        <id>copy-dependencies</id>
        <phase>package</phase>
        <goals>
          <goal>copy-dependencies</goal>
        </goals>
        <configuration>
          <outputDirectory>${project.build.directory}</outputDirectory>
          <overWriteReleases>false</overWriteReleases>
          <overWriteSnapshots>true</overWriteSnapshots>
        </configuration>
      </execution>
    </executions>
  </plugin>

More details on this can be found here: https://maven.apache.org/plugins/maven-dependency-plugin/usage.html

Getting maven to package the jars together would be nice, but this is good enough to answer this question. Related answers on stackoverflow:

Building executable jar with maven?

How can I create an executable JAR with dependencies using Maven?




回答2:


I know this question is old, but it shows up at the top of searches for getting Maven to set dependencies properly with -SNAPSHOT versions and I had to refine the accepted solution to get my classpath resolution working correctly.

The problem I ran into was that the maven-jar-plugin included the resolvedVersion of a dependency (e.g. --.jar) while the maven-dependency-plugin (as of version 2.5.1) copies dependencies preserving their baseVersion --SNAPSHOT.jar). (See https://jira.codehaus.org/browse/MDEP-380 for more info about that enhancement.)

To get things working, I had to turn off this behaviour as follows:

    ...
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>dependency/</classpathPrefix>
                        <mainClass>com.example.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <useBaseVersion>false</useBaseVersion>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
    ...

This configuration caused the dependencies to be copied into ${project.build.directory}/dependency with their resolvedVersion matching the blasspath being set into the META-INF/MANIFEST.MF by the maven-jar-plugin. Hopefully this helps someone in the future.




回答3:


Maven does set the classpath to the dependencies correctly, but not prefixed with repository location. It will look like this in your Manifest file.

Class-Path: mysql-connector-java-5.1.14.jar

It is upto you to place the dependant jars in the same folder as the jar which you are running.

Refer to the examples




回答4:


Or if you are using maven-shade-plugin a workaround is to add a filter for including the missing files:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.1.0</version>
            <executions>
                <execution>
                    ...
                    <configuration>
                        ...
                        <filters>
                            ...                                
                            <filter>
                                <artifact>com.sun.istack</artifact>
                                <includes>
                                    <include>**</include>
                                </includes>
                            </filter>


来源:https://stackoverflow.com/questions/4687609/maven-not-setting-classpath-for-dependencies-properly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!