I encountered this confusing issue when working on a larger project, so I’ve created a simple reproduction project to better reproduce and explain my issue. I’m not sure if it is possible for me to upload a zip with the whole structure, but it is only 5 files: https://paste.gg/p/anonymous/f502a8e613a64aeeae671b4c41587c43.
I have a parent module MavenTest with 3 submodules: A, B, and C.
A only contains the class org.example.maventest.A
.
B shades A like so:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>org.example.maventest</pattern>
<shadedPattern>org.example.maventest.a</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
This relocates the org.example.maventest.A
class to org.example.maventest.a.A
.
C shades B like so:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
This should simply shade in the relocated org.example.maventest.a.A
class from module B into C’s jar.
Expected behavior: running mvn clean install
to build all the modules should create a jar C that only includes the relocated org.example.maventest.a.A
file.
Actual behavior: When the shade plugin runs for module C, it reports this:
[INFO] --- shade:3.6.0:shade (default) @ C ---
[INFO] Including org.example:B:jar:1.0-SNAPSHOT in the shaded jar.
[INFO] Including org.example:A:jar:1.0-SNAPSHOT in the shaded jar.
[INFO] Dependency-reduced POM written at: /MavenTest/C/dependency-reduced-pom.xml
Module A seems to incorrectly be included in C’s jar, which causes the original A class to be shaded in as well (using IntelliJ to look inside the jar):
The strange part (and the specific title of this question), is that if I only build module C using mvn clean install -pl :C
, maven correctly only includes the relocated class A:
[INFO] --- shade:3.6.0:shade (default) @ C ---
[INFO] Including org.example:B:jar:1.0-SNAPSHOT in the shaded jar.
[INFO] Dependency-reduced POM written at: /MavenTest/C/dependency-reduced-pom.xml
This suggests to me that is possible to only include the relocated class A
from module B in C, but I can’t imagine why the shade plugin would be including different classes when I run a full build vs a single module build.
I think I need to change the configuration of my project in some way so that when I run a full build with mvn clean install
, the C jar only includes org.example.maventest.a.A
. When C shades B, it should not try to include module A, since B contains those module A classes already.
This also seems to affect compilation. For example, if I add this class to module C:
public class C {
org.example.maventest.A first = null;
org.example.maventest.a.A second = null;
}
When I run the full build (or look at it statically with IntelliJ), this code compiles.
However, when I build module C independently, this code fails because the org.example.maventest.A
class cannot be found. I want the behavior of the independent build, where module A is seemingly excluded from the compile classpath.