How to package an Akka project - java

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.

Related

how to create two jars from one Maven project but with different resources files

I have a single maven project that has multiple folders in src/main/resources, I want to generate two Jars, one include src/main/resources/folder1/all properties and the other include src/main/resources/folder2/all properties.
Is their a way to achive this ? If not, what is the simplest way to achive my goal?
If I understood your problem correctly then you can use "Maven Assembly plugin" and "The Assembly Descriptor" in the following way:
first of all, you can not use a profile if you want to build 2 jar files simultaneously.
So, my suggestion is to exclude your config files from your jar then use Maven Assembly plugin to create a different zip file with these folders.
for example, in your case you should have 2 file descriptors like the following:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>folder1</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/java/descriptors/folder1.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
and folder1.xml contains:
<assembly>
<id>folder1</id>
<formats>
<format>zip</format>
</formats>
<files>
<file>
<source>
target/${project.artifactId}-${project.version}-yourJar.jar
</source>
<outputDirectory>/</outputDirectory>
</file>
</files>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources/folder1</directory>
<includes>
<include>*</include>
</includes>
<outputDirectory>/config</outputDirectory>
</fileSet>
</fileSets>
</assembly>
for "folder2" you can do it in the same way.
also for exclude some config files from the jar you can use this plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3</version>
<configuration>
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>package.path.to.your.main.class.MainClass</mainClass>
</manifest>
<manifestEntries>
<Class-Path>conf/</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
Using maven-resources-plugin as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>install</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/conf</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
From Introduction to Build Profiles
Profiles can be activated in the Maven settings, via the section. This section takes a list of elements, each containing a profile-id inside.
<settings>
...
<activeProfiles>
<activeProfile>profile-1</activeProfile>
</activeProfiles>
...
</settings>
Profiles listed in the tag would be activated by default every time a project use it.
Profiles can be automatically triggered based on the detected state of the build environment. These triggers are specified via an section in the profile itself. Currently, this detection is limited to prefix-matching of the JDK version, the presence of a system property or the value of a system property.
This allows to create a different package content based on the target environment.

How do I set file permissions on a file when deploying an AWS Serverless Application with Maven

I want to deploy an AWS lambda function using the AWS Serverless Application Model with Maven. In the lambdas deployment zip file I want to include two external files (file1 and file2) that need to have executable permisions. (chmod 755 / -rwxr-xr-x). The files are both 64-bit ELFs
The files on my local machine have those permisions, however when built and deployed to AWS I can export and download the function from the online AWS lambda console to a ZIP and see that the deployed files now have the permisions -rw-r--r-- (chmod 644).
I have fixed this issue in Gradle before by quite simply doing something like filesMatching('file1') { mode = 0755 }
I am using:
java11
maven-shade-plugin 3.2.2
How do I achieve this in Maven? Here is the build portion of my pom.xml
<build>
<resources>
<resource>
<directory>files</directory>
<includes>
<include>file1</include>
<include>file2</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<configuration>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
For anyone else having this issue, I ended up using maven-assembly-plugin as suggested by khmarbaise. My solution ended up looking like this:
This was the build section of my pom.xml
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>distribution.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Then I added the file "distribution.xml" to the same directory as the POM.xml. Which looked like this.
<assembly
xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>aws-lambda-package</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>files</directory>
<outputDirectory>./</outputDirectory>
<includes>
<include>file1</include>
<include>file2</include>
</includes>
<fileMode>0755</fileMode>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
As a side effect of doing this I could no longer use the name of the function as the value for the codeURI in the template.yaml. So I needed to change it to the location of the zip file created when maven clean install is ran. Which in most peoples cases will be located: <functionName>/target/<fileName>.zip.

Prevent breakup of fat jars in dependencySet during maven-assembly-plugin build

I have a Maven project that is intended to be a demo of one of our products, which is itself a fat jar with several dependencies. We distribute the source code of these demos as a .zip file containing a self-contained Maven project that our customers can build and play around with.
I'm using the maven-assembly-plugin to do a custom assembly of our distributed demos project. I'm using a dependencySet to place our product's JAR in a lib/ directory in the final assembly. The problem is, the maven-assembly-plugin splits up our fat jar into the normal jar (without dependencies), and all of the dependencies of the jar. I would rather the plugin not split up the fat jar, and simply place the fat jar in the lib/ directory. Is there a way to do this?
assembly.xml:
<dependencySets>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>lib/</outputDirectory>
<includes>
<include>our-product:jar</include>
</includes>
<outputFileNameMapping>our-product.jar</outputFileNameMapping>
</dependencySet>
</dependencySets>
pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>DemoManager</mainClass>
</manifest>
</archive>
<!-- Generates jar -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- Generates distributed demo project -->
<descriptors>
<descriptor>src/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-jar</id>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
</plugin>

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.

How do I create an executable jar file including dependencies where the main class is in Test, using Maven

I am new to Maven and have a project with the following directory structure
project
-src
-main
-java
-org
-core
-starter.java
-test
-java
-org
-core
-testStarter.java
Both starter.java and testStarter.java are Main classes. However I wish to create an executable jar file (including dependencies) where testStarter.java is executed.
I added the following to my pom file:
<groupId>org</groupId>
<artifactId>proj</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>project</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>org.core.testStarter</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
<plugins>
</build>
However everytime I run mvn clean package, it creates a package with only the compiled classes in the main directory and not the test directory. Hence everytime I run the jar file, it does not run, since the testStarter.class does not exist in the created jar file.
Is there a way I can create either
1) One big jar file containing test and main classes while it executes only the test class
2) Only the test classes but all dependencies are included.
According to you pom.xml you have already had a big jar with all dependencies and correct classname in manifest.
All you need now is to include your test classes into artifact.
One big jar file containing test and main classes while it executes only the test class. You can specify you /src/test directory as another source directory (see Maven compile with multiple src directories).
Only the test classes but all dependencies are included. You can mark your test directory as the only source directory by using sourceDirectory tag in build section. But I guess, your tests depend on code in main, so this configuration could fail on compile time.
p.s. I strongly recommend you to create separate build-profile for such case, because it seems strange for me to have main method for jar in test class.
Well, this seems kinda strange, but what you can do is to put testStarter under main (I suppose this won't work because it has references to other classes under the testfolder, am I right?). Btw, use CapitalCamelCase class names, that's more Java-ish.
Alternatively, you can use test-jar to create a jar for the tests (this might work if you add the original jar to the Class-Path manifest property), or you can start hacking the whole assembly of your project, but I wouldn't recommend that.
What I'd suggest is rethinking your project layout and clarifying your requirements. Probably you won't need this process.
I'd recommend using the Maven OneJar Plugin,
look here: https://code.google.com/p/onejar-maven-plugin/
"Lets you build an executable jar with Maven2, containing all dependencies"
As for you scoping issue-- You need to move that Main class to the src folder so that it can be in the compile scope.
Cheers!
We do this in our project by using a assembly.xml with the maven-assembly-plugin.
In the POM we have:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>src/main/resources/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>package-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
Then there is a assembly.xml in src/main/resources which tells how to build that assembly:
<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>
<formats>
<format>jar</format>
</formats>
<!-- Adds dependencies to jar package under lib directory -->
<dependencySets>
<dependencySet>
<useProjectArtifact>true</useProjectArtifact>
<outputDirectory></outputDirectory>
<unpack>true</unpack>
</dependencySet>
</dependencySets>
</assembly>

Categories