How to merge module jars to a single jar in Maven2? - maven-2

I have a maven2 project with several jar modules, build the project will get .jar archives for each module in the directory modules/XYZ/target/XYZ-x.x.x.jar
Now, if my project P is of version P-p.q.r, and I want to generate a single jar P-p.q.r-all.jar with all sub-modules included in, how should I do?

What you want to achive is called uber jar. This module has to have dependecies of all others submodules you want to package into one jar. If you create another submodule that will produce a desired artifact it can be built in reactor with all its dependencies but if it will be a separate project that you have to install all uber jar dependecies.
| parent
| -- submodule1
...
| -- submoduleN
| -- uberjarSubmodule
Uber jar can be done by using:
maven-shade-plugin - in your case you have to remember to exclude transitive dependecies from your modules
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<excludes>
<exclude>classworlds:classworlds</exclude>
<exclude>junit:junit</exclude>
<exclude>jmock:jmock</exclude>
<exclude>xml-apis:xml-apis</exclude>
</excludes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
maven-assembly-plugin - in this question you'll find a detailed answer

Depends on how you are going to ship this, if your jar is a library that you want other developers to download and use via maven. You should specify these as dependencies in the projects pom.
If you are trying to ship something to an end-user who just wants to grab the binary and use your project, you could try using the assembly plugin to package your project. With this plugin you can package a jar alongside its dependencies. It won't put it all in a single jar file, but assuming you configure the users classpath correctly it shouldn't matter.

Related

Update Update-Site From Maven Repository

I have a normal Eclipse plug-in build with Tycho, and want to build an update site with the very same Tycho. My problem is figuring out how to get the artifact from its Maven GAVs (or optionally the JAR) into the update site.
What I tried:
<plugin>
<groupId>org.eclipse.tycho.extras</groupId>
<artifactId>tycho-p2-extras-plugin</artifactId>
<version>${tycho.version}</version>
<executions>
<execution>
<id>add-to-update-site</id>
<phase>install</phase>
<goals>
<goal>mirror</goal>
</goals>
<configuration>
<source>
<repository>
<url>${project.baseUri}/target/repository</url>
</repository>
</source>
<destination>${project.basedir}</destination>
<append>true</append>
</configuration>
</execution>
</executions>
</plugin>
This takes the repository from target/repository and merges it with the one in the base directory of the project. So every plug-in in target/repository will be added to the update site.
This works with a target platform file, but of course not with Maven GAVs or JAR. I tried adding the plug-in as a dependency and using dependency:copy-dependencies, but this will not create a P2 repository.
There is the plug-in tycho-p2-repository:assemble-repository, but I'm not sure it can help me create a P2 repository for tycho-p2-extras-plugin to consume. Or even as standalone.
I found reficio's p2-maven-plugin, which can generate P2 repositories from JARs, but it doesn't support Tycho at all.
I feel like I'm only one step away from a solution. So how do I build a P2 repository from Maven GAVs (or JAR files)?
That is not possible with Tycho. So I used the command line:
SET ECLIPSE_HOME=S:/Development/Eclipse 2018-12
SET EQUINOX_VERSION=1.5.200.v20180922-1751
SET CURRENT_PATH=%~dp0
SET SOURCE_REPOSITORY=%CURRENT_PATH%\dropin
SET TARGET_REPOSITORY=%CURRENT_PATH%\
java -jar "%ECLIPSE_HOME%/plugins/org.eclipse.equinox.launcher_%EQUINOX_VERSION%.jar"
-application org.eclipse.equinox.p2.publisher.FeaturesAndBundlesPublisher
-metadataRepository "file:/%TARGET_REPOSITORY%" -artifactRepository "file:/%TARGET_REPOSITORY%"
-source "%SOURCE_REPOSITORY%" -publishArtifacts -append
However I haven't been able to create categories, so the repository appears to be empty on default.

How to add jar Non-osgi jar files as dependency to eclipse plugin?

I am developing an eclipse plugin using tycho build ,It needs some non-osgi jar files as dependency.when I add the dependency in my pom file ,It does not take the dependency during maven build.
So, I have tried to make a osgi bundle which contains all the required dependencies by using the following Plugin.
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>1.4.0</version>
<extensions>true</extensions>
<configuration>
<manifestLocation>META-INF</manifestLocation>
<instructions>
<Bundle-SymbolicName>Osgi-bundle</Bundle-SymbolicName>
<Bundle-Name>Osgi-dependency</Bundle-Name>
<Bundle-Version>1.0.0</Bundle-Version>
<Export-Package>*</Export-Package>
<Private-Package>com.foo.bundle</Private-Package>
<Bundle-Activator>com.foo.bundle.Activator</Bundle-Activator>
<Import-Package>*;resolution:=optional</Import-Package>
<Embed-Dependency>*;scope=compile|runtime;inline=true</Embed-Dependency>
<Embed-Directory>target/dependency</Embed-Directory>
<Embed-StripGroup>true</Embed-StripGroup>
<Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
</plugin>
After that i have provided the dependency of this osgi bundle to the eclipse plugin .But still it does not take the dependency.
I have gone through lot of sites.But I am not able to get the solution for this maven build in continuous integration
But,When I tried creating new plugin project with existing jar and add the osgi bundle and export the plugin .Its work fine. But I am in need to maven continuous builds.
Please provide some solution to add the dependency to eclipse plugin project.
I have solved the problem by creating p2 repository and deployed it in the server.I have created a target definition file and linked it to my plugin project.
We can convert non osgi jars to p2 repository by using the following code.
<build>
<plugins>
<plugin>
<groupId>org.reficio</groupId>
<artifactId>p2-maven-plugin</artifactId>
<version>1.1.2-SNAPSHOT</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<artifacts>
<!-- specify your depencies here -->
<!-- groupId:artifactId:version -->
<artifact>
<id>org.slf4j:slf4j-log4j12:1.7.10</id>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
'
For detailed information this site is very helpfull.
http://www.vogella.com/tutorials/EclipseTycho/article.html#convertjars
One possible option is to download jars into separate folder using maven-dependency-plugin, configure classpath in manifest for OSGi bundle and do not forget to include jars in build.

Maven Assembly Plugin is not setting the MainClass manifest setting

I have a maven project which generates a jar via the maven assembly plugin I want to run as a console app. However, the MainClass attribute is not being set in MANIFEST.MF. Here is my plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>net.justaprogrammer.poi.cleanser.Cleanser</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
However, this does not get added to the MANIFEST.MF in the jar generated by mvn package. The manifest generated is below:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: zippy
Build-Jdk: 1.6.0_25
What am I doing wrong?
I missed that you weren't generating your assembly on package. You have a jar project, so Maven will build a jar using the maven-jar-plugin. You don't have to have anything in your pom to tell it that. That's Maven's convention-over-configuration working for you. The jar it builds will have only your project classes and resources in it. If you want to add a Main-Class to the manifest in that jar, you should configure the jar plugin to do so. Basically, just move that archive configuration to the jar plugin.
However, if you actually want to assemble an executable fat jar--that is, a jar that includes all of your classes as well as the classes of all of your dependencies--then you have the setting in the right place, but you need to actually run the assembly plugin either using mvn assembly:single or by binding that goal to a lifecycle phase. To be clear, if you do this, then your project will output two jars: one that contains your project files and one that contains that plus the contents of all the libraries that your project depends on. The former is built by the jar plugin. That latter is built by the assembly plugin. Note that fat jars aren't commonly used, and you can run into unusual problems when you use them because they're rather outside the realm of normal Java stuff.
For copy&paste fans like me, assembled from above answer, and http://maven.apache.org/plugins/maven-assembly-plugin/usage.html#Execution:_Building_an_Assembly:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.db.search.filenet.Load</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
If you happen to be using the maven shade plugin to build a fat jar (rather than or in addition to using the assembly plugin), it's worth noting that the shade plugin handles entires in the MANIFEST.MF file a bit differently; see the shade plugin's executable jar page.
You probably need to add the maven-jar-plugin configuration too and configure the MainClass there also. The assembly unpacks all JAR files (e.g. project jar and dependency jars) and I think that the last MANIFEST.MF found in the list of JAR files "overwrites" the expected/generated manifest.mf.

Best way to copy multi module project in maven

I have a maven project in which I would like to unpack all the child modules of a mutli module project. Does anyone know if the best way to approach this? There are over 100 modules in this project and I'm trying to avoid having to copy all this information somewhere else.
First you will need to create a pom.xml file that has all the projects as dependencies.
If there is one submodule that has
all other submodules as
dependencies, then you are in luck, just add a dependency to that submodule.
If not, you will have to write a script or program that gathers the groupIds, artifactIds, versions (and packagings) of all the submodules. And creates a pom.xml with all of them as dependencies.
Then, in this project, you can use dependency:unpack-dependencies to unpack the projects:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-projects</id>
<phase>generate-sources</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>com.basegroupId*</includeGroupIds>
</configuration>
</execution>
</executions>
</plugin>
(Set includeGroupIds to a pattern that matches all submodule groupIds)
Now you just have to call
mvn generate-sources
(or any other phase you configure in the execution)

how to control the pom.xml inside jar built by maven?

When maven builds a jar it places a pom.xml at META-INF///pom.xml.
This is the original pom of the artifact.
No variables are expanded or inherited and no inherited dependencies are listed.
This makes the information of the production jar dependent on the build environment.
How can the pom inside the jar be configured ?
Best would be some configuration of the maven-jar-plugin.
I had a similar requirement, as I wanted to get all the information that belongs to the parent pom.xml. In others words, I wanted to have, in addition to the "raw" pom.xml, the effective pom inside the JAR generated.
The idea is to use the help:effective-pom plugin and goal during the generation of the JAR, and put it with the pom.xml. This is done with this configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>effective-pom</goal>
</goals>
<configuration>
<output>${project.build.outputDirectory}/META-INF/maven/${project.groupId}/${project.artifactId}/effective-pom.xml</output>
</configuration>
</execution>
</executions>
</plugin>
(source)