I have had a project set up for the past year or so and have been using the maven assembly plugin to package the jar.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<finalName>myProject</finalName>
<descriptors>
<descriptor>src/main/assembly/project.xml</descriptor>
<descriptor>src/main/assembly/zip.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
I have been using the project.xml descriptor to specify the exclusions of the jar as follows:
<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>project</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<useTransitiveFiltering>true</useTransitiveFiltering>
<scope>runtime</scope>
<excludes>
<exclude>commons-codec:commons-codec</exclude>
<exclude>commons-io:commons-io</exclude>
<exclude>commons-lang:commons-lang</exclude>
<exclude>org.apache.commons:commons-lang3</exclude>
<exclude>commons-logging:commons-logging</exclude>
...
</excludes>
</dependencySet>
</dependencySets>
This has been working fine. My jar would be packaged perfectly, excluding the dependencies that it was supposed to and would end up only being around 850KB by the end of everything. So today I go to package my jar as normal after doing some updates and none of the exclusions are being applied, and my final Jar is at about 12MB. This was quite alarming and frankly annoying. The thing is I have done absolutely nothing to the pom.xml. I back up my eclipse workspaces every night and I went to back to what I had yesterday (which I know produced a 850KB jar) and its the same result, a 12MB jar. Is there any sort of thing that would change this. An update of some kind? Anything?
Related
We're trying to build a client jar that includes unpacked dependent jar's. And the manifest should have class-path entries to the dependent jars. The snippet below works but the jars are unpacked - how can we stop the jars from being unpacked?
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Indeed, assembling using jar-with-dependencies causes maven to unpack all the dependencies as ${assembly.dependencySets.dependency.unpack} is set to true in the corresponding assembly descriptor.
A simple fix would be to provide an assembly descriptor similar to the jar-with-dependencies.xml and modify ${assembly.dependencySets.dependency.unpack} to false, like this:
EDIT: For an unknown reason, the behavior when using <unpack>false</unpack> is not exactly the same and it seems necessary to add <outputDirectory>/</outputDirectory> to the fileSet or you don't get the expected result.
<assembly>
<id>uberjar</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
You can add your dependencies as jar files to your jar:
assembly-descriptor.xml
<assembly>
<id>uberjar</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
<useProjectArtifact>false</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>.</outputDirectory>
</fileSet>
</fileSets>
</assembly>
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>make-uberjar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptor>src/main/assemble/assembly-descriptor.xml</descriptor>
</configuration>
</execution>
</executions>
</plugin>
But unfortunately you can't use the Class-Path header in manifest.mf, see Adding Classes to the JAR File's Classpath:
Note: The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file or classes accessible over Internet protocols. To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar.jar contains another JAR file called MyUtils.jar, you cannot use the Class-Path header in MyJar.jar's manifest to load classes in MyUtils.jar into the class path.
The solution proposed by Pascal Thivent defines a new assembly for the Maven assembly plugin. The Maven assembly plugin offers defaults assemblies which are 'bin', 'jar-with-dependencies', 'project' and 'src' producing various predefined bundles.
A new assembly has to be defined in a new xml file, most of the time located in src/assemble. Then it will be loaded instead of the predefined one, this way:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<!-- disabled predefined assembly -->
<!--
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
-->
<descriptors>
<descriptor>src/assemble/myAssembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
I'm currently moving a small project in to Maven and I am having some trouble.
The setup is as follows
Where a setting file is used in a my resource folder for running the application in eclipse. But when i create a fat jar the setting file is packed in side the jar. I want to filter the setting file so it is outside the jar (I understand this makes the file brittle, but that is by design) and still have it available to the application from the same folder as the jar. I have achieved this with an eclipse runnable jar and and Ant file. But I cannot seem to get it to work with maven. Any insight you have would be very useful.
Her are examples of my plugin and filter file. Any Ideas on this would be great as this has been driving me insane
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<filters>
<filter>src/assembly/filter.properties</filter>
</filters>
<archive>
<manifest>
<mainClass>ie.business.project.artifact</mainClass>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</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>
and my filter
<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>distribution</id>
<formats>
<format>jar</format>
</formats>
<files>
<file>
<source>settings.ini</source>
<outputDirectory>/</outputDirectory>
<filtered>true</filtered>
</file>
</files>
</assembly>
So I have tired something else. If I define an exclusion in my jar-plugin in addition to using maven-assembly, the setting file dose not end up in the fat jar. I'm unsure if this is the right way to do this but it has worked.
Please let me know if there in a better way to do this.
I added the following plugin to my pom
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<excludes>
<exclude>setting.ini</exclude>
</excludes>
</configuration>
</plugin>
It seems that you are not using the assembly plugin pointing to the assembly in your question. If you look at the plugin configuration you are using:
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
Actually you should be pointing to the relative path of the assembly file, like e.g:
<configuration>
<descriptors>
<descriptor>src/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
Now the assembly file for the creation of a fat jar should be changed to create the fat jar and exclude some files. This example is just to give you an idea:
<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>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<fileSets>
<fileSet>
<directory>${basedir}</directory>
<excludes>
<exclude>settings.ini</exclude>
</excludes>
</fileSet>
</fileSets>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
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.
Following this Guide I ran the command
mvn assembly:assembly
and got the Build Failure of
Error reading assemblies: No assembly descriptors found.
I've looked at numerous questions on this, but to no avail.
From this post, I created a .xml with this inside:
<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>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<dependencySets>
<dependencySet>
<scope>runtime</scope>
<unpack>true</unpack>
<unpackOptions>
<excludes>
<exclude>**/LICENSE*</exclude>
<exclude>**/README*</exclude>
</excludes>
</unpackOptions>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/resources/META-INF/services</directory>
<outputDirectory>META-INF/services</outputDirectory>
</fileSet>
</fileSets>
</assembly>
and included this in the pom.xml:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptors>
<descriptor>jar-with-dependencies.xml</descriptor>
</descriptors>
</configuration>
</plugin>
but still no luck.
I'm pretty new to this as you can probably tell, how can I get this running?
~~EDIT~~
In the pom.xml I changed
<descriptor>jar-with-dependencies.xml</descriptor>
To
<descriptor>src/main/assembly/jar-with-dependencies.xml</descriptor>
~~EDIT 2~~
pom.xml now contains this:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/jar-with-dependencies.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
~~EDIT 3~~
This pom.xml now works for me:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/jar-with-dependencies.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
For this to work, you need to create the file jar-with-dependencies.xml in src/main/assembly/ and this XML:
<descriptors>
<descriptor>src/main/assembly/jar-with-dependencies.xml</descriptor>
</descriptors>
i.e. you need to specify the path to the file and the convention is to put the files into src/main/assembly/.
To use the ones provided by Maven, you need to use the descriptorRef element instead (wrapped in a descriptorRefs).
Also don't put the descriptor inside of the execution element or mvn assembly:assembly can't find it anymore (since you specifically moved it to the mvn package target).
[EDIT] I followed the tutorial myself and there is an important point which you might have missed: You need to select the correct archetype. In my case, that was 5 but the order can change. So read the whole list and look for the string openimaj-quickstart-archetype or things will break.
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>