Maven shade plugin Packaging DLL - java

I have to add to my project a JNI module.
I install the module in Maven as two different artifact: the jar library:
mvn install:install-file -DgroupId=com.test -DartifactId=ssa -Dversion=1.0 -Dpackaging=jar -Dfile=ssa.jar
and the runtime library with the DLL
mvn install:install-file -DgroupId=com.sirio -Dpackaging=ddl -DartifactId=ssa-runtime -classifier=windows-x86 -Dversion=1.0 -Dfile=SSADll.dll
In my maven project I add these dependecies:
<dependency>
<groupId>com.test</groupId>
<artifactId>ssa</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>ssa-runtime</artifactId>
<classifier>windows-${arch}</classifier>
<type>dll</type>
<version>1.0</version>
<scope>runtime</scope>
</dependency>
My problem is when I run the shade plugin goal to create a jar with dependencies, I get error:
Failed to execute goal org.apache.maven.plugins:maven-shade-plugin:2.3:shade (default) on project ....: Error creating shaded jar: error in opening zip file sirio\ssa-runtime\1.0\ssa-runtime-1.0-windows-x86.dll
How can I tell the shade plugin to do not unpack the dll?

Maybe what you need is to package differently. Make the shaded jar with all java classes and libraries you use and then package this jar and the DLL together in a Zip file to be released. For this you can use the maven-assembly-plugin with a descriptor for your zip, like this:
In your pom.xml:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>zip.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
In zip.xml file:
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
<id>release</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>target</directory>
<includes>
<include>myapp.jar</include>
</includes>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
<files>
<file>
<source>your.dll</source>
<fileMode>0644</fileMode>
</file>
</files>
</assembly>
That way you have all you need to release in this zip. I don't know if that's the best solution, but maybe it solves the problem for your use case.

this solution worked for my JavaFX-OpenCV project
package your project without DLL files.
copy and paste your DLL files in the jar file directory.
now you can run your application because all DLL files are now on the classpath of your jar application.
your directory should be like this :
/target/application.jar
/target/your_DLL_files.dll

Also being new to Maven, it took me a while to solve a similar problem. This answer may help others.
Using com.microsoft.sqlserver:mssql-jdbc_auth with mssql-jdbc_auth-10.2.3.x64.dll as a dependency.
Fortunately the dll is a separate artifact from the mssql jdbc jar.
To stop the shade plugin trying to open the dll as a zip file....
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<excludes>
<exclude>com.microsoft.sqlserver:mssql-jdbc_auth</exclude>
</excludes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
and then to put the dll into the same directory as the shaded jar file
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<includeArtifactIds>mssql-jdbc_auth</includeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>

Related

Maven : Download of executable zip based on OS

I want to download a zip file via mavens POM.XML, but based on the OS i need different URLs (Linux/Windows).
How can I change the URL based on the OS maven is executed? (locally, its Windows, on Jenkins its then Linux)
This is how the plugins part of my POM.XML looks like:
<build>
<plugins>
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<executions>
<execution>
<!-- the wget goal actually binds itself to this phase by default -->
<phase>process-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://test/chromedriver_win32.zip</url>
<unpack>true</unpack>
<outputFileName>chromedriver</outputFileName>
<outputDirectory>${project.build.directory}/chromeDriver</outputDirectory>-->
<outputDirectory>${user.home}/localdata/tools/chromeDriver</outputDirectory>
<overwrite>true</overwrite>
<skipCache>true</skipCache>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

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.

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.

maven - how to compile code to jar file and not .class

I am trying to build a groovy project using maven. My packaging type is war file. Maven is building the project and putting all dependent libraries in WEB-INF/lib folder but it is compiling all code into class files and putting it into WEB-INF/classes folder. Is there a way I can tell maven to build jar file for my project also and put it into WEB-INF/lib folder.
My pom.xml looks like this :
<groupId>com.myproject</groupId>
<artifactId>ExampleProject</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>My Example Project</name>
<url>http://maven.apache.org</url>
<dependencies>
...
...
...
</dependencies>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/groovy</directory>
<excludes>
<exclude>**/*.groovy</exclude>
</excludes>
</resource>
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/groovy</source>
<source>src/main/resources</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/groovy</source>
<source>src/test/resources</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<finalName>master</finalName>
</build>
In these scenarios the usual approach is to you separate your library code in a different module that will be a dependency from your war module. For this suggestion you can see also how to generate jar and war both in project .
However if you still prefer to go with the solution you mention, you can do it with the following configuration in your pom
<configuration>
..
<attachClasses>true</attachClasses>
<archiveClasses>true</archiveClasses>
</configuration>
(see http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html, and how to use class file from another war)

Maven - generate archive of every dependency source

Is there a way to get an archive containing every dependency source as a separate artifact ?
What i know is that there is a way to download every source jar using the dependency-plugin as stated here. However these files are downloaded to the local repository.
What i try to achieve is:
Ship a JAR containing some runnable code. In addition a ZIP archive cotaining the source-code of shipped dependencies inside the JAR.
I needed to do something similar, except I also needed to filter the included sources to just those produced by teams at my company. You may use a combination of the maven-dependency-plugin and the maven-assembly-plugin to achieve this.
Here's the configuration I use.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
<executions>
<execution>
<id>retrieve-dependency-sources</id>
<phase>process-sources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<classifier>sources</classifier>
<outputDirectory>${project.build.directory}/dep-sources</outputDirectory>
<type>jar</type>
<failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
<prependGroupId>true</prependGroupId>
<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
<excludeTransitive>false</excludeTransitive>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>package-dependency-sources</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<attach>true</attach>
<finalName>${your.app.finalName}</finalName>
<descriptors>
<descriptor>src/main/assembly/dep-source-assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
And here is the assembly descriptor, dep-source-assembly.xml, which should be placed in src/main/assembly.
<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>dep-sources</id> <!-- whatever you'd like the classifier to be -->
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}/dep-sources</directory>
<outputDirectory></outputDirectory>
<!-- Define the includes if you'd like to have sources only for certain
packages. For my use case, I needed to include just source files
produced elsewhere in my company, not commonly available jars like
Spring. -->
<includes>
<include>**/com.mycompany.*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
It sounds like your use case may be a little different than mine, so you might be able to use the assembly plugin's dependencySet in place of the separate invocation of maven-dependency-plugin and the fileSet.
One other potential gotcha: if you are doing this for a war or ear, you will need to add a dependency on the project's POM to get the complete set of dependencies. (See MNG-1991.)
<dependency>
<groupId>${my.webapp.groupId}</groupId>
<artifactId>${my.webapp.artifactId}</artifactId>
<version>${my.webapp.version}</version>
<type>pom</type>
</dependency>

Categories