How to tell Maven about creating an executable jar

It seems that it should be simple, but I did not understand this and did not get much help from reading documents and searching the Internet. In an attempt to learn how to use Maven (2.2.1) with a multi-module project, I used Maven to create a simple P project with class C (containing the main one) and subclass S. When I run mvn install , it builds and displays a BUILD SUCCESSFUL message. However, when I run the resulting C-box, I get an exception: "Exception in thread" main "java.lang.NoClassDefFoundError: P / S"

Directory structure (not displaying src subdirectories, etc.):

P
|
-C | -S

pom.xml in the P directory currently:

 <?xml version="1.0" encoding="UTF-8"?> <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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>P</groupId> <artifactId>P</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <name>P</name> <url>http://maven.apache.org</url> <dependencyManagement> <dependencies> <dependency> <groupId>P</groupId> <artifactId>C</artifactId> <version>${project.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>P</groupId> <artifactId>S</artifactId> <version>${project.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>PC</mainClass> <packageName>PC</packageName> </manifest> </archive> </configuration> </plugin> </plugins> </build> <modules> <module>C</module> <module>S</module> </modules> </project> 

pom.xml in C:

 <?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>P</artifactId> <groupId>P</groupId> <version>1.0-SNAPSHOT</version> </parent> <groupId>P</groupId> <artifactId>C</artifactId> <version>1.0-SNAPSHOT</version> <name>C</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>P</groupId> <artifactId>S</artifactId> <version>${project.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project> 

and pom.xml in S:

 <?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>P</artifactId> <groupId>P</groupId> <version>1.0-SNAPSHOT</version> </parent> <groupId>P</groupId> <artifactId>S</artifactId> <version>1.0-SNAPSHOT</version> <name>S</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project> 

The above are all the latest versions after several attempts.

For this simple training exercise, the Java classes:

P / C / SRC / Main / Java / P / C.java:

 package P; public class C { public static void main( String[] args ) { System.out.println( "Hello World!" ); S o = new S(); o.sayHey(); } } 

and S / src / main / java / P / S.java:

 package P; public class S { public void sayHey() { System.out.println("Hey!"); } } 

So, how can I tell Maven to include class S in jar C?

+1
source share
3 answers

After further research, I found a way to tell Maven to create a jar file that includes all the necessary classes. The only estate I had to change was in the P directory. First, the next section was to be removed from the build-plugins section:

  <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>PC</mainClass> <packageName>PC</packageName> </manifest> </archive> </configuration> 

Instead, I set:

  <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <id>create-executable-jar</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>PC</mainClass> <packageName>PC</packageName> </manifest> </archive> </configuration> </execution> </executions> 
+3
source

Maven does not include dependencies in artifacts by default: to run P you still need S in your classpath.

This is usually not a problem, since maven itself uses transitive dependencies: for example, if you have another project that depends on P, it automatically puts both P and S in your classpath.

If you want to create "uber-jar": a stand-alone jar containing all the dependencies, check out the "shade" plugin: http://maven.apache.org/plugins/maven-shade-plugin/

+3
source

The maven exec plugin can solve your problem. You can use it to run C.jar and it will control the classpath (and ensure that S.jar is included).

Add something similar to this to your p pom.xml:

 <project> ... <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.1</version> <executions> <execution> ... <goals> <goal>java</goal> </goals> </execution> </executions> <configuration> <mainClass>PC</mainClass> </configuration> </plugin> </plugins> </build> ... </project> 

Then you can run the program as follows:

 mvn exec:java -Dexec.mainClass="PC" 
+1
source

Source: https://habr.com/ru/post/1445815/


All Articles