bundling multiple artifact for deployment? - java

This is follow up based on this answer.
I have a structure that looks like
$ ls service/target/
classes lib maven-status surefire-reports
classes.-1194128992.timestamp maven-archiver service-1.0-SNAPSHOT.jar
and with-in that lib looks like
$ ls service/target/lib/
activation-1.1.jar akka-http-spray-json-experimental_2.11-1.0.jar mail-1.4.7.jar scala-reflect-2.11.2.jar
akka-actor_2.11-2.3.12.jar akka-parsing-experimental_2.11-1.0.jar manager-1.0-SNAPSHOT.jar scala-xml_2.11-1.0.2.jar
akka-http-core-experimental_2.11-1.0.jar akka-stream-experimental_2.11-1.0.jar reactive-streams-1.0.0.jar scalatest_2.11-2.2.5.jar
akka-http-experimental_2.11-1.0.jar config-1.2.1.jar
As part of mvn clean install, I want to bundle my-deployment-artifact which should look contain
service-1.0-SNAPSHOT.jar
lib/* (all the jars here)
How do I create this as a tar or .tar.gz and produce with mvn clean install?

You can use maven-assembly-plugin to do that task.
Create an assembly definition file in src/assembly/distribution.xml
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>distribution</id>
<formats>
<format>tar</format>
</formats>
<files>
<file>
<source>${project.build.directory}/${project.build.finalName}.${project.packaging}</source>
</file>
</files>
<fileSets>
<fileSet>
<directory>${project.build.directory}/lib</directory>
<outputDirectory>lib</outputDirectory>
</fileSet>
</fileSets>
</assembly>
In pom.xml file, add plugin declare, execution phase and goal for it.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<descriptor>${project.basedir}/src/assembly/distribution.xml</descriptor>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
More format file or customize of maven-assembly-plugin can be found here: https://maven.apache.org/plugins/maven-assembly-plugin/

Related

I added CLI support for my java library, how can I conveniently expose this to my library users?

I maintain a Java library which recently added support for CLI commands, but I'm having trouble understanding how to actually expose this support.
How can I provide an easy command cross-platform that works with all the dependencies needed?
During my own testing I have either relied on Junit tests that I run from IntelliJ or on the Maven exec plugin. IntelliJ and Maven manage all the dependencies, but I can't expect my library users to do the same. I'm thinking of providing a .bat file for Windows users and an alias for Linux users, which act as a shortcut for:
java -cp all;the;jars.jar my.package.CliSupportingClass command --option value
Is there a better way?
This article explains it quite well, using appassembler-maven-plugin to assemble all the dependencies and producing a script helper and maven-assembly-plugin to bundle it all as an archive such as zip and tar.
The article uses version 2.4 of one of the plugins, where I updated for the latest 3.1.0. The only difference for our use case is that the <descriptor> tag is now nested in a <descriptors> tag.
Include both plugins either as standard build plugins or under a profile:
<profiles>
<profile>
<id>standalone-cli</id>
<build>
<plugins>
<!-- appassembler-maven-plugin -->
<!-- maven-assembly-plugin -->
</plugins>
</build>
</profile>
</profiles>
The appassembler-maven-plugin collects all dependencies for us and produces a script helper for windows and unix:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.8.1</version>
<configuration>
<repositoryLayout>flat</repositoryLayout>
<repositoryName>lib</repositoryName>
<showConsoleWindow>true</showConsoleWindow>
<platforms>
<platform>unix</platform>
<platform>windows</platform>
</platforms>
<programs>
<program>
<mainClass>org.simplejavamail.cli.SimpleJavaMail</mainClass>
<id>sjm</id>
</program>
</programs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
</plugin>
The maven-assembly-plugin then produces the archive(s):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptors>
<descriptor>src/assembly/standalone-cli-descriptor.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Finally standalone-cli-descriptor.xml tells maven-assembly-plugin what should be included in the archives and what type of archives should be produced:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>standalone-cli</id>
<formats>
<format>tar</format>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>LICENSE-2.0.txt</include>
<include>NOTICE.txt</include>
<include>RELEASE.txt</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/appassembler</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Gradle has an application plugin that creates a distribution zip file. Your users can unzip this to install it. It has all the dependencies in a lib folder and Windows bat files and *nix shell scripts to run the application in a bin folder.
I believe Maven has something similar.

Zip/tar the generated jar file along with other file

I need to zip the generated jar file after running the mvn clean deploy.
But i am facing problem with it.
I am using assembly plugin and my assembly.xml
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>bin</id>
<baseDirectory>/</baseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources/process.sh</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
and pom.xml looks like below.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/assembly/assembly.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- this is used for inheritance merges -->
<phase>package</phase>
<!-- append to the packaging phase. -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
In above case i tried to tar the entire target folder. It got compressed but there was no files.
What am doing is first executing mvn clean then executing mvn clean deploy.
I just want the generated jar/war file to be compressed after execution of mvn clean deploy.
after running mvn clean deploy its zipping the .jar file, its zipping the .jar.original. which is of 8kb file.
Any help will be appreciated.

Create zip in maven with additional files next to the jar

The only Maven experience I have is including other libraries so I need a very basic explanation about how I can achieve things in Maven with Eclipse.
I want to create my jar regulary. Then I want to take 3 further files and put all files together in 1 zip file. The content of my zip should look like this:
A.jar
B.txt
C.txt
D.bat
I know I have to insert certain goals in my pom.xml file. I already saw posts on Stack Overflow (i.e. here) regarding similar topics. I also tried the Maven documentation like here. Do I already need any Maven plugins or is still already Maven-core stuff?
But my skills are not enough yet to transfer this information for my case.
+ project
+ src/main/java
+ src/main/resources
+ src/main/config
+B.txt
+C.txt
+D.bat
+ src/main/assembly
+bin.xml
+pom.xml
bin.xml
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>bin</id>
<baseDirectory>/</baseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/config</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
poml.xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/bin.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- append to the packaging phase. -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Output :
mvn clean package
+ artifactId-version.zip
+ B.txt
+C.txt
+D.txt
+artifactId-version.jar
Not added B.txt, C.txt, D.bat in src/main/resources because it's not good to have them in the CLASSSPATH
You need to use the maven-assembly-plugin when you need to create custom artifacts. I strongly suggest that you read Chapter 8. Maven Assemblies of the Maven book to get you started with using assemblies. This chapter contains in-depth explanations on the creation of Maven assemblies, and it is easy to read.
Basically, an assembly is created with the help of an assembly descriptor. The following assembly descriptor will include the project main artifact at the root of a zip archive. You can add more <file> or <fileSets> declaration here to add your custom files in your archive (the logic is the same)
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>assemby-id</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<files>
<file>
<source>${project.build.directory}/${project.build.finalName}.${project.packaging}</source>
<outputDirectory>/</outputDirectory>
</file>
</files>
</assembly>
Then you just need to declare this plugin in your POM. In this case, the plugin is bound to the package phase and configured with the descriptor above. By default, the assembly id is appended to the name of the archive: I removed it here.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor> <!-- path to the descriptor -->
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
When running mvn clean package, you will see that a zip archive will have been created in the target directory.

What can I have as a Maven artifact and how can I use it?

I know that it seems like a question that is already asked, but I have not found an answer that helps me a lot.
I read a lot of times that it is preferable to generate an artifact per project. But my question is : what can I have as a Maven artifact?
For example : I have a custom packaging "MyPack" with a custom lifecycle, can I have whole a directory "Mydirectory" as an artefact?
Let's say that the structure of the directory is like this:
MyDirectory
-----|--jars
-----|-----|--- client.jar
-----|-----|--- server.jar
-----|--jsps
-----|-----|--- page1.jsp
-----|-----|--- page2.jsp
-----|--imgs
-----|-----|--- img1.png
-----|-----|--- img2.png
Then, I want to create a new project that has the packaging "MyPack" and a dependency with the type "MyPack". In this project, my Java classes need client.jar and server.jar which are in the Maven repository to compile and I want to copy all jsps and imgs from the repository in my new project.
can I do all that with a custom Maven plugin?
You can have as maven artifact whatever you choose to have as an artifact.
Use the maven assembly plugin to generate the artifact:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>${basedir}/src/main/assembly/shared.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
....
</plugins>
....
</build>
In the shared.xml file you specify the format and files to be included in the artifact:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>shared</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<outputDirectory>/</outputDirectory>
<directory>${basedir}/.....</directory>
<includes>
<include> ... </include>
</includes>
<fileMode>0644</fileMode>
<filtered>false</filtered>
<lineEnding>unix</lineEnding>
</fileSet>
</fileSets>
</assembly>
When you do "maven deploy", the "shared" artifact will be packaged and deployed together with the project's main artifact.
In order to use the artifact in another project, use the maven-dependency-plugin with the goal "unpack-dependencies".

How to package an Akka project

I have an Akka stand alone project
that implements the Bootable interface of the mico-kernel
The tutorials on paclaging an akka system with the micro-kernel
describes an SBT project that uses the sbt pluggin
Can nay one tell me how to package the maven project with the micro-kernel
A search on Google for "akka microkernel maven" lists this as one of the top contending answers to your question: http://jcranky.com/2012/07/13/akka-microkernel-with-maven/
after going through JCrnak's blog and reading through the maven assembly plugin and the manifest file documentation,I was able to come up with a slightly different solution from that of JCranky and will like to share.
The first assumption is that all the Akka plugins including that of the microkernel have been configured in the POM.xml. Secondly, that the application to be distributed has been developed.
The maven package phase creates an executable jar file. However this will need the main class of the application to be directly executed using the java -jar command. To make the location of the main class known to the package application , we insert the following plugin with the configuration of the manifest file in the POM.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.bbox.gesture.BoundingBox</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
To copy the akka dependencies into the lib file in the target file we add the following plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
With this plugins we copy all the necessary files to the target file.
Now we copy the content of the target file to a zip folder using the assembly plugin with the descriptor.xml file. below is the descriptor.xml file.
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>akka</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/deploy</outputDirectory>
<includes>
<include>**</include>
</includes>
<excludes>
<exclude>*.jar</exclude>
<exclude>*.zip</exclude>
</excludes>
</fileSet>
</fileSets>
<files>
<file>
<source>target/com-bbox-gesture-1.0-SNAPSHOT.jar</source>
<outputDirectory>/deploy</outputDirectory>
<destName>bbox.jar</destName>
</file>
<file>
<source>src/main/resources/application.conf</source>
<outputDirectory>/deploy/config</outputDirectory>
</file>
</files>
</assembly>
To run the assembly plugin we add the following to the POM.xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptors>
<descriptor>/descriptor.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
To top it all we add a simple batch file that start's the application by running the java -jar command from withing the deploy directory. Below is the simple script from the batch file
echo off
cls
start java -jar bbox.jar
the start command runs the java -jar command on the executable jar file. the bbox.jar file is the executable jar
To run the application simply unpack the zip folder in your server , navigate to the start.bat file and click.

Categories