Apache Maven Assembly plugin allows to create an executable jar which includes all its dependencies within it. The resultant jar is also called 'fat jar'.
Example
Create a simple project
Create a project using maven-archetype-quickstart with following parameters.
<groupId>com.logicbig.example</groupId>
<artifactId>maven-assembly-plugin-example</artifactId>
<version>1.0-SNAPSHOT</version>
Import the project into your IDE.
Add dependency of third party jar
As in this example we are using to demonstrate how to create a jar with dependencies. We chose com.google.guava as a dependent jar.
<project ...>
......
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
</dependency>
</dependencies>
...
</project ...>
Add maven-assembly-plugin in pom
<project .....>
.......
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.logicbig.example.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Create a Main class
package com.logicbig.example;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
public class Main {
public static void main (String[] args) {
Multimap<Integer, String> map =
LinkedListMultimap.create();
map.put(1, "apple");
map.put(1, "banana");
map.put(1, "orange");
System.out.println(map);
}
}
Run the above class to check if everything is working.
Output
{1=[apple, banana, orange]}
Package the jar
Now run package goal from command line:
mvn package
It will kick off 'assembly:single' goal as we have attached it with 'package' in above pom using <execution>.
We can also run mvn assembly:single instead.
Running resultant executable jar
Here's are all steps on windows cmd. It shows directory tree before and after packaging. At the end, we are executing jar and having the same output:
D:\examples\maven-assembly-plugin-example>mvn -q clean
D:\examples\maven-assembly-plugin-example>tree /A /F
Folder PATH listing for volume Data
Volume serial number is 000000A3 68F9:EDFA
D:.
| pom.xml
|
\---src
\---main
\---java
\---com
\---logicbig
\---example
Main.java
D:\examples\maven-assembly-plugin-example>mvn -q package
D:\examples\maven-assembly-plugin-example>tree /A /F
Folder PATH listing for volume Data
Volume serial number is 0000008D 68F9:EDFA
D:.
| pom.xml
|
+---src
| \---main
| \---java
| \---com
| \---logicbig
| \---example
| Main.java
|
\---target
| maven-assembly-plugin-example-1.0-SNAPSHOT-jar-with-dependencies.jar
| maven-assembly-plugin-example-1.0-SNAPSHOT.jar
|
+---archive-tmp
+---classes
| \---com
| \---logicbig
| \---example
| Main.class
|
+---maven-archiver
| pom.properties
|
\---maven-status
\---maven-compiler-plugin
\---compile
\---default-compile
createdFiles.lst
inputFiles.lst
D:\examples\maven-assembly-plugin-example>java -jar target\maven-assembly-plugin-example-1.0-SNAPSHOT-jar-with-dependencies.jar
{1=[apple, banana, orange]}
D:\examples\maven-assembly-plugin-example>
What's inside jar with dependencies?
Followings creates a temp folder and extracts jar with dependencies there to see the tree.
D:\examples\maven-assembly-plugin-example>md temp
D:\examples\maven-assembly-plugin-example>cd temp
D:\examples\maven-assembly-plugin-example\temp>jar -xf ..\target\maven-assembly-plugin-example-1.0-SNAPSHOT-jar-with-dependencies.jar
D:\examples\maven-assembly-plugin-example\temp>tree /A /F
Folder PATH listing for volume Data
Volume serial number is 0000007D 68F9:EDFA
D:.
+---com
| +---google
| | +---common
| | | +---annotations
| | | | Beta.class
| | | | GwtCompatible.class
| | | | GwtIncompatible.class
| | | | VisibleForTesting.class
| | | |
| | | +---base
| | | | | Absent.class
| | | | | AbstractIterator$1.class
| | | | | AbstractIterator$State.class
| | | | | AbstractIterator.class
| | | | | Ascii.class
| | | | | CaseFormat$1.class
| | | | | CaseFormat$2.class
| | | | | CaseFormat$3.class
| | | | | CaseFormat$4.class
| | | | | CaseFormat$5.class
| | | | | CaseFormat$StringConverter.class
| | | | | CaseFormat.class
| | | | | CharMatcher$1.class
| | | | | CharMatcher$And.class
| | | | | CharMatcher$Any.class
| | | | | CharMatcher$AnyOf.class
| | | | | CharMatcher$Ascii.class
| | | | | CharMatcher$BitSetMatcher.class
| | | | | CharMatcher$BreakingWhitespace.class
| | | | | CharMatcher$Digit.class
| | | | | CharMatcher$FastMatcher.class
| | | | | CharMatcher$ForPredicate.class
| | | | | CharMatcher$InRange.class
| | | | | CharMatcher$Invisible.class
| | | | | CharMatcher$Is.class
| | | | | CharMatcher$IsEither.class
| | | | | CharMatcher$IsNot.class
| | | | | CharMatcher$JavaDigit.class
| | | | | CharMatcher$JavaIsoControl.class
| | | | | CharMatcher$JavaLetter.class
| | | | | CharMatcher$JavaLetterOrDigit.class
| | | | | CharMatcher$JavaLowerCase.class
| | | | | CharMatcher$JavaUpperCase.class
--------------------- more -----------------------------
| | | | |
| | | | \---internal
| | | | Finalizer.class
| | | |
| | | +---cache
| | | | AbstractCache$SimpleStatsCounter.class
| | | | AbstractCache$StatsCounter.class
| | | | AbstractCache.class
| | | | AbstractLoadingCache.class
| | | | Cache.class
| | | | CacheBuilder$1.class
| | | | CacheBuilder$2.class
| | | | CacheBuilder$3.class
| | | | CacheBuilder$NullListener.class
| | | | CacheBuilder$OneWeigher.class
| | | | CacheBuilder.class
| | | | CacheBuilderSpec$1.class
| | | | CacheBuilderSpec$AccessDurationParser.class
| | | | CacheBuilderSpec$ConcurrencyLevelParser.class
| | | | CacheBuilderSpec$DurationParser.class
| | | | CacheBuilderSpec$InitialCapacityParser.class
| | | | CacheBuilderSpec$IntegerParser.class
| | | | CacheBuilderSpec$KeyStrengthParser.class
| | | | CacheBuilderSpec$LongParser.class
| | | | CacheBuilderSpec$MaximumSizeParser.class
| | | | CacheBuilderSpec$MaximumWeightParser.class
| | | | CacheBuilderSpec$RecordStatsParser.class
| | | | CacheBuilderSpec$RefreshDurationParser.class
--------------------- more -----------------------------
| | | |
| | | +---collect
| | | | AbstractBiMap$1.class
| | | | AbstractBiMap$BiMapEntry.class
| | | | AbstractBiMap$EntrySet.class
| | | | AbstractBiMap$Inverse.class
| | | | AbstractBiMap$KeySet.class
| | | | AbstractBiMap$ValueSet.class
| | | | AbstractBiMap.class
| | | | AbstractIndexedListIterator.class
| | | | AbstractIterator$1.class
| | | | AbstractIterator$State.class
| | | | AbstractIterator.class
| | | | AbstractListMultimap.class
| | | | AbstractMapBasedMultimap$1.class
--------------------- more -----------------------------
| | | +---graph
| | | | AbstractDirectedNetworkConnections$1.class
| | | | AbstractDirectedNetworkConnections.class
| | | | AbstractGraph$1.class
| | | | AbstractGraph.class
| | | | AbstractGraphBuilder.class
| | | | AbstractNetwork$1$1$1.class
| | | | AbstractNetwork$1$1.class
| | | | AbstractNetwork$1.class
| | | | AbstractNetwork$2.class
| | | | AbstractNetwork.class
| | | | AbstractUndirectedNetworkConnections.class
| | | | AbstractValueGraph$1.class
| | | | AbstractValueGraph.class
| | | | ConfigurableMutableGraph.class
| | | | ConfigurableMutableNetwork.class
| | | | ConfigurableMutableValueGraph.class
| | | | ConfigurableNetwork.class
| | | | ConfigurableValueGraph.class
| | | | DirectedGraphConnections$1$1.class
| | | | DirectedGraphConnections$1.class
| | | | DirectedGraphConnections$2$1.class
| | | | DirectedGraphConnections$2.class
| | | | DirectedGraphConnections$PredAndSucc.class
| | | | DirectedGraphConnections.class
| | | | DirectedMultiNetworkConnections$1.class
--------------------- more -----------------------------
| | | +---hash
| | | | AbstractByteHasher.class
| | | | AbstractCompositeHashFunction$1.class
| | | | AbstractCompositeHashFunction.class
| | | | AbstractHasher.class
| | | | AbstractNonStreamingHashFunction$BufferingHasher.class
| | | | AbstractNonStreamingHashFunction$ExposedByteArrayOutputStream.class
| | | | AbstractNonStreamingHashFunction.class
| | | | AbstractStreamingHashFunction$AbstractStreamingHasher.class
| | | | AbstractStreamingHashFunction.class
| | | | BloomFilter$1.class
| | | | BloomFilter$SerialForm.class
| | | | BloomFilter$Strategy.class
| | | | BloomFilter.class
| | | | BloomFilterStrategies$1.class
| | | | BloomFilterStrategies$2.class
| | | | BloomFilterStrategies$BitArray.class
| | | | BloomFilterStrategies.class
| | | | ChecksumHashFunction$1.class
| | | | ChecksumHashFunction$ChecksumHasher.class
| | | | ChecksumHashFunction.class
| | | | Crc32cHashFunction$Crc32cHasher.class
| | | | Crc32cHashFunction.class
| | | | FarmHashFingerprint64.class
| | | | Funnel.class
| | | | Funnels$ByteArrayFunnel.class
| | | | Funnels$IntegerFunnel.class
| | | | Funnels$LongFunnel.class
| | | | Funnels$SequentialFunnel.class
--------------------- more -----------------------------
| | | |
| | | +---html
| | | | HtmlEscapers.class
| | | | package-info.class
| | | |
| | | +---io
| | | | AndroidIncompatible.class
| | | | AppendableWriter.class
| | | | BaseEncoding$1.class
| | | | BaseEncoding$2.class
| | | | BaseEncoding$3.class
| | | | BaseEncoding$4.class
| | | | BaseEncoding$5.class
| | | | BaseEncoding$Alphabet.class
| | | | BaseEncoding$Base16Encoding.class
| | | | BaseEncoding$Base64Encoding.class
| | | | BaseEncoding$DecodingException.class
| | | | BaseEncoding$SeparatedBaseEncoding.class
| | | | BaseEncoding$StandardBaseEncoding$1.class
| | | | BaseEncoding$StandardBaseEncoding$2.class
| | | | BaseEncoding$StandardBaseEncoding.class
| | | | BaseEncoding.class
| | | | ByteArrayDataInput.class
| | | | ByteArrayDataOutput.class
| | | | ByteProcessor.class
| | | | ByteSink$1.class
| | | | ByteSink$AsCharSink.class
| | | | ByteSink.class
--------------------- more -----------------------------
| | | |
| | | +---math
| | | | BigIntegerMath$1.class
| | | | BigIntegerMath.class
| | | | DoubleMath$1.class
| | | | DoubleMath.class
| | | | DoubleUtils.class
| | | | IntMath$1.class
| | | | IntMath.class
| | | | LinearTransformation$1.class
| | | | LinearTransformation$LinearTransformationBuilder.class
| | | | LinearTransformation$NaNLinearTransformation.class
| | | | LinearTransformation$RegularLinearTransformation.class
| | | | LinearTransformation$VerticalLinearTransformation.class
| | | | LinearTransformation.class
| | | | LongMath$1.class
| | | | LongMath$MillerRabinTester$1.class
| | | | LongMath$MillerRabinTester$2.class
| | | | LongMath$MillerRabinTester.class
| | | | LongMath.class
| | | | MathPreconditions.class
| | | | package-info.class
| | | | PairedStats.class
| | | | PairedStatsAccumulator.class
| | | | Quantiles$1.class
| | | | Quantiles$Scale.class
| | | | Quantiles$ScaleAndIndex.class
| | | | Quantiles$ScaleAndIndexes.class
| | | | Quantiles.class
| | | | Stats.class
| | | | StatsAccumulator.class
| | | |
| | | +---net
| | | | HostAndPort.class
| | | | HostSpecifier.class
| | | | HttpHeaders.class
| | | | InetAddresses$TeredoInfo.class
| | | | InetAddresses.class
| | | | InternetDomainName.class
| | | | MediaType$1.class
| | | | MediaType$2.class
| | | | MediaType$Tokenizer.class
| | | | MediaType.class
| | | | package-info.class
| | | | PercentEscaper.class
| | | | UrlEscapers.class
| | | |
| | | +---primitives
| | | | Booleans$BooleanArrayAsList.class
| | | | Booleans$BooleanComparator.class
| | | | Booleans$LexicographicalComparator.class
| | | | Booleans.class
| | | | Bytes$ByteArrayAsList.class
| | | | Bytes.class
| | | | Chars$CharArrayAsList.class
| | | | Chars$LexicographicalComparator.class
| | | | Chars.class
| | | | Doubles$DoubleArrayAsList.class
| | | | Doubles$DoubleConverter.class
| | | | Doubles$LexicographicalComparator.class
| | | | Doubles.class
| | | | Floats$FloatArrayAsList.class
| | | | Floats$FloatConverter.class
| | | | Floats$LexicographicalComparator.class
| | | | Floats.class
| | | | Ints$IntArrayAsList.class
| | | | Ints$IntConverter.class
| | | | Ints$LexicographicalComparator.class
| | | | Ints.class
| | | | Longs$LexicographicalComparator.class
| | | | Longs$LongArrayAsList.class
| | | | Longs$LongConverter.class
| | | | Longs.class
| | | | package-info.class
| | | | ParseRequest.class
| | | | Primitives.class
| | | | Shorts$LexicographicalComparator.class
| | | | Shorts$ShortArrayAsList.class
| | | | Shorts$ShortConverter.class
| | | | Shorts.class
| | | | SignedBytes$LexicographicalComparator.class
| | | | SignedBytes.class
| | | | UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator.class
| | | | UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator$1.class
| | | | UnsignedBytes$LexicographicalComparatorHolder$UnsafeComparator.class
| | | | UnsignedBytes$LexicographicalComparatorHolder.class
| | | | UnsignedBytes.class
| | | | UnsignedInteger.class
| | | | UnsignedInts$LexicographicalComparator.class
| | | | UnsignedInts.class
| | | | UnsignedLong.class
| | | | UnsignedLongs$LexicographicalComparator.class
| | | | UnsignedLongs.class
| | | |
| | | +---reflect
| | | | AbstractInvocationHandler.class
| | | | ClassPath$1.class
| | | | ClassPath$ClassInfo.class
| | | | ClassPath$DefaultScanner.class
| | | | ClassPath$ResourceInfo.class
| | | | ClassPath$Scanner.class
| | | | ClassPath.class
| | | | Element.class
| | | | ImmutableTypeToInstanceMap$1.class
| | | | ImmutableTypeToInstanceMap$Builder.class
| | | | ImmutableTypeToInstanceMap.class
| | | | Invokable$ConstructorInvokable.class
| | | | Invokable$MethodInvokable.class
| | | | Invokable.class
| | | | MutableTypeToInstanceMap$1.class
| | | | MutableTypeToInstanceMap$UnmodifiableEntry$1.class
| | | | MutableTypeToInstanceMap$UnmodifiableEntry$2.class
| | | | MutableTypeToInstanceMap$UnmodifiableEntry.class
| | | | MutableTypeToInstanceMap.class
--------------------- more -----------------------------
| | | |
| | | +---util
| | | | \---concurrent
| | | | AbstractCatchingFuture$AsyncCatchingFuture.class
| | | | AbstractCatchingFuture$CatchingFuture.class
| | | | AbstractCatchingFuture.class
| | | | AbstractCheckedFuture.class
| | | | AbstractExecutionThreadService$1$1.class
| | | | AbstractExecutionThreadService$1$2.class
| | | | AbstractExecutionThreadService$1.class
| | | | AbstractExecutionThreadService$2.class
| | | | AbstractExecutionThreadService.class
| | | | AbstractFuture$1.class
| | | | AbstractFuture$AtomicHelper.class
| | | | AbstractFuture$Cancellation.class
| | | | AbstractFuture$Failure$1.class
| | | | AbstractFuture$Failure.class
| | | | AbstractFuture$Listener.class
| | | | AbstractFuture$SafeAtomicHelper.class
| | | | AbstractFuture$SetFuture.class
--------------------- more -----------------------------
| | | | WrappingExecutorService$1.class
| | | | WrappingExecutorService.class
| | | | WrappingScheduledExecutorService.class
| | | |
| | | \---xml
| | | package-info.class
| | | XmlEscapers.class
| | |
| | \---thirdparty
| | \---publicsuffix
| | PublicSuffixPatterns.class
| | PublicSuffixType.class
| | TrieParser.class
| |
| \---logicbig
| \---example
| Main.class
|
\---META-INF
| MANIFEST.MF
|
\---maven
+---com.google.guava
| \---guava
| pom.properties
| pom.xml
|
\---com.logicbig.example
\---maven-assembly-plugin-example
pom.properties
pom.xml
D:\examples\maven-assembly-plugin-example\temp>
It shows that instead of creating nested dependent jars, this plugin creates a flat directory structure with merged java packages and classes tree.
Example ProjectDependencies and Technologies Used: - guava 21.0:
Guava is a suite of core and expanded libraries that include
utility classes, google's collections, io classes, and much
much more.
Guava has only one code dependency - javax.annotation,
per the JSR-305 spec.
- JDK 1.8
- Maven 3.3.9
|