I have a maven project with both Java and Scala components, but when I use maven-shade-plugin, it relocates package names for both Java and Scala files, but ONLY renames packages inside Java files, Scala files still contain the older package names, what am I missing?
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<!--<minimizeJar>true</minimizeJar>-->
<artifactSet>
<includes>
<include>ml.dmlc:xgboost4j-spark</include>
<include>ml.dmlc:xgboost4j</include>
</includes>
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>ml.dmlc.xgboost4j</pattern>
<shadedPattern>ml.dmlc.xgboost4j.shaded</shadedPattern>
</relocation>
</relocations>
<transformers>
</transformers>
</configuration>
</execution>
</executions>
</plugin>```
Sadly, I believe that Maven is intended to have this functionality but, currently (Dec 2020), it does not.
This can be seen with this bug ticket:
https://issues.apache.org/jira/browse/MSHADE-345
workaround
I have personally done a silly workaround for this. I make a new empty mvn project that has the dependency:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.0-jre</version>
</dependency>
And the plugin:
<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>
<relocations>
<relocation>
<pattern>com.google.</pattern>
<shadedPattern>shader.com.google.</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
Then in the project with code that requires a low version of guava and a new version of guava, include the empty project as a dependency.
<dependency>
<groupId>com.yoursite.yourwork</groupId>
<artifactId>shader</artifactId>
<version>0.0.1</version>
</dependency>
Then in a .scala file you import the new (version 28) guava classes like this:
import shader.com.google.common.graph.Network
Why this works
Since the error only occurs in scala projects where you refer to your own class that uses the dependency, or as said in the question "Scala files still contain the older package names", shading a project that does not refer to its own dependencies bypasses the bug.
Yes, it does. Choose any build version you want and import the library into your Scala project.
How to create multiple war files from one maven eclipse Jersey Rest API project? As i have multiple Rest APIs in this project. I want to have one war file per each Rest API. How to do? As i don't want to use multi module maven project.
I think your best bet is using Maven's executions feature (i.e. "run" any plugin, multiple times, in your case maven-war-plugin).
So basically you "run" maven-war-plugin multiple times, and configure it differently for each war you want to make. Below is an example taken from SO (you need to tailor the configuration section for each execution.
Please be aware, that this is considered "last-resort" build design, and it is still advisable to use multi-module.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>list</id>
<phase>package</phase>
<goals>
<goal>war</goal>
</goals>
<configuration>
<warName>myProj-list.war</warName>
<webResources>
<resource>
<directory>src/main/webapp</directory>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</webResources>
<filtering>true</filtering>
<filters>
<filter>src/main/filters/list.properties</filter>
</filters>
</configuration>
</execution>
...
<!-- more executions -->
</execution>
</executions>
</plugin>
I'm trying to use the Maven shade plugin (according to the tutorial here) to create a "fat jar" from my project.
I'm working on my project in eclipse and when I look at the (huge) resulting fat jar, I see that it contains a lot (possibly all) of classes from the Eclipse IDE code itself.
Why is it doing that and how to prevent it from doing it?
I've tried just listing a bunch of directories in the <exclude> <filters>, but the Eclipse JDT jars also have some files in jars "root" folders and its not easy to list all of these as well.
The shade <plugin> part of the pom.xml file currently looks like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${maven.shade.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>vertx-unit*/**</exclude>
<exclude>org/apache/derby/**</exclude>
<exclude>javax/annotation/**</exclude>
<exclude>com/google/googlejavaformat/**</exclude>
<exclude>org/eclipse/**</exclude>
<exclude>jdtCompilerAdapter.jar</exclude>
<exclude>ant_tasks/**</exclude>
<exclude>META-INF/services/org.osgi.framework.launch.FrameworkFactory</exclude>
<exclude>about_files/**</exclude>
<exclude>org/osgi/**</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>io.vertx.core.Starter</Main-Class>
<Main-Verticle>io.thesphere.service.App</Main-Verticle>
</manifestEntries>
</transformer>
</transformers>
<artifactSet />
<outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jar</outputFile>
</configuration>
</execution>
</executions>
</plugin>
I'm trying to get Maven to filter & copy two files used for testing.
I've tried putting them in src/test/resources as well as src/test/application (in case it works similar to src/main/application) but nothing happens.
The documentation doesn't say anything about test resources.
Thanks in advance!
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals><goal>read-project-properties</goal></goals>
<configuration>
<files>
<file>${filter.build.props}</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<filtering>true</filtering>
<displayName>myapp</displayName>
<version>1.4</version>
<defaultJavaBundleDir>lib</defaultJavaBundleDir>
</configuration>
</plugin>
</plugins>
<filters>
<filter>${filter.build.props}</filter>
</filters>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
Test resources aren't packaged in the final package (be it JAR, WAR, EAR). I'm not sure what you want to achieve exactly but maybe you're actually looking for a solution based on filtering and profiles (to pick up the wanted filter).
In my project, I have a resources directory (src/main/resources) that contains properties and XML files.
I want to filter only the properties files, but not any others kind of files (XML for example). Thus, I've set this in my pom.xml:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
</resource>
</resources>
</build>
This is working well when I run a Maven 2 package command, i.e. both XML and properties files are included in my final JAR, and only properties files have been filtered.
However, as I want to include this project in Eclipse, when I run the command mvn eclipse:eclipse, and import the project, then I have a problem with the source declared in my project properties.
In the "Java Build Path" option of Eclipse for my project, in tab "Source", I see the src/main/resources directory, but Eclipse also add filters which say to exclude all java files (Excluded: **/*.java) and include only properties files (Included: **/*.properties).
In the .classpath file generated, I get this line:
<classpathentry kind="src" path="src/main/resources" including="**/*.properties" excluding="**/*.java"/>
This way, the JAR built by Eclipse is not correct as all my XML files are not in the JAR.
How can I solve this problem?
Edit, regarding this page, I've added this in my pom.xml:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.6</version>
<configuration>
<sourceIncludes>
<sourceInclude>**/*.xml</sourceInclude>
</sourceIncludes>
</configuration>
</plugin>
</plugins>
However, the .classpath generated is not modified with the adequate information...
Edit again.
The addition in my previous edit works only for version 2.6.1+ of the Eclipse plugin, not for 2.6. So, I've tried with version 2.7. However, I don't know how to force the Eclipse plugin to not define the including attribute:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.7</version>
<configuration>
<sourceIncludes>
<sourceInclude>*</sourceInclude>
</sourceIncludes>
</configuration>
</plugin>
</plugins>
If I run the mvn eclipse:eclipse command, I get the following error:
Request to merge when 'filtering' is not identical. Original=resource src/main/resources: output=target/classes, include=[**/*.properties], exclude=[**/*.java], test=false, filtering=true, merging with=resource src/main/resources: output=target/classes, include=[], exclude=[**/*.properties|**/*.java], test=false, filtering=false
Well maven-eclipse-plugin is very bugy :( and we use version 2.5. The solution we found is copy resources to different folder. For regular maven bulid we use default filtering but for eclipse we have special profile. Here is maven-eclipse=plugin configuration in this profile:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources-step1</id>
<goals>
<goal>copy-resources</goal>
</goals>
<phase>initialize</phase>
<configuration>
<outputDirectory>${project.build.directory}/for-eclipse/resources</outputDirectory>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-resources-step2</id>
<goals>
<goal>copy-resources</goal>
</goals>
<phase>initialize</phase>
<configuration>
<outputDirectory>${basedir}/src/main/resources</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}/for-eclipse/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Of course you must modify include/exclude section for your needs.
I did some testing with the maven eclipse plugin 2.6, 2.5.1, 2.7 and 2.8-SNAPSHOT and none of them is indeed producing the expected result.
The only workaround I've been able to find is to use another directory for the resources you don't want to filter. Something like this:
...
<build>
<resources>
<resource>
<directory>src/main/resources1</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources2</directory>
<filtering>false</filtering>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.6</version>
</plugin>
</plugins>
</build>
I agree that this is ugly. But at least, it produces a .classpath with the following entries:
<classpathentry kind="src" path="src/main/resources1" including="**/*.properties" excluding="**/*.java"/>
<classpathentry kind="src" path="src/main/resources2" including="**/*.xml" excluding="**/*.java"/>
That should allow you to deploy on Tomcat.
By the way, I wouldn't use the version 2.7 of the plugin because it's not working (see this thread). The version 2.6 may not produce the expected output but at least, it works.
Use properties to have Eclipse and Maven build into different directories. Now you can use Eclipse to quickly develop your code and use Maven to deploy it as a JAR.
I suggest that you either the mvn package goal as an external tool from Eclipse. I don't think that Eclipse can handle complex Maven workflows.
Even the m2eclipse plugin, which I use and highly recommend, has troubles with complex workflows.