How to use maven shade to build jar and war - maven

I'm on a project working with openrdf, and I require the shade plugin to transform my service entries. I would like to build a war and a jar simultaneously, as both usages are possible. However, I cannot get the shade plugin to produce a shaded jar and a shaded war at the same time - shade only invokes on the package type defined in the properties, and binding e.g. the jar plugin to the package phase in order to create a jar next to the war results in an unshaded jar. How can I create both a shaded jar and a shaded war at the same time?

If by "shaded war" you mean just the regular war with all dependencies packed into WEB-INF/lib, then you might just use maven-war-plugin separately and use jar as packaging type. This way shade plugin will work correctly. And .war will be built by plugin.
Below is pom.xml. And here is working example.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>so.test</groupId>
<artifactId>stackoverflow-test2</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>${project.build.finalName}-fatjar</finalName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>war</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>5.14.9</version>
</dependency>
</dependencies>
</project>

Related

How to generate a SINGLE jar contains /src/main/java and /src/test/java

I have created a maven project and trying to generate a SINGLE jar file should contain both /src/main/java & /src/test/java.
But it is generating two SEPARATE jar files. Please let me know, how can I achieve this in maven?
generated jar files:
test-0.0.1-SNAPSHOT.jar
test-0.0.1-SNAPSHOT-tests.jar
my pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.testmaven</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>test</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
You cannot access test classes from application code. So no maven plugin will help you to add src/main/java and src/test/java in a single executable jar.
If at all you want to access the main classes from the test project, check the answer similar to your question on stackoverflow here:
How can I include test classes into Maven jar and execute them?
I have tried with below approach and it worked.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.basedir}/src/test/java/</source>
</sources>
</configuration>
</execution>
</executions>

Maven to include JAR that is generated by that build

Normally we use dependency tag in pom.xml to have Maven include a JAR on the classpath and it also packages that dependency.
What if the JAR is generated in a step of the same project's build? I mean, it's not the compile plugin that generates it, it is a JAR without any java source and an external executable creates it.
I can use maven exec plugin to have my JAR generated and maven install plugin to have it installed to my local repository. But still I can't have it as a dependency in the same project: No matter which phase I put my JAR generator command in, the dependency check will happen before that and fail because the JAR does not yet exist.
Is system scope dependency my best choice? Then I need to give up packaging. And it's deprecated. And the JAR needs to be outside the project directory.
Or the JAR generator must be in a separate pom? Also not very nice because the JAR is only used by this one project.
Can I configure the dependency plugin to defer the dependency check and download to compile phase?
Any other solution?
This pom almost works, but first time I need to install the generated thing manually to the repo.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>something-parent</artifactId>
<groupId>something</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>something-sample</artifactId>
<properties>
<jnbridge.path>C:/Program Files (x86)/JNBridge/JNBridgePro v9.0</jnbridge.path>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-proxies-jar</id>
<phase>generate-test-resources</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>jnbproxy.bat</executable>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>process-test-resources</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>jnbridge.local</groupId>
<artifactId>proxies</artifactId>
<version>0.0.0</version>
<packaging>jar</packaging>
<file>${basedir}/proxies.jar</file>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!--
Yes, these are true system-scope dependencies. JNBridge is expected to be
installed on the system wherever this project is built.
-->
<dependency>
<groupId>com.jnbridge.org.apache</groupId>
<artifactId>bcel</artifactId>
<version>5.1</version>
<scope>system</scope>
<systemPath>${jnbridge.path}/jnbcore/bcel-5.1-jnbridge.jar</systemPath>
</dependency>
<dependency>
<groupId>com.jnbridge</groupId>
<artifactId>jnbcore</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${jnbridge.path}/jnbcore/jnbcore.jar</systemPath>
</dependency>
<!--
This one will be installed to local maven repo in the process-test-resources phase,
as defined in the project/build/plugins section of this file.
-->
<dependency>
<groupId>jnbridge.local</groupId>
<artifactId>proxies</artifactId>
<version>0.0.0</version>
</dependency>
<!-- other dependencies... -->
</dependencies>
</project>

Using maven with external build scripts

My application depends on a third-party ear (it deconstructs it, adds/modifies some items therein, and reconstructs it into a new ear). The third-party ear must be built using a third-party build script.
I am trying to learn the "maven-y" way to set this up. I expect I will need to get the third-party ear installed into my repository.
I want to create a pom.xml for the third-party ear which will build the third-party ear and install/deploy it. I have created a pom.xml which successfully calls out to the third-party build script (via maven-antrun-plugin) and creates the ear in exactly the place that a default maven ear project would.
My problem is that maven's install plugin fails because it can't find the archive (it expects whatever plugin does the packaging to have set an attribute on the artifact object, which maven-antrun-plugin doesn't do).
mvn package works fine and generates the ear.
The exact error message when running mvn install looks like this:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-install-plugin:2.3.1:install (default-install) on project third_party_ear: The
packaging for this project did not assign a file to the build artifact -> [Help 1]
Is there a better way to go about this?
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.thirdparty</groupId>
<artifactId>third_party_ear</artifactId>
<version>9.0</version>
<packaging>ear</packaging>
<name>third_party_ear</name>
<build>
<plugins>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>default-ear</id>
<phase>none</phase>
</execution>
<execution>
<id>default-generate-application-xml</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>package</phase>
<configuration>
<target>
<subant target="build-ear" antfile="build.xml" buildpath="${project.basedir}"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
When you specify <packaging>ear</packaging> you are telling Maven to invoke the full lifecycle specified for that packaging.
In your case what you want to do is write a wrapper pom.xml that just shells out to your 3rd party build script without invoking the EAR lifecycle and attach the produced artifact to Maven's reactor...
Something like this should work
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.thirdparty</groupId>
<artifactId>third_party_ear</artifactId>
<version>9.0</version>
<packaging>pom</packaging>
<name>third_party_ear</name>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>package</phase>
<configuration>
<target>
<subant target="build-ear" antfile="build.xml" buildpath="${project.basedir}"/>
<attachartifact file="${project.build.directory}/${project.build.finalName}.ear" type="ear"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
There may be some slight glitches because the pom's packaging differs... but as this is not a classpath relevant artifact they shouldn't affect you.
Note the attachartifact ANT task can attach an artifact from anywhere, so you need not have battled ANT to get the file in the "right" place... though it is nicer to follow that convention. You may want to not use the project.build.finalName and hardcode the filename.

Use jarsign plugin with assembly plugin in Maven 3

I'm using assembly plugin to package a list of applets into zip in one of modules with my maven project. here is the pom.xml:
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<artifactId>applets-deploy</artifactId>
<name>deploy</name>
<dependencies>
<dependency>
<groupId>com.activx.lims</groupId>
<artifactId>applets-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.activx.lims</groupId>
<artifactId>ceplot-applet</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
......
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/resources.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
what I need is to also sign jars before they are packaged, can I use jarsign plugin here, and how? I can't find where the jar files are temporarily stored during the build process.
Thanks,
This would be a pretty normal use of the jarsigner plugin. By default, jars are built by the jar plugin during the package phase and output to the ${project.build.directory}, which defaults to target.
You'd just need to sign the jars some time after they're built during package and before you assemble the zip. You could do that by binding the assembly plugin to a later phase or by adding the jarsigner plugin above the assembly plugin and binding it to the package phase, too.

Maven install plugin with depedency packaging

I have Project A and Project B. ProjectB just has only proprietary jars or third party libs that ProjectA needs which cannot be found in maven repository. I intended to package all the related ( grouping dependencies) jars of Project B into one/more jar files. Question is, how do I install these jars and shade/assemble them in to one jar at the same time using POM. I am getting proprietary jars installed separately but I cannot get them packaged them in to one jar. M2 eclipse is also not helping much , so I decide to use mvn commands inside eclipse. What is the best practice to do this?. I think shading them since I want to use these dependencies in other projects as well.Can I install and shade/assemble jars( logically group the related dependencies in to one jar) at the time using POM?.
I followed this( from stack over flow forum) , it did not work- as this is creating one project jar which doesn't have anything + proprietary jars separately but not shading all jars in to one. I want them installed and combined in to one jar at the same time.
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.projectdeps</groupId>
<artifactId>sharedlibs</artifactId>
<version>1.0-SNAPSHOT</version>
<name>shared-libs</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>install activationjar</id>
<goals><goal>install-file</goal></goals>
<phase>validate</phase>
<configuration>
<file>${basedir}/src/main/libs/activation.jar</file>
<groupId>com.mycompany.activation</groupId>
<artifactId>activation</artifactId>
<version>12.8</version>
<packaging>jar</packaging>
</configuration>
</execution>
<execution>
<id>install opsjar</id>
<goals><goal>install-file</goal></goals>
<phase>validate</phase>
<configuration>
<file>${basedir}/src/main/libs/Operations.jar</file>
<groupId>com.mycompany.gcs.ops</groupId>
<artifactId>Operations</artifactId>
<version>12.8</version>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>Operations</artifact>
<includes>
<include>/**</include>
</includes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.5</version>
<type>maven-plugin</type>
</dependency>
</dependencies>
</project>

Resources