Include only certain packages in a Maven generated non-runnable jar - maven

I'm trying to build a non-executable jar file that only includes certain packages from my project to use as a library for common code. I'm planning on deploying that to Nexus and including it in other projects.
I can make it manually in eclipse by right clicking on the project, selecting Export, selecting JAR file (NOT Runnable Jar File) then checking the packages that I want to include. I'm trying to mimic this behavior in Maven. I have been able to replicate the non-runnable part in maven by not including a main in the manifest, but still have to find out how to include only certain packages.
This project actually builds 2 jar files already (from 2 different main's in the program - a test GUI and the regular application). I'm having trouble finding information on how to do the non-runnable jar and selecting certain packages only.
Here is the existing build portion of my pom file is below. Build-third is the non-runnable jar:
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>build-first</id>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>com.joy.fb20.da.exec.jDaExecutive</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>DaExecutive</finalName>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
<execution>
<id>build-second</id>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>com.joy.fb20.gui.jExampleAppGui</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>ExampleAppGui</finalName>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<execution>
<id>build-third</id>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>ddslib</finalName>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</plugin>
</plugins>
</build>

Tried this myself and it is possible.
Create a new maven profile
Add pluginManagement section to that new profile for maven-jar-plugin and if needed for maven-resources-plugin also
Use this pluginManagement to configure inclusions/exclusions of sources/resources and override artifacts final name here to have different name for that separate jar
Example
<profiles>
<profile>
<id>subset</id>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<finalName>subset</finalName>
<includes>
<include>org/example/stuff/**</include>
</includes>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
Using this profile maven creates subset.jar that has everything under org/example/stuff/**
See more about excluding: How to exclude a set of packages from maven build jar?
Of course it might be possible to do all this also without pluginManagement but in my opinion pluginManagement provides clean & flexible way to configure this kind of stuff so i recommend that.

You should be able to do that by using a custom assembly descriptor and specifying your fileset and / or file includes / excludes. See https://maven.apache.org/plugins/maven-assembly-plugin/assembly.html#class_fileSet

Related

Executing Maven Project [duplicate]

I have a code base which I want to distribute as jar. It also have dependency on external jars, which I want to bundle in the final jar.
I heard that this can be done using maven-assembly-plug-in, but I don't understand how. Could someone point me to some examples.
Right now, I'm using fat jar to bundle the final jar. I want to achieve the same thing using maven.
Note: If you are a spring-boot application, read the end of answer
Add following plugin to your pom.xml
The latest version can be found at
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>CHOOSE LATEST VERSION HERE</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
After configuring this plug-in, running mvn package will produce two jars: one containing just the project classes, and a second fat jar with all dependencies with the suffix "-jar-with-dependencies".
if you want correct classpath setup at runtime then also add following plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
For spring boot application use just following plugin (choose appropriate version of it)
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
You can use the maven-shade-plugin.
After configuring the shade plugin in your build the command mvn package will create one single jar with all dependencies merged into it.
Maybe you want maven-shade-plugin, bundle dependencies, minimize unused code and hide external dependencies to avoid conflicts.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>true</createDependencyReducedPom>
<dependencyReducedPomLocation>
${java.io.tmpdir}/dependency-reduced-pom.xml
</dependencyReducedPomLocation>
<relocations>
<relocation>
<pattern>com.acme.coyote</pattern>
<shadedPattern>hidden.coyote</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
References:
http://maven.apache.org/plugins/maven-shade-plugin/plugin-info.html
http://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html
actually, adding the
<archive>
<manifest>
<addClasspath>true</addClasspath>
<packageName>com.some.pkg</packageName>
<mainClass>com.MainClass</mainClass>
</manifest>
</archive>
declaration to maven-jar-plugin does not add the main class entry to the manifest file for me.
I had to add it to the maven-assembly-plugin in order to get that in the manifest
You can use the onejar-maven-plugin for packaging. Basically, it assembles your project and its dependencies in as one jar, including not just your project jar file, but also all external dependencies as a "jar of jars", e.g.
<build>
<plugins>
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Note 1: Configuration options is available at the project home page.
Note 2: For one reason or the other, the onejar-maven-plugin project is not published at Maven Central. However jolira.com tracks the original project and publishes it to with the groupId com.jolira.
An alternative is to use the maven shade plugin to build an uber-jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version> Your Version Here </version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
Read if you want to use the maven-assembly-plugin.
As other answers have already outlined, it seems that the maven-shade-plugin offers more features and is the recommended plugin to build a fat jar, but in case you would like to use the maven-assembly-plugin the following plugin configuration will work.
The answer of #jmj explains that the correct classpath can be setup with an additional maven-jar-plugin, but this will only add the classpath to the original jar and not the fat jar. The information must instead be directly included into the configuration section of the maven-assembly-plugin.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.package.YourMainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
When you now run maven package, your normal and fat jar will be created and you can run your fat jar with java -jar yourJar.jar.

Minify maven plugin,does not add minified file to maven local repository

I'm using minify maven plugin with following configuration in POM -
<plugin>
<groupId>com.samaxes.maven</groupId>
<artifactId>minify-maven-plugin</artifactId>
<version>1.7.4</version>
<configuration>
<verbose>true</verbose>
<fork>true</fork>
<executable>${JAVA_HOME_1_7}/bin/javac</executable>
<compilerVersion>1.7</compilerVersion>
</configuration>
<executions>
<execution>
<id>crf</id>
<phase>package</phase>
<configuration>
<jsSourceDir>crf/js</jsSourceDir>
<jsSourceIncludes>
<jsSourceInclude>*.js</jsSourceInclude>
</jsSourceIncludes>
<jsTargetDir>crf/js</jsTargetDir>
<skipMerge>true</skipMerge>
<jsEngine>CLOSURE</jsEngine>
<nosuffix>true</nosuffix>
<closureCreateSourceMap>false</closureCreateSourceMap>
</configuration>
<goals>
<goal>minify</goal>
</goals>
</execution>
<execution>
<id>bundle-configuration-minify</id>
<configuration>
<jsEngine>CLOSURE</jsEngine>
<closureCreateSourceMap>false</closureCreateSourceMap>
</configuration>
<goals>
<goal>minify</goal>
</goals>
</execution>
</executions>
</plugin>
When i build the component(Say 'component-war' using mvn clean install), i see the target(component-war) has a minified JavaScript.But Maven local repo does not contain the minified file.
Due to which when i package the project(Say 'project-ear') target does not contain the minified file.
I Also have the following configuration in my POM -
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<packagingIncludes>WEB-INF/lib/urlrewritefilter-*.jar,WEB-INF/lib/xercesImpl-*.jar,WEB-INF/lib/io-*.jar,WEB-INF/lib/xtags-*.jar,**/*.xml,**/*.xsd,**/*.pdf,**/*.txt,**/*px,**/*dummyfile,**/*.properties,**/*.class,**/*.png,**/*.css,**/*.js,**/*.jsp,**/*.jspf,**/*.xsl,**/*.html,**/*.htm,**/*.vm,**/*.tld,**/*.gif,**/readme,**/*.zip,**/*.jpg,**/*.zul,**/*.zs,**/*.eot,**/*.svg,**/*.ttf,**/*.woff,**/*.swf
</packagingIncludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
First you must delete:
<execution>
<id>crf</id>
<phase>package</phase>
because for WAR project in phase package maven-war-plugin has priority over other plugins (http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Plugins) - WAR is build before minification.
BTW, it explains why Maven has phase prepare-package and do not have post-package; everything defined in package is effectively post-package
That's not enough, because maven-war-plugin will overwrite minified files. You must configure it to ignore original JS files, because their minified versions are already prepared by minify plugin (Exclude source files from WAR package)
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<packagingIncludes>WEB-INF/lib/urlrewritefilter-*.jar,WEB-INF/lib/xercesImpl-*.jar,WEB-INF/lib/io-*.jar,WEB-INF/lib/xtags-*.jar,**/*.xml,**/*.xsd,**/*.pdf,**/*.txt,**/*px,**/*dummyfile,**/*.properties,**/*.class,**/*.png,**/*.css,**/*.js,**/*.jsp,**/*.jspf,**/*.xsl,**/*.html,**/*.htm,**/*.vm,**/*.tld,**/*.gif,**/readme,**/*.zip,**/*.jpg,**/*.zul,**/*.zs,**/*.eot,**/*.svg,**/*.ttf,**/*.woff,**/*.swf
</packagingIncludes>
<!--HERE **************** -->
<warSourceExcludes>crf/js/*.js</warSourceExcludes>
<!--HERE **************** -->
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
BTW, your maven war plugin configuration (packagingIncludes) suggests you have a mess in project. You should consider clean it up, because my proposal extends configuration and any further unnecessary extension cause whole configuration hard to understood

Maven : Dependencies Management

I already saw lot of post related to this question, but hard to figure out the best approach of doing this. I am having a maven project having two dependencies (A.Jar) and (B.Jar) in maven central repostories. I want to create a runnable jar. Which is the best approach in doing this and how to do this ? An example will be helpful. (sample POM.XML)
thanks !
The simplest solution would be to use maven-assembly-plugin via a predefined descriptor:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Via the above you can do simply:
mvn clean package
which results in having a file target/whatever-1.0-SNAPSHOT-jar-with-dependencies.jar which is exactly what you like to get.

Building a fat jar using maven

I have a code base which I want to distribute as jar. It also have dependency on external jars, which I want to bundle in the final jar.
I heard that this can be done using maven-assembly-plug-in, but I don't understand how. Could someone point me to some examples.
Right now, I'm using fat jar to bundle the final jar. I want to achieve the same thing using maven.
Note: If you are a spring-boot application, read the end of answer
Add following plugin to your pom.xml
The latest version can be found at
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>CHOOSE LATEST VERSION HERE</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
After configuring this plug-in, running mvn package will produce two jars: one containing just the project classes, and a second fat jar with all dependencies with the suffix "-jar-with-dependencies".
if you want correct classpath setup at runtime then also add following plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
For spring boot application use just following plugin (choose appropriate version of it)
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
You can use the maven-shade-plugin.
After configuring the shade plugin in your build the command mvn package will create one single jar with all dependencies merged into it.
Maybe you want maven-shade-plugin, bundle dependencies, minimize unused code and hide external dependencies to avoid conflicts.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>true</createDependencyReducedPom>
<dependencyReducedPomLocation>
${java.io.tmpdir}/dependency-reduced-pom.xml
</dependencyReducedPomLocation>
<relocations>
<relocation>
<pattern>com.acme.coyote</pattern>
<shadedPattern>hidden.coyote</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
References:
http://maven.apache.org/plugins/maven-shade-plugin/plugin-info.html
http://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html
actually, adding the
<archive>
<manifest>
<addClasspath>true</addClasspath>
<packageName>com.some.pkg</packageName>
<mainClass>com.MainClass</mainClass>
</manifest>
</archive>
declaration to maven-jar-plugin does not add the main class entry to the manifest file for me.
I had to add it to the maven-assembly-plugin in order to get that in the manifest
You can use the onejar-maven-plugin for packaging. Basically, it assembles your project and its dependencies in as one jar, including not just your project jar file, but also all external dependencies as a "jar of jars", e.g.
<build>
<plugins>
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Note 1: Configuration options is available at the project home page.
Note 2: For one reason or the other, the onejar-maven-plugin project is not published at Maven Central. However jolira.com tracks the original project and publishes it to with the groupId com.jolira.
An alternative is to use the maven shade plugin to build an uber-jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version> Your Version Here </version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
Read if you want to use the maven-assembly-plugin.
As other answers have already outlined, it seems that the maven-shade-plugin offers more features and is the recommended plugin to build a fat jar, but in case you would like to use the maven-assembly-plugin the following plugin configuration will work.
The answer of #jmj explains that the correct classpath can be setup with an additional maven-jar-plugin, but this will only add the classpath to the original jar and not the fat jar. The information must instead be directly included into the configuration section of the maven-assembly-plugin.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.package.YourMainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
When you now run maven package, your normal and fat jar will be created and you can run your fat jar with java -jar yourJar.jar.

can maven assembly plugin picking the specify java package?

Suppose we have following packages in our project
org.xxx.dao, org.xxx.service, org.xxx.service.impl
all the package are in ther source folder src/main/java
can i assembly packages into seprated jars,(xxx-dao.jar,xxx-service.jar,xxx-service-impl.jar)?
You can use the standard maven-jar-plugin for this:
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>dao</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<archive>
<index>true</index>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
<classifier>dao</classifier>
<includes>
<include>org/xxx/dao/**/*</include>
</includes>
</configuration>
</execution>
<execution>
<id>service</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<archive>
<index>true</index>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
<classifier>service</classifier>
<includes>
<include>org/xxx/service/**/*</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
This gives you one JAR with everything and then several JARs with only the selected content which you can select with a classifier in your Maven POMs.
If you want to omit the default JAR (which contains everything), then you replace one <id> with <id>default-jar</id> and add an <excludes> element because the default JAR includes everything, so you have to get rid of anything that you don't want.
maven-assembly plugin is not intended for this kind of tasks, see its features. If you have the source codes, then I would suggest copying them into a module of your project.
But if you want to do it with maven-assembly plugin, then I think you can do it by creating separate descriptor components and defining which files to include in which assembly. You can define source files to be included in includes tags under sources definition.

Resources