maven embed dependency artifact code in jar - maven

I have a multi-module maven project. I have a main "base-code" module which creates a jar of all the compiled source code in my project.
I have another module, "executable", which creates an executable jar from the same source code. To avoid duplication I want to pull the classes in from the "base-code" module.
I thought that all I had to do was make the "base-code" module a dependency of the "executable" module to do this. But I just get an empty jar. What am I doing wrong?
(my "executable" pom is below)
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.myproject/groupId>
<artifactId>myproject</artifactId>
<version>1</version>
</parent>
<artifactId>executable</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.myproject/groupId>
<artifactId>code-base</artifactId>
<version>1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>runnable</finalName>
<archive>
<manifest>
<mainClass>com.myproject.Main</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

What you are looking for is probably uber-jar: a single jar file with all embedded jar dependencies, the newly version of maven-assembly-plugin support this as one of the 4 pre-defined descriptor, check out here.
Try using maven-assembly-plugin replace your maven-jar-plugin like this:
<!-- Create single executable jar with all dependencies unpacked and embedded -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.myproject.Main</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
<descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals><goal>single</goal></goals>
</execution>
</executions>
</plugin>
Alternatively, you can also use maven-shade-plugin to do this.
Hope that helps.

Related

Packaging custom javadoc doclet with maven

I've written my own java doclet and want to package it into a single jar file to use it later on.
I'm currently using maven with these settings to generate it:
<build>
<finalName>Doclet</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>de.test.tools.doclet.Doclet</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- Maven Assembly Plugin -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-my-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>de.test.tools.doclet.Doclet</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Problem:
Everything is properly packaged into the jar but my sources are missing.
If I try to do a simple mvn package it tells me that the sun package doesn't exist.
error: package com.sun.javadoc does not exist
I think the last part is the main reason behind why I can't find my sources in the jar and thus my question is how I can tell maven to ignore those imports.
The problem is that maven cannot find package com.sun.javadoc which is in the tools.jar in the /lib folder of the java installation dir.
Eclipse was able to execute it because I added it to the classpath there but maven had no idea where he can get the resources from. So adding the following system dependency solved the problem for me:
<dependency>
<scope>system</scope>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>YOUR_JAVA_VERSION</version>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
Replace the version with your version and make sure java home is known in your environment.
Note: This dependency doesn't work on MacOS. See: JDK tools.jar as maven dependency - Summary: Use Profiles for each OS to be able to specify the correct path.
I only need to support Linux + Windows so it is the best solution for me.

No main class in manifest with maven

I have my IntelliJ maven project and I am trying to build the jar but whenever I run it it throws no main manifest attribute, in Project.jar
Here is my pom.xml build. I am trying to set the main class in the manifest with Maven I read online to do it in the maven-compiler-plugin. When I open the jar in WinRar the manifest is generated by Apache Maven but has not got the main class.
<?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>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<archive>
<manifest>
<mainClass>com.bwfcwalshy.ssbbot.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Add the maven-jar-plugin and make sure you use the maven directory structure (src/main/java) for your java files.
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.bwfcwalshy.ssbbot.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
...

Maven multimodules w. assembly options per module?

I've a multimodule maven setup, where I'd like to pack one of the jars with their dependencies and all others could stay as they are. My configuration looks like this:
Root:
<project...>
<modelVersion>4.0.0</modelVersion>
<name>Foo</name>
<artifactId>Foo</artifactId>
<groupId>org.example</groupId>
<version>1.0</version>
<packaging>pom</packaging>
<modules>
<module>Bar1</module>
<module>Bar2</module>
<module>Bar3</module>
</modules>
</project>
Module (Bar1):
<project...>
<modelVersion>4.0.0</modelVersion>
<name>Foo - Bar1</name>
<artifactId>Bar1</artifactId>
<groupId>${project.parent.groupId}</groupId>
<parent>
<artifactId>Foo</artifactId>
<groupId>org.exmaple</groupId>
<version>1.0</version>
</parent>
<build>
<finalName>Bar1</finalName>
<plugins>
...
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>org.exmaple.bar1.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
...
</plugins>
</build>
</project>
With that running mvn package would give me all jar/war files for the modules. But to generate the jar with dependencies I have to switch into the module and trigger the assembly in addition cd Bar1; mvn assembly:single.
Is there any chance to change the setup so that after mvn package one of the jars is build with dependencies included?
Cheers.
Include the assembly plugin to the execution of the package phase:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptor>src/assembly/bin.xml</descriptor>
<finalName>apache-maven-cookbook-${pom.version}</finalName>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
As described on maven assembly page
You need to define an execution for the assembly plugin. Otherwise it won't be executed. The site of the plugin may be a bit misleading as there is a section on configuration which looks like yours. But if you want the execution to actually happen, you need to define it.

How to expose a dependency of a dependency in a maven project

I have a maven web application that is using a jar I created and is referenced as a dependency in my pom file.
The jar file I created has another jar file as a dependency.
When I deploy the web application, it says that a class in the dependency of the jar file I created cannot be found.
The only way to work around this was to add the dependency of the jar file as a dependency of the war file. This seems unnecessary.
Is there a way I can configure the war file to be able to see the classes defined in a dependency of a dependent jar file?
my jar pom file looks like: The dependency that has the class that can't be found is the the QRS one.
<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>group</groupId>
<artifactId>artifact</artifactId>
<packaging>jar</packaging>
<version>1.0.7</version>
<name>name</name>
<dependencies>
<dependency>
<groupId>group2</groupId>
<artifactId>QRS</artifactId>
<version>8.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<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>
my war pom looks like:
<dependency>
<groupId>group</groupId>
<artifactId>artifact</artifactId>
<version>1.0.7</version>
</dependency>
and the war plug in is configured:
<plugin>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<warName>${project.name}-${project.version}-${env}</warName>
<webResources>
<resource>
<directory>src/main/webapp/WEB-INF</directory>
<filtering>true</filtering>
<include>jboss-web.xml</include>
<include>web.xml</include>
<targetPath>/WEB-INF</targetPath>
</resource>
</webResources>
<warSourceExcludes>**/toAggregateAndRemove/**</warSourceExcludes>
<goal>war:manifest</goal>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
Maven already resolves transitive dependencies.
That it isn't indicates you're likely not doing it right: the other jar you've created should be a Maven project with its own pom, installed at least locally via mvn install, and listed as a dependency in the second project (the one that uses it).
The project using the jar only needs to specify that artifact as its dependency, the other project's dependencies will be transitively determined and included as a project dependency.
#Dave Newton has answered, this should happen by default.
A few observations from the snippets in the question - if that helps...
Packaging dependant jars as a folder of artifact project's jar.
Defining the maven war plugin jar itself as a dependency for maven war plugin - this is not required at all!
war:manifest goal in the maven war plugin configuration.
It is possible that the war:war which actually creates the war is not run.

Maven - Build with Dependencies [duplicate]

This question already has answers here:
How can I create an executable/runnable JAR with dependencies using Maven?
(33 answers)
Closed 9 years ago.
I've downloaded a source code from internet and I'm trying to build it with maven. Here is the pom.xml file that came with the source code:
<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>com.mycompany</groupId>
<artifactId>myArtifact</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>myArtifact</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>myArtifact.Main</mainClass>
</manifest>
</archive>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-701.jdbc4</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
The mvn install command is generating the jar file but I'm unable to execute this file because of the missing dependencies (class not found exception related to postgresql dependency in this example).
I've noticed that maven has downloaded the dependencies correctly (the jar libraries are all at the local maven repository directory) but mvn install is not copying these libraries into the generated jar file. How can I do this?
Thanks.
Remove the descriptorRefs and archive tag from your maven-compiler-plugin section.
In order to generate a JAR with all the dependencies self contained. You need to put this into the build plugins section of your pom.xml:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>
com.test.your.main.class.goes.Here
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Create the JAR file by running the following at the command prompt:
mvn clean compile assembly:single

Resources