I am trying to build a single uber-jar from a set a modules that are mostly independent, but it's not working the way I'd thought.
I was initially directed here: https://maven.apache.org/plugins/maven-assembly-plugin/examples/multimodule/module-binary-inclusion-simple.html though now I'm not quite certain that this was what I should have started with...
The parent pom 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.mycompany</groupId>
<artifactId>BigProject</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<name>BigProject</name>
<modules>
<module>../mod1</module>
<module>../mod2</module>
<!-- ...a bunch more... -->
<module>../distribution</module>
</modules>
<build>
<pluginManagement>
<plugins>
<!-- not even sure why this needs to be specified here, but the documentation seems to think it's important... -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptors>
<descriptor>src/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
The pom for the "distribution" module 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>
<artifactId>distribution</artifactId>
<name>distribution</name>
<packaging>pom</packaging>
<parent>
<groupId>com.mycompany</groupId>
<artifactId>BigProject</artifactId>
<version>0.0.1</version>
</parent>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>distro-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
And finally, the assembly file:
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>bin</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<moduleSets>
<moduleSet>
<includeSubModules>true</includeSubModules>
<useAllReactorProjects>true</useAllReactorProjects>
<includes>
<include>com.myCompany:mod1</include>
<include>com.myCompany:mod2</include>
<!-- and others... -->
</includes>
<binaries>
<includeDependencies>true</includeDependencies>
<outputDirectory>modules/maven-assembly-plugin</outputDirectory>
<unpack>false</unpack>
</binaries>
</moduleSet>
</moduleSets>
</assembly>
(I realize that at some point I will probably need to change <format>dir</format> to <format>jar</format> but for now, I'd just like to get something working)
When I run mvn clean package from the main parent module's directory, I get warnings like this:
[INFO] Reading assembly descriptor: src/assembly/assembly.xml
[WARNING] The following patterns were never triggered in this artifact inclusion filter:
o 'com.myCompany:mod1'
o 'com.myCompany:mod2'
...
Followed by the error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-assembly-plugin:3.1.0:single (distro-assembly) on project distribution: Failed to create assembly: Error creating assembly archive bin: archive cannot be empty -> [Help 1]
What I actually want:
One jar file containing all of my modules, and all of their dependencies (that is, the *-with-dependencies.jars), as a single jar file with everything contained inside.
I'm really not sure how to achieve this in a multi-module context.
I think I may have resolved it: the child modules mod1, mod2, ... were missing the parent module dependency. I've added
<parent>
<groupId>com.mycompany</groupId>
<artifactId>BigProject</artifactId>
<version>0.0.1</version>
</parent>
to the relevant child modules and now the build doesn't fail, but populates the target directory under the distribution project.
Related
I am trying to find a good example on how you would build multiple zip files for a multi-module project with several runnable components using the maven-assembly-plugin.
My end result would hopefully have a single "dist" component that is capable of building all the necessary zip files.
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>xyz.exampleproject</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<name>Project Distribution</name>
<artifactId>dist</artifactId>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>component1-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>component2-core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-bundles</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
I would add one extra module per zip file that you want to create and configure the assembly plugin in there.
I am trying to create an executable jar for my multi-module maven project. I used the maven-assembly-plugin to generate the jar.
Even though am getting the jar created, am getting the ClassNotFound exception while trying to run the jar file using java -jar command.
Use the shade plugin, much easier than assembly.
Parent pom to hold it all together:
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.greg</groupId>
<artifactId>fat-jar</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>library-jar</module>
<module>final-jar</module>
</modules>
</project>
Final build jar pom, with dependency to library:
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>fat-jar</artifactId>
<groupId>com.greg</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>final-jar</artifactId>
<dependencies>
<dependency>
<groupId>com.greg</groupId>
<artifactId>library-jar</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.greg.App</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
There is some mistake in you descriptor or how you are using the assembly plugin.
A jar file is like a zip, just open your jar and find your class, if you don't find it then check your pom file or descriptor to understand why.
I'm building a java service which has two distribution. Each distribution must be build different (one has a spring-boot embedded jetty server inside, the other not). In both, I created a distribution with dependencies, except one (already achieved). The jar without jetty is build using maven-assembly-plugin (similarly as here Problems running executable jar with dependencies) the other one uses spring-boot-maven-plugin (see http://docs.spring.io/spring-boot/docs/current/maven-plugin/usage.html). My issue is the external dependencies.
I want add an additional dependency on runtime, but I DON'T WANT TO US OSGi
In both building process the result is a 'executable' jar, which I can run like this:
java -jar my.jar
But I don't know how to address the additional dependencies. If I run the command above without a the external dependency (lets say external.jar) inside my.jar will fail, even if is in the same folder. I can make it work for the distribution without jetty like this:
java -classpath "./*" my.main.App
But this doesn't work for my-with-jetty.jar. I also try to run:
java -classpath "./*" -jar my-with-jetty.jar
This simply doesn't work.
So my question are:
is it possible to pack a jar with almost all the dependencies for both cases?
is it possible to pack the jar as runnable jar such that it not necessary to provide the main class?
of course if yes, how? I would like to run both distribution in the same manner.
I want similar behavior:
java -cp "./*" java -jar my.jar conf.cfg
and
java -cp "./*" java -jar my-rest.jar conf.cfg
Thank you.
You need at least 3 maven projects all under the same parent so they get built together and have the same version. All your code will be in the shared project, this will be included in both runnable jar projects. Each runnable jar project will be build differently.
Your parent pom will be something like :
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>foo.bar</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>shared-jar</module>
<module>spring-boot-jar</module>
<module>jetty-jar</module>
</modules>
</project>
Your shared-jar project will have all the shared code
Your spring-boot-jar will look like :
<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>
<parent>
<groupId>foo.bar</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-jar</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>foo.bar</groupId>
<artifactId>shared-jar</artifactId>
<version>${project.version}</version>
</dependency>
.... you will need to add all the spring boot dependencies with versions
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Your jetty-jar will be built using the
<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>
<parent>
<groupId>foo.bar</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>jetty-jar</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>foo.bar</groupId>
<artifactId>shared-jar</artifactId>
<version>${project.version}</version>
</dependency>
.... other dependencies
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<!-- <Main-Class>foo.bar.Application</Main-Class> -->
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
We have a multi module maven project where the sonar-maven-plugin and jacoco maven-plugin are defined in the parent pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<configuration>
<destFile>${sonar.jacoco.reportPath}</destFile>
<append>true</append>
<excludes>
<exclude>**/generated/**</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>2.5</version>
</plugin>
Now we have a submodule common, containing again other submodules:
In the submodule common, the maven structure is as follows:
<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">
<parent>
<groupId>be.groupname</groupId>
<artifactId>artifactname</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>be.groupname</groupId>
<artifactId>common-master</artifactId>
<name>Common - Master</name>
<packaging>pom</packaging>
<modules>
<module>bindings</module>
<module>core</module>
<module>tools</module>
</modules>
</project>
The submodule core has the following maven structure:
<?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/xsd/maven-4.0.0.xsd">
<parent>
<groupId>be.groupid</groupId>
<artifactId>common-master</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common-core</artifactId>
<name>Common - Core</name>
<packaging>jar</packaging>
...
</project>
Now my question, in my SonarQube report, I see the uncovered lines:
The common master project contains all the uncovered lines from the submodules (common-core,...). I would expect that only the common core module would contain those lines.
In the filesystem, I see a jacoco.exec is generated under the common/target folder.
In the subdirectory common, I don't see this file being created but instead I see a file common/core/target/sonar/jacoco-overall.exec
I am using the maven-shade-plugin to combine two seperate jars into a single combined jar.
One of the jars is signed, while the other is not.
If I use the default configuration of the plugin, it will build a broken jar as the new manifest is missing the digest needed by the signature.
I could "fix" the jar by excluding the signature files, but this will of course result in a completely unsigned jar.
I am looking for a way to create a combined jar with all the signed classes remaining signed and valid. - The jar format allows those kind of jars but I could not find an easy way to tell the shade plugin to do so.
Should I write my own transformer to do a proper merging of manifest files or is there already a suitable option in the shade-plugin I did not find, yet?
Example:
pom.xml (defining two modules "foo" and "bar")
<?xml version="1.0"?>
<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>mygroup</groupId>
<artifactId>myparent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modules>
<module>foo</module>
<module>bar</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
foo/pom.xml: (combine signed bar into unsigned foo)
<?xml version="1.0"?>
<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>
<parent>
<groupId>mygroup</groupId>
<artifactId>myparent</artifactId>
<version>1.0</version>
</parent>
<artifactId>foo</artifactId>
<dependencies>
<dependency>
<groupId>mygroup</groupId>
<artifactId>bar</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>Foo</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
bar/pom.xml: (create signed bar)
<?xml version="1.0"?>
<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>
<parent>
<groupId>mygroup</groupId>
<artifactId>myparent</artifactId>
<version>1.0</version>
</parent>
<artifactId>bar</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<keystore>${user.home}/keystore-name</keystore>
<alias>alias-name</alias>
<storepass>123456</storepass>
</configuration>
<executions>
<execution>
<id>sign</id>
<goals>
<goal>sign</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
If both modules contain a single hello-word class, I would expect java -jar foo/target/foo-1.0.jar to work and jarsigner -verify foo/target/foo-1.0.jar to tell about the presence of signed classes.
The maven shade plugin does not play nicely with signed jars. I would recommend you take a look at Capsule that is way better to do this kind of job.