Maven package in-project repository dependencies inside jar - java

I am using the in-project repository dependency solution to include a third party jar as a dependency in my Maven project. I'm following the instructions on this blog for that.
Now, I want that when I package my Maven project into a jar, the jar that is created should have a lib folder with the third party jar in it. However, I do NOT want the other dependencies to be packaged in the jar. (I don't want a fat jar with ALL dependencies packaged inside it, I just want a jar with the one third party dependency jar packaged inside it).
I have been trying to play around with the maven-dependency-plugin and the maven-jar-plugin, but I've not been able to achieve what I want.
Can someone please help me out?

You can use maven-dependency-plugin (look here) as shown below, this plugin will provide lots of options to include jars which ArtifactId (i.e., <includeArtifactIds>) or groupId (<includeGroupIds>), etc...
<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>
<includeArtifactIds>YOUR_THIRDPARTY_JAR_NAME</includeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>
So, the above code will add YOUR_THIRDPARTY_JAR_NAME.jar into your final .jar file's lib folder.

Take a look at Maven Assembly Plugin. It allows filtering included dependencie, so you can choose what deps to include in the assembly

Related

Create a jar artifact with minimal pom / parent pom.xml / flattened / regenerated pom [maven]

I have a multimodule maven project and distribute the resulting jar file to different parties. Part of the jar file is the pom.xml file (in META-INF/maven/.../pom.xml).
The problem with that is, that the parent pom.xml is missing which contains a complete list of the dependencies and the necessary dependency-versions etc.
So I tried several things:
Solution 1
I added the effective pom to the jar file
Problem
the pom file is way too big, with too much information (partly internal, local etc)
Solution 2
I combined two plugins and managed to additionally add the parent pom.xml file to the jar.
Problem
This is way better than S1 however the parent pom again contains a (grand)parent and also tags like <scm> which are internal and could & should not be handed to the outside world
Now I wanted to start to manipulate the parent pom and remove some parts etc. However there must be a better solution and others who have the same problem?
What I need is (e.g) a plugin which creates a clean "releasable" pom.xml file with only the dependencies (and of course artifact, groupid, version) and can then be imported by external parties into their repo without any conflicts. Is that possible?
The only thing remotely related is the eclipse tycho pom generator plugin. It is however eclipse specific...
The flatten-maven-plugin is exactly what I needed! Thanks to khmarbaise
I use the following configuration and the pom is looking beautiful :-)
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<pomElements>
<repositories>flatten</repositories>
</pomElements>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>

How maven jar project works when it is packaged to jar?

I am new to maven. I have created a maven project which will be packaged to JAR. I did clean package then jar is created. When i extracted the same jar, i could not see any dependencies (jars) i added in pom.xml inside the packaged jar. If i give this jar to third party clients how will the code work without any dependent jars ? Please help me how maven manages the jars?
Thanks!
Maven handles dependencies based on how you configure the dependency plugin.
See this reference for a simple example of how to do this.
In this example, the following code configures where your dependencies will end up:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>log4j</includeGroupIds>
<outputDirectory>${project.build.directory}/dependency-jars/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Then this code sets up the classpath for your main jar, which will allow anyone running it to find these dependencies
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mkyong.core.App</mainClass>
<classpathPrefix>dependency-jars/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
Your other option would be to create a single jar, with all dependencies included, by following this example here
You could distribute the jar and the POM file if you want to try and provide your users with the files in that manner, but they'd need to be able to access your Maven repository where those dependencies are kept.
Core maven doesn't handle this. Maven is a build tool, its work is to build an artifact (a jar in your case). Dependencies you define in your module's pom.xml file are needed to get the code compiled. You'll need maven plugins to do so.
Now, you're asking not about the build, but the distribution of your compiled binaries.
If I understand it should be a lot of jars (your and your dependencies). Alternatively you may distribute the code as a jar + dependencies inside.
Example:
A first case:
If your code resides in module A (say, the code is in packages org.a.*) and depends on some thirdparty (say, log4j, whose classes reside in org.apache.log4j) than you can expect that you jar will only contain the classes of module a and you expect that the log4j will be added by the user of your module automatically (The first case).
A second case:
module a.jar will contain both org.a.* and org.apache.log4j.* classes, everything in the same module.
In general the first approach is more "healthy" and in this case you shouldn't do anything in maven. Maybe your distribution tool/documentation should contain this information.
If someone uses the module a in his/her code like a thirdparty (if you develop a framework or something) and if his/her project is mavenized, than the fact you've defined a dependency on log4j will make the maven to download the log4j as well as your a.jar (In maven notation, this is called "transitive dependencies").
If you're interested in the second case (this can be relevant if you define some "client application", like "jndi client for some server" for example) you might want to take a look on Maven shade plugin
Beware this can lead to dependency hell (what if the application that uses your client also makes use of log4j? what if the log4j-s are of different version)/
Bottom line, you probably want the first approach, think twice before you decide the second approach :)
One more tip, if you just want to download all the dependencies of your module "a" you might want to use maven dependency plugin - type the following in the command prompt
mvn dependency:copy-dependencies
and you'll find all the dependencies in target/dependencies folder
Hope this helps and happy mavening
The simplest solution to the problem is to use the maven-assembly-plugin which can create such jar with dependencies like the following:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>distro-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Afterwards you can distribute the created jar xyz-1.0-jar-with-dependencies which contains the defined dependencies.
If you need more control on how the resulting artifact is created or if some files needed to be overwritten etc. you might take a deeper look into maven-shade-plugin

Does maven have an ability to pack single *.dll to jar without any sources?

I'd like to add *.dlls as third party libs to my repository and during packaging process just pack them to *.jar, sign them and copy to some specific folder.
Signing and coping are well done and work correctly (as expected by using maven-dependency-plugin and maven-jarsigner-plugin). But I didn't find any method to automatically pack single dll to jar (without any sources like maven-assembly-plugin does).
Solution that I see by the time: add to my repository not a "pure" dll, but already packed to jar lib (packed by myself)... but it's not a good idea, I guess)
It sounds like you've successfully retrieved your .dll (with dependency plugin) and signed it (jarsigner plugin), and it's somewhere in your ${project.build.directory} (which defaults to target).
If that's correct, give this a try:
Define the packaging of your project as jar
Retrieve dlls
Make sure the jarsigner:sign goal is bound to the prepare-package phase. It binds to package by default and we need to ensure jarsigner:sign runs before jar:jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>sign</id>
<phase>prepare-package</phase> <!-- important -->
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
Configure the jar plugin to include the signed dll(s)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<!-- using this ID merges this config with default -->
<!-- So it should not be necessary to specify phase or goals -->
<!-- Change classes directory because it will look in target/classes
by default and that probably isn't where your dlls are. If
the dlls are in target then directoryContainingSignedDlls is
simply ${project.build.directory}. -->
<id>default-jar</id>
<configuration>
<classesDirectory>directoryContainingSignedDlls</classesDirectory>
<includes>
<include>**/*.dll</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Now, running mvn clean package should give you a jar containing your signed dlls.
If JACOB requires manifest config there are docs explaining how to do this.
Good luck!
I would recommend to pack your dll's as a zip archive via maven-assembly-plugin and let that module deploy the zip archive as attached to your usual pom. The packaging of that project should be pom instead of default.
I would be a little bit confused if i download a jar and find dll's inside it,
but if you prefer you could create jar via the maven-assembly-plugin or use the maven-jar-plugin.

Maven: My project has a dependency that is NOT in any maven repo (system scope). Does it get included in my final jar?

So my maven project depends on a jar that is NOT in any maven repository. Therefore I need to use the system scope to include this local file in my maven classpath. Question is: When I build my final jar to distribute my library, I do need to somehow include that dependency with it. The classes can be extracted and then bundled with my library classes OR the jar can be included somehow inside my library jar. I am not even sure the latter (jar inside jar) is possible in Java.
So how should I approach this problem? Will Maven take my system scope dependency and take care of that for me? What should I do?
Thanks!
No, it will not. These dependencies are only for compilation and transitive dependency resolution. Your library consumers should have the jar too.
However, you could use the Assembly Plugin to repackage the jar's classes into your artifact.
Or, the standard approach: then you will publish your artifact, you will create a public repository for deployment. You also could deploy the jar in it.
UDPATE: adding example for the shade plugin (instead of the Assembly)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>legacy-jar.groupId:legacyJar</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
There is a second option. Put the jar into your repository as described here:
http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
and to your online repository
http://maven.apache.org/guides/mini/guide-3rd-party-jars-remote.html
give your client access to your repository and use your legacy.jar as normal dependency.
It depends a little bit what kind of library do you have. With this way you don't have problems with version conflicts of your legacy.jar in the environment of your customer.
Could this be what you are looking for, http://maven.40175.n5.nabble.com/How-to-specify-local-dependency-in-maven2-td103415.html.

Is it best to Mavenize your project jar files or put them in WEB-INF/lib?

I've been doing this for all of the jar files that my Spring MVC project needs:
call mvn install:install-file -DgroupId=vegetables -DartifactId=potatoes -Dversion=1.0 -Dfile=vegetables-1.0.jar -Dpackaging=jar -DgeneratePom=true
Recently I must have exceeded some limit on how many dependencies you can list in your pom.xml file because I got an error that said:
Your command line is too long
So I removed some dependencies from the pom.xml that my project no longer uses and I was able to run the project with maven again.
My question is, should I put install all jar files into my Maven repository as I have been doing so far? Or should I put some of them into the WEB-INF/lib directory?
What's the best practice here?
I've been doing the same that you do with the command line, but by configuring maven-install-plugin in my POM (please read the note at the end):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<id>install-vegetables</id>
<phase>initialize</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.basedir}/lib/vegetables-1.0.jar</file>
<groupId>vegetables</groupId>
<artifactId>potatoes</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</configuration>
</execution>
<execution>
<id>install-minerals</id>
<phase>initialize</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.basedir}/lib/minerals-1.0.jar</file>
<groupId>minerals</groupId>
<artifactId>rocks</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
It is much less efficient, because files get installed over and over, but it is much less annoying than making it manually. Anyway, I think you should give it a try.
All your dependencies should reside under the local repository. According to the Maven convention/best practices, you should not keep jar files in your project.
Convert your project to a fully war based Maven project. This will place all your dependencies (jar files) under your webapp's WEB-INF/lib directory. Thus you will not have to worry about long paths.
You just need to add the dependencies in your pom.xml file, no need to install them manually. Maven will download the libraries and put it in your local repository whenever needed. Only if you want to use third party(custom) libraries, you may go for installing it in your local repository.

Categories