I have a multi-module project where I build every project with tycho. Everything including the phase "install" works perfectly. Every module results in one artefact which are installed to my local maven repository...about 10 artefacts.
Now, I would like to make maven additionally copy all 10 artefacts to a local directory if the build successes. At the end, when I rebuilt my application, I should only see one directory with all (updated) artefacts.
Btw, how do the big companies get their product out of the maven repository?
You may define an aggregator module in your project, that has dependencies on all other projects and then use the maven-dependency-plugin to collect all jars
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-libs</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Of course you can collect resource files like startup scripts etc using the same plugin. Create another execution
<execution>
<id>copy-sh-files</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/scripts</outputDirectory>
<includes>bin/*.sh</includes>
</configuration>
</execution>
To put that all together into a single zip, you have to create an assembly file in src/assembly/zip.xml with that content
<assembly>
<id>zip</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>src/bin</directory>
<outputDirectory>.</outputDirectory>
<includes>
<include>*.cmd</include>
</includes>
<lineEnding>dos</lineEnding>
</fileSet>
<fileSet>
<directory>target/lib</directory>
<outputDirectory>lib</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
and add the maven-assembly-plugin to your build plugins
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptor>src/assembly/zip.xml</descriptor>
<finalName>yourProjectFinalName</finalName>
</configuration>
<executions>
<execution>
<id>zip-bundle</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
All these configuration are just one way to do it, but it is a good start. Big companies usually have various requirements for their packaging, including installers etc, so there is no one-size-fits-all solution and it's usually quite a process to get to the final solution.
Related
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 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 to sign all jars and wars that are generated in project when i clean and build with maven ? Is there such plugin and instruction how to use it. I found this http://maven.apache.org/plugins/maven-jarsigner-plugin/usage.html while searching the internet but there is no good instruction how to use or test it.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>sign</id>
<phase>install</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
<configuration>
<archiveDirectory>jars location</archiveDirectory>
<includes>
<include>**/*.jar</include>
</includes>
<keystore>/path/to/keystore.jks</keystore>
<alias>...</alias>
<storepass>...</storepass>
<keypass>...</keypass>
</configuration>
</plugin>
This code worked for me
I would like to overlay another person's project, using customizations of specific files (ie one file would use a different controller, or display something in one way, or have different processes). We have been using an overlay that takes all of the files I have in my repository, and overlaying all of the files on top of their files so that my smaller set of customizations still act like the larger project should. We have accomplished it like this so far, but it plays havoc on the IDE. Is there a better way? I tried using maven-builder-helper-plugin but it gave me duplicate classes on the java files I had overriden.
<build>
<sourceDirectory>target/overlay</sourceDirectory>
<resources>
<resource>
<directory>target/overlay</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<tasks>
<copy todir="target/overlay" overwrite="true">
<fileset dir="src/main/java">
</fileset>
<fileset dir="src/main/resources">
</fileset>
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>initialize</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.sample.service</groupId>
<artifactId>sampleService</artifactId>
<classifier>sources</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>target/overlay</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
I should note that I'm absolutely fine with using a different direction than this one. I just couldn't figure out a better way to include all of the resource & source files that are needed from them to keep the project running properly. This is for a module that is a part of a web app. The module that is being built and the module it is overlaying are both jar's
We do this using the maven war overlay feature (read about it here). To do this we simply have a dependency from our web client module onto a war type <type>war</type>, and override what we need to in our module. Maven will take the contents of the dependent war and use its files to provide content for our web client, but if there is a clash on filename it'll take the file from our web client, not from the dependent jar. It's as if it takes the dependent jar and overlays our client on top of it to produce a new war. We do this very simply, without any need for ant run -- in years of using maven I have never had to resort to antrun (I consider it an antipattern).
You mention in the comments that you have a separate problem dealing with some xml files. This can be handled by the resource plugin, if you tell it which directory your files are in, and give it a wildcard to define the files you need copying.
So, I figured out a solution that allows me overlay the artifact without messing around with the source directory. Instead of slapping all of the files I want to overlay on top of the artifact files, I realized a simpler way would be to expand the artifact, remove the duplicate classes/resources, and use it as an additional source. I created my own plugin that takes as many 'source' directories as I want and it filters them in the order loaded.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>initialize</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.sample.service</groupId>
<artifactId>sampleService</artifactId>
<classifier>sources</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${additional-source-folder}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>mn-stateadvantage</groupId>
<artifactId>duplicateSourceRemover-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>removeDuplicates</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<sourceDirectories>
<param>src/main</param>
<param>${additional-source-folder}</param>
</sourceDirectories>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-resources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${additional-source-folder}</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-resource</id>
<phase>generate-resources</phase>
<goals>
<goal>add-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${additional-source-folder}</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
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>