What I want to do is to change two existing classes in a project (project A). These classes are of type .class.
I want to use maven shade in another project (project B) to point out these classes in project A, do some modification to them, and send them back to the project (project A).
How can I do this?
So far I've created a project (B) and added the maven shade plugin to the pom file and have tried to point out the classes I want to change. Do not know if this is the right way to do this.
This is my pom file:
<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>logic-rexster</groupId>
<artifactId>logic-rexster</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>com.tinkerpop.rexster:rexster-server:*:*</include>
</includes>
</artifactSet>
<filters>
<filter>
<artifact>rexster-server:rexster-server</artifact>
<includes>
<!-- These classes will be taken directly from dependency JAR -->
<include>/rexster-server/com/tinkerpop/rexster/server/RexsterApplicationProvider.class</include>
<include>/rexster-server/com/tinkerpop/rexster/filter/AbstractSecurityFilter.class</include>
</includes>
</filter>
</filters>
<transformers>
<transformer implementation=
"org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
<resource>LogicRexsterApplicationProvider</resource>
<file>RexsterApplicationProvider</file>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.tinkerpop.rexster</groupId>
<artifactId>rexster-server</artifactId>
<version>2.4.0</version>
</dependency>
</dependencies>
</project>
Regarding the modification I want to do:
I want to modify the RexsterApplicationProvider.class class.
to copy some stuff from the AbstractSecurityFilter.class class
[UPDATE]
I've added the two classes that I want to alter to my new project (B)'s src folder. (These classes have been decompiled before I added them here.)
Where do I go from here?
Related
Packaging Akka application.
Hi I am trying to package my application into an executable Jar. Below is my Pom.xml
<?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>com.personalProjects</groupId>
<artifactId>MyAkkaProject</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</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>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>allinone</shadedClassifierName>
<artifactSet>
<includes>
<include>*:*</include>
</includes>
</artifactSet>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>reference.conf</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>akka.Main</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-stream_2.12</artifactId>
<version>2.5.18</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-stream-kafka_2.12</artifactId>
<version>1.0-M1</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.1</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.4.3</version>
</dependency>
</dependencies>
</project>
I can't seem to get the Jar to work, it states missing akka.streams config.
I went through the official doc here
but it doesn't seem to work.
If I copy all Jar to output directory everything works just fine but the issue seems to be when I try to create a big fat jar with all the dependencies in it.
my MANIFEST.INF is below:
Manifest-Version: 1.0
Main-Class: MyAkkaProject.App
where App is the class with psvm and MyAkkaProject` is the package name
I resolved the issue, the issue was my IDE when I ran he project or even build it, it wasn't using Maven Lifecycle commands and hence the plug-in wasn't getting triggered.
I am a newbie when it comes to Maven, and so really struggling to solve the following problem because a colleague with real knowledge in this area has moved onto fresh pastures. Would really appreciate pointers to where I might be going wrong; I realise there must be lots of questions on StackOverflow about Maven & Eclipse classpaths, but having searched some of them, I need to ask in my own terms because of my lack of experience - sorry.
Some files are attached which I hope will be enough to form the equivalent of an SSCCE in pure Maven POM terms. The Java itself is irrelevant and subject to obvious confidentiality, but I can provide more info if needed.
So I have a small Maven project providing my own API for a third-party software protection dongle (DinKey, from Microcosm). The project is called dinkeypro with half a dozen of my classes which reference the manufacturer's class that reads/writes the dongle, namely DinkeyPro.class. This class is held inside DinkeyPro.JAR, which I reference as a dependency using a SystemPath and, as you can see from the following POM, I've tried two different SystemPath specs. Just for reference, note that the manufacturer requires the package structure for the class file to be:
uk/microcosm/dinkeydongle/DinkeyPro.class
Here is the POM for dinkeypro, with irrelevant dependencies removed for brevity/readability:
<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.xyz</groupId>
<artifactId>dinkeypro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>DinkeyPro API</name>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>dinkeyjar</groupId>
<artifactId>dinkeyjar</artifactId>
<scope>system</scope>
<version>1.0</version>
<!--<systemPath>${basedir}\src\main\resources\DinkeyPro.jar</systemPath>-->
<systemPath>C:\Dev\core_dinkeypro\src\main\resources\DinkeyPro.jar</systemPath>
</dependency>
</dependencies>
</project>
Access to the dongle API is required from two other Maven projects, 'client' and 'server'. They both appear to specify the exact same Maven dependency on dinkeypro (see POMs below) although, admittedly, client and server are structured differently in terms of folders (server uses the more recognisable src/main/java paradigm but the client does not, and I'm wondering if this is the source of the problem.
What happens is that the client project runs and successfully reads the dongle via my API, whilst the server throws:
Exception in thread "main" java.lang.NoClassDefFoundError: uk/microcosm/dinkeydongle/DinkeyPro
at com.xyz.dinkeypro.SoftwareProtectionReadOnlyAgent.isProtectionDevicePresent(SoftwareProtectionReadOnlyAgent.java:73)
at com.xyz.soft.ServerApp.initialize(ServerApp.java:1200)
at com.xyz.soft.ServerApp.main(ServerApp.java:310)
Caused by: java.lang.ClassNotFoundException: uk.microcosm.dinkeydongle.DinkeyPro
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 3 more
Here is the POM for client, which runs OK:
<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.xyz.soft</groupId>
<artifactId>client</artifactId>
<version>0.5.0-SNAPSHOT</version>
<name>client</name>
<description>client</description>
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target</outputDirectory>
<resources>
<resource>
<directory>${basedir}/target-resource</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>${basedir}/target-resource</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
</resource>
</resources>
<delimiters>
<delimiter>${*}</delimiter>
</delimiters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>client</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.xyz.client.ClientApp</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.xyz</groupId>
<artifactId>dinkeypro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
Here is the POM for the server which has the classpath problem:
<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.xyz.soft</groupId>
<artifactId>server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>server</name>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>additional-target-resources</id>
<phase>pre-integration-test</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<includeEmptyDirs>true</includeEmptyDirs>
<outputDirectory>${basedir}/target</outputDirectory>
<resources>
<resource>
<directory>${basedir}/target-resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>${basedir}/target-resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
</resource>
</resources>
<delimiters>
<delimiter>${*}</delimiter>
</delimiters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>run</id>
<phase>integration-test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.xyz.server.ServerApp</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>ebmsCore</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.xyz.server.ServerApp</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.xyz</groupId>
<artifactId>dinkeypro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
I've examined the content of both the built client and server JAR files. They both contain DinkeyPro.JAR at the root of their own JAR, and both can navigate from the root to com.xyz.dinkeypro.
So, confusion reigns. Can anyone shed any light on what I've done wrong ? As you can see, I am valiantly trying to keep with Maven, simply so that future changes to dinkeypro API can just roll through to client and server (and any other projects that may need it one day...). However, if this gets to be too much of a minefield, I may just have to place a copy of DinkeyPro.JAR in the resources folder of the server project so that I can move on.
Many thanks
In my Maven project, I have tried the maven-shade-plugin to produce an uber jar when I run mvn package. As a result, I get three jars in my target directory:
original-hello-world-0.1.0-SNAPSHOT.jar
hello-world-0.1.0-SNAPSHOT.jar
hello-world-0.1.0-SNAPSHOT-shaded.jar
I understand that first jar is the output of packaging without including dependencies. But the both the second and the third jars include dependencies and seem to be completely identical (they both have the same file size).
Is there supposed to be a difference between the second and third jars? If so, what is it? Otherwise, why are two identical jars being produced?
Here is my pom file:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mygroup</groupId>
<artifactId>myproject</artifactId>
<packaging>jar</packaging>
<version>0.1.0-SNAPSHOT</version>
<name>hello-world</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
<main.class>org.example.HelloWorld</main.class>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.source>${java.version}</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.jgrapht</groupId>
<artifactId>jgrapht-core</artifactId>
<version>0.9.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- To build executable jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>${main.class}</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<!-- To use Maven to run main class -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.2</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${main.class}</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
I copied your pom into a project of mine and only got two jars created when I ran mvn package.
Are you sure the "hello-world-0.1.0-SNAPSHOT-shaded.jar-shaded" jar is not the output of a previous maven run? Please try a mvn clean package and check what lands in the target folder.
If you would like an additional jar with the "-shaded" tag you can add the following to your pom in the shade plugin configuration:
<shadedClassifiedName>shaded</shadedClassifiedName>
I am using maven for configuration of an application consisting of multiple small services. Most of the services developed in java share the same maven configuration, as in the same build lifecycle, some shared resources (like spring AMQP).
So I have organized the shared resources in a SuperPom.
While the shade plugin doesn't really seem to disturb the install process, the antrun plugin of course won't find any of the files it should copy, due to there not being created any jar files by the shade plugin.
As I'd like the configuration of the shade/antrun plugin to be abstracted in the SuperPom, I need to skip the shade/copy goal.
I have tried mvn clean install -Dmaven.shade.skip=true, mvn clean install -Dmaven.copy.skip=true, mvn clean install -Dmaven.shade.shade.skip=true
Here is a small sample for you to play with:
<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>Test</groupId>
<artifactId>SuperTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<log4j.version>1.2.17</log4j.version>
<destination>pleasedeleteme</destination>
<mainpackage>com.uk.cc.it.info.gov.test.xxx</mainpackage>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${mainpackage}.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${destination}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</project>
Did you try setting the phase of maven-shade-plugin to none in the super-pom and then overriding this in the client poms?
So in the parent pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<id>shade</id>
<phase>none</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<!-- ... -->
</configuration>
</execution>
</executions>
</plugin>
And in the child poms that need it:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<!-- no need to specify version -->
<executions>
<execution>
<id>shade</id>
<phase>package</phase>
<!-- no need to specify configuration -->
</execution>
</executions>
</plugin>
The maven-shade-plugin doesn't have a parameter to skip. Often the shade-plugin isn't there just for fun, so you might wonder if you really want to skip this. If you think it is still valid, you have to create a profile with activation like this:
<activation>
<property>
<name>skipShade</name>
<value>!true</value>
</property>
</activation>
This way it is activated by default, unless you add -DskipShade or -DskipShade=true.
Maven 3.6.1 gives you a new approach.
In the superPom you can define a profile for your shading configuration:
<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>Test</groupId>
<artifactId>SuperTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<log4j.version>1.2.17</log4j.version>
<destination>pleasedeleteme</destination>
<mainpackage>com.uk.cc.it.info.gov.test.xxx</mainpackage>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${destination}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>shade</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${mainpackage}.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
In the user's settings.xml under .m2 you can add a profile of the same id to enable the shade profile configuration of your superPom. This gives you the option to simple toggling the shading from inside your IDE like Intellij IDEA (only tested in Intellij).
<settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
...
<!-- toggle shading from inside Intellij IDEA -->
<profiles>
<profile>
<id>shade</id>
</profile>
</profiles>
<!-- Shade Profile has to be activeProfile to be
able to explicitly disable shading -->
<activeProfiles>
<activeProfile>shade</activeProfile>
</activeProfiles>
</settings>
In the child project you can add a .mvn/maven.config file to your child project template to predefine shading for the project by default. (Requires a CVS template that is used to predefine a company standard.)
The approach using a maven.config is useful if some of your team members do not have the profile in their settings.xml file and you have to take care that shading will be done most of the time.
.mvn/maven.config:
-Pshading
The profile can also be activated by default using jenkinsfile for Jenkins by passing -Pshade. It will overwrite the maven.config setting. To disable use -P!shade
Please note if you are using maven.config file in Intellij (2020.2.2): The .mvn/maven.config file must exists in the subdirectory of the root aggregator pom folder. Building a subproject form the IDE does not respect a .mvn/maven.config file on the subproject level at the moment. Running a mvn command from the command line in the subproject folder will repespect both, the child project .mvn/maven.config and the parent .mvn/maven.config.
Disabling the maven shade plugin worked for me. The build was stock trying to produce the dependency reduced pom file before I disabled the Maven shade plugin.
The skip option was introduced in version 3.3.0 of the shade plugin, so now skipping can be done dynamically using, for example, properties:
<properties>
....
<skipShaded>true</skipShaded>
</properties>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<skip>${skipShaded}</skip>
...
</configuration>
</execution>
</executions>
</plugin>
In the above the default is to skip, and this can be overridden with passing -DskipShaded=false to mvn.
When using the maven assembly plugin to build an uberjar and then package it into a zip file, I encounter a runtime failure:
java.lang.RuntimeException: could not find writer for content-type text/xml type: java.lang.String
This failure does not occur when I run my project within eclipse, or when I create and executable .jar using the eclipse Export -> Runnable Jar File so I suspect there is something wrong with the way I'm using maven creating the uberjar.
How do I fix this problem?
Turns out, the root of my problem was a conflict with the javax.ws.rs.ext.Providers file that occurs when the maven assembly plugin creates the jar. (This file can be found in the uberjar within META-INF -> services -> javax.ws.rs.ext.Providers)
The Providers file contains a list of available provider classes. Within the dependencies of my project this file exists in more than one place, and the different copies contain different provider lists. The maven assembly plugin simply chooses one version to include in the jar, and so at runtime the required "writer" class cannot be found: This class is not listed in the Providers file within the jar.
I used the maven shade plugin to overcome this problem. The shade plugin contains a facility to selectively merge duplicate files contained within the dependency tree. Within pom.xml:
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/services/javax.ws.rs.ext.Providers</resource>
</transformer>
Tells maven to merge by appending any duplicates of javax.ws.rs.ext.Providers.
Also, by setting the maven shade plugin to execute during the package phase of my build, and then the maven assembly plugin to execute at the install phase, I was able to create an executable uberjar, then package that uberjar within a .zip file, all with a simple mvn clean install invocation.
Here's what my pom.xml looks like:
<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>
<parent>
...
</parent>
<groupId>com.foo.bar</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>2.1.0.0-SNAPSHOT</version>
<name>My App</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<issues-product>MyApp</issues-product>
<issues-component>MY-APP</issues-component>
</properties>
<dependencies>
...
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<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>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.foo.bar.MyMainClass</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/services/javax.ws.rs.ext.Providers</resource>
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.2</version>
<configuration>
<finalName>${project.artifactId}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/assembly/my-app-assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</project>
And here is my-app-assembly.xml:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.2.2 http://maven.apache.org/xsd/assembly-2.2.2.xsd">
<id>bin</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}</directory>
<outputDirectory/>
<includes>
<include>Readme.pdf</include>
<include>config\</include>
<include>input\</include>
<include>output\</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>bin\java\</outputDirectory>
<includes>
<include>my-app.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>