Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating Two Executable Jars Using maven-assembly-plugin

I have a Maven project and I want to create two executable jar files from it. One will be used interactively by users and a second will be run as a scheduled job that reads the log files produced by the former. In the end, I would expect the two jar files to be identical except for the Main-Class attribute in the MANIFEST.MF file.

I am using maven-antrun-plugin to create an executable jar and this seemed to be working fine until I tried to create a second jar file by introducing Maven profiles. The relevant section of my POM file looks like this:

<profiles>     <profile>         <id>publisher</id>         <build>             <finalName>${project.artifactId}</finalName>             <plugins>                 ...                 <plugin>                     <artifactId>maven-assembly-plugin</artifactId>                     <version>2.4</version>                     <configuration>                         <appendAssemblyId>false</appendAssemblyId>                         <finalName>${project.artifactId}</finalName>                         <archive>                             <manifest>                                 <mainClass>fully.qualified.path.Publisher</mainClass>                             </manifest>                         </archive>                         <descriptorRefs>                             <descriptorRef>jar-with-dependencies</descriptorRef>                         </descriptorRefs>                     </configuration>                     <executions>                         <execution>                             <phase>package</phase>                             <goals>                                 <goal>single</goal>                             </goals>                         </execution>                     </executions>                 </plugin>             </plugins>         </build>     </profile>     <profile>         <id>logReader</id>         <build>             <finalName>${project.artifactId}</finalName>             <plugins>                 ...                 <plugin>                     <artifactId>maven-assembly-plugin</artifactId>                     <version>2.4</version>                     <configuration>                         <appendAssemblyId>false</appendAssemblyId>                         <finalName>${project.artifactId}-logReader</finalName>                         <archive>                             <manifest>                                 <mainClass>fully.qualified.path.LogReader</mainClass>                             </manifest>                         </archive>                         <descriptorRefs>                             <descriptorRef>jar-with-dependencies</descriptorRef>                         </descriptorRefs>                     </configuration>                     <executions>                         <execution>                             <phase>package</phase>                             <goals>                                 <goal>single</goal>                             </goals>                         </execution>                     </executions>                 </plugin>             </plugins>         </build>     </profile> </profiles> 

Really, the only difference between the two is the "finalName" and "mainClass" elements as defined within the plugin.

When I try to execute mvn:package on both profiles (I'm using IntelliJ IDEA, by the way), I get two .jar files, but one is correct and the other is incorrect. The "correct" one contains all the dependencies and a valid MANIFEST.MF file. The "incorrect" one contains no dependencies and the MANIFEST.MF file lacks the "Main-Class" property that I need in order for it to be executable.

I have found that if I ever run just one profile or the other, that it works fine but, if I try to execute both profiles at once, it fails. I also get the following notes in my log, but I must admit that I don't completely understand what they are saying:

[INFO] Building jar: .../target/publisher.jar ... [INFO] Building jar: .../target/publisher-logReader.jar [WARNING] Configuration options: 'appendAssemblyId' is set to false, and 'classifier' is missing. Instead of attaching the assembly file: .../target/publisher-logReader.jar, it will become the file for main project artifact. NOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic! [WARNING] Replacing pre-existing project main-artifact file: .../target/publisher.jar with assembly file: .../target/publisher-logReader.jar 

Any thoughts about this? Is it possible to produce two jar files with a single mvn:package in this way, or am I barking up the wrong tree?

Thanks!

like image 807
McGlone Avatar asked Apr 03 '13 21:04

McGlone


People also ask

How can I create an executable jar with dependencies?

You could combine the maven-shade-plugin and maven-jar-plugin . The maven-shade-plugin packs your classes and all dependencies in a single JAR file. Configure the maven-jar-plugin to specify the main class of your executable JAR file (see Set Up The Classpath, chapter "Make The Jar Executable").

How do I create an executable jar file?

In Eclipse you can do it simply as follows : Right click on your Java Project and select Export. Select Java -> Runnable JAR file -> Next. Select the Destination folder where you would like to save it and click Finish.

What is the use of Maven Assembly plugin?

The Assembly Plugin for Maven enables developers to combine project output into a single distributable archive that also contains dependencies, modules, site documentation, and other files. Your project can easily build distribution "assemblies" using one of the prefabricated assembly descriptors.


1 Answers

So as soon as I posted this, I found this thread:

Create multiple runnable Jars (with depencies included) from a single Maven project

This uses a different approach in that it doesn't use two profiles, it uses two executions, as such:

<plugin>     <artifactId>maven-assembly-plugin</artifactId>     <version>2.4</version>     <executions>         <execution>             <id>build-publisher</id>             <configuration>                 <appendAssemblyId>false</appendAssemblyId>                 <archive>                     <manifest>                         <mainClass>fully.qualified.path.Publisher</mainClass>                     </manifest>                 </archive>                 <descriptorRefs>                     <descriptorRef>jar-with-dependencies</descriptorRef>                 </descriptorRefs>                 <finalName>${project.artifactId}</finalName>             </configuration>             <phase>package</phase>             <goals>                 <goal>single</goal>             </goals>         </execution>         <execution>             <id>build-logReader</id>             <configuration>                 <appendAssemblyId>false</appendAssemblyId>                 <archive>                     <manifest>                         <mainClass>fully.qualified.path.LogReader</mainClass>                     </manifest>                 </archive>                 <descriptorRefs>                     <descriptorRef>jar-with-dependencies</descriptorRef>                 </descriptorRefs>                 <finalName>${project.artifactId}-logReader</finalName>             </configuration>             <phase>package</phase>             <goals>                 <goal>single</goal>             </goals>         </execution>     </executions> </plugin> 

This seems to be working. The moral of the story seems to be that I don't completely understand profiles or when they should be used.

like image 149
McGlone Avatar answered Oct 11 '22 08:10

McGlone