Recommended practices for distributing/using maven projects outside the build lifecycle - maven

There are many occasions where I am not sure whats the best to handle dependencies for a maven project. That is while executing a jar thats the result of mvn package.
Things I have tried
1) Maven-shade plugin
For some use cases ( such as hadoop jobs ) I find it convenient to use the Maven shade plugin to integrate with the package step ( it builds an all inclusive uber-jar ). The downside is that the uber-jar is too massive. Also, I cant get the maven shade to work on datanucleus dependencies as it messes up something.
2) distribute the dependencies along with the jar.
//something like this
$ mvn package dependency:copy-dependencies
$ java -cp target/project.jar:target/dependency com.MyMainClass
generates a directory with all the dependencies along with the jar.
What I would like to do is
3) just be able to distribute the jar and handle the dependencies while executing the jar. Since mvn package puts the pom in the jars manifest folder, all the information is there right ? . Now, I would like it if there was a one line command to be able to run this jar asking maven to manage the dependencies. Even more awesome if someone knows if such a thing can be used as a hadoop job.

I think there is no solution for question in your point 3.
My three options, in all cases you can run application with simple java -jar target/project.jar. Nothing more is needed.
1. Maven Assembly Plugin with jar-with-dependencies descriptor
(manifest in jar configuration is missed here)
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.2</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
2. Maven dependency plugin
Maven dependency plugin, properly jar configured (classpath) and maven assembly custom descriptor for packing all together.
(you can simplify this, if your project is not using snapshot dependencies)
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>your.package.MainApp</mainClass>
<packageName>your.package</packageName>
<classpathLayoutType>custom</classpathLayoutType>
<customClasspathLayout>lib/$${artifact.artifactId}.$${artifact.extension}/customClasspathLayout>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<excludeScope>test</excludeScope>
<includeScope>compile</includeScope>
<stripVersion>true</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
3. Maven One Jar
<plugin>
<groupId>org.dstovall</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<configuration>
<attachToBuild>true</attachToBuild>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>

Related

How to combine javafx-maven-plugin and maven-assembly-plugin?

I have a JavaFx project which I want to reduce to one jar file.
My pom contains a java-fx plugin:
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>8.1.4</version>
<configuration>
<mainClass>application.Main</mainClass>
<jfxAppOutputDir>${project.build.directory}/jfx/app</jfxAppOutputDir>
</configuration>
<executions>
<execution>
<id>create-jfxjar</id>
<phase>package</phase>
<goals>
<goal>build-jar</goal>
</goals>
</execution>
</executions>
</plugin>
and an assembly plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>application.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
When I call "mvn package" a single jar file is being build but it does not contain the jfx-jar file but contains some sort of "jar wihout jfx support"-version.
How can I tell the Maven Assembly Plugin to use the jar version from the jfx plugin (which is located in jfxAppOutputDir (../jfx/app/))?
Found the problem myself.
the jar file with the "no main manifest attribute"-error was created by maven-jar-plugin. But it is possible to configure it to omit that creation. If you are interested please take a look:"what-is-the-best-way-to-avoid-maven-jar"
the assembly plugin worked correctly. It was my fault. I thought that the assembly plugin creates a jar file with all dependencies including all resource files(all files from the resource folder). My mistake. "jar-with-dependencies" includes all jars belonging to the project, nothing more.

Can I force Maven to build a JAR even though POM packaging specifies WAR?

I'd like to build our project from the command line as a JAR without modifying the POM, which has the <packaging>war</packaging> configuration.
Is there a way to do this?
If you are free to chose how maven is executed it is possible to call maven to invoke the jar goal directly:
mvn jar:jar
I was not able to explicitly build a jar while preventing the building of a war as well. But I realized I didn't have to. With this configuration of the maven-assembly-plugin, and the packaging set to WAR in my POM, a fat-jar and a war will always be created.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<finalName>myApp</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.company.app.Startup</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
If this questions / answer seems confusing / not useful to searchers, feel free to delete it. Thanks to everyone who helped me get here.

how to add my external jar file to class path

I am new to maven environment, need some ones help.
Added my external jar file (directoryhelper.jar) in lib folder as below in pom.xml
<dependency>
<groupId>com.test.directoryhelper</groupId>
<artifactId>DirectoryHelper</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/directoryhelper.jar</systemPath>
</dependency>
compilation is successful, but during run time I am getting
java.lang.NoClassDefFoundError.
how to add the directoryhelper.jar to class path.
Maven out of the box will come up with a JAR file (default packaging). This JAR file only contains (main) artifacts of the project. If you take just that and run it, clearly the dependencies are missing -- by design.
Typically Maven artifacts are reused in combination with their POM so that at the point of use it's know what the dependencies are. Edit: if you're using APKs and installing them on a phone, there may be mechanisms to deal with dependencies, I'm answering this merely from a Maven standpoint.
If you want to create a JAR with dependencies you have to tell Maven to do so, that's not the default.
Ways of having Maven do that are (probably not exhaustive):
Maven Assembly plugin, jar-with-dependencies predefined descriptor:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
...
Maven Shade plugin
That way it'll create a single-jar of large size and build time will be large everytime you try to build.
I instead prefer adding all jars to a lib folder and including in the classpath (jar's manifest), because of which when we have to make some change or redeploy to the client or some place, we can simply give the small jar (not all the dependencies merged within jar)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.kalindiinfotech.webcrawler.MainGUI</mainClass>
<!-- <mainClass>com.KalindiInfotech.busbookingmaven.form.LoginForm</mainClass>-->
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>

dozer with maven

I wanted to download the latest release of Dozer mapper from github, but I didn't find any jar.
There is pom.xml file and I try to compile with command mvn package. I also added every dependencies to pom.xml file. It created dozer-5.5.0-SNAPSHOT.jar.
Next I imported this jar to my project, but it throws me java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory.
I also tried to create POM project in the netbeans and build with dependencies. After import to my project, it throws me the same exception.
I don't have any experiences with maven. How can I get correct JAR file?
Guess your dozer-package has a dependency to slf4j, right?
Then you should checkout this Maven-Plugin: Maven-Assembly-Plugin
This will put your required dependencies into the jar.
Here you can read, how to use it
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
version>2.4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>your.main.class</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
If you want always execute the assemby-plugin when you invoke mvn clean package
add this to your maven-assembly-plugin:
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
You have a correct jar. Simple add commons-beanutils lang and slf4j to you project with dozer or add this libraries as a maven dependencies.
Jars required for Dozer dependency.
Make the entry in pom.xml file.Make sure the required Jars are present.
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.3.1</version>
</dependency>
<properties>
<osgi.version>4.3.0</osgi.version>

mvn install jar-with-dependencies

Is there a way to do an install on a jar-with-dependencies created using maven-assembly-plugin?
If you bind the assembly to the packaging phase, it will install in your repository both the "regular" jar and the with-dependencies jar when you do a build:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
mvn assembly:assembly -DdescriptorId=jar-with-dependencies
:)
One way would be to create a project where you use the assembly-plugin. In the assembly-plugin configuration you can specify what output you want (jar, zip, ...)
In this projects pom you can put your dependencies and build it. Every time you execute the install command all your dependencies will be in your packaged file.
Look under the heading "Executing: Building an Assembly" here.
Is mvn install not doing this?

Resources