Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven dynamically exclude class with same name from different dependencies

There are two classes com.package.A, one coming from

<dependency>
    <groupId>com.package</groupId>
    <artifactId>art1</artifactId>
</dependency>

and one coming from

<dependency>
    <groupId>com.package</groupId>
    <artifactId>art2</artifactId>
</dependency>

Notice that the artifact ids are different.

For different Maven profiles, I want to exclude one version and just keep the other version. I am using the Shade Plugin.

like image 831
Amit Kumar Avatar asked Feb 07 '23 05:02

Amit Kumar


1 Answers

With the maven-shade-plugin, it is possible to exclude certain class for specific dependencies. This is configured with the help of the filters property:

Archive Filters to be used. Allows you to specify an artifact in the form of a composite identifier as used by artifactSet and a set of include/exclude file patterns for filtering which contents of the archive are added to the shaded jar.

In your case, to exclude the class com.package.A from the dependency art2, you can have:

<filters>
  <filter>
    <artifact>com.package:art2</artifact>
    <excludes>
      <exclude>com/package/A.class</exclude>
    </excludes>
  </filter>
</filters>

To make this dynamic, i.e. select at build-time which com.package.A class you want to keep, you don't need to use a profile. You can use a Maven property that will hold the artifact id of the dependency to filter. In your properties, add

<properties>
  <shade.exclude.artifactId>art2</shade.exclude.artifactId>
</properties>

The shade.exclude.artifactId property will hold the artifact id of the dependency to filter. By default, this configuration would select art2. Then, in the <filter> configuration of the Shade Plugin, you can use <artifact>com.package:${shade.exclude.artifactId}</artifact>.

Here's a full configuration of this in action:

<build>
  <plugins>
    <plugin>
      <artifactId>maven-shade-plugin</artifactId>
      <version>2.4.3</version>
      <executions>
        <execution>
          <id>shade</id>
          <goals>
            <goal>shade</goal>
          </goals>
          <phase>package</phase>
          <configuration>
            <filters>
              <filter>
                <artifact>com.package:${shade.exclude.artifactId}</artifact>
                <excludes>
                  <exclude>com/package/A.class</exclude>
                </excludes>
              </filter>
            </filters>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
<properties>
  <shade.exclude.artifactId>art2</shade.exclude.artifactId>
</properties>

Running mvn clean package will create an uber jar with the A.class from art1 since the one from art2 was excluded. And then, running mvn clean package -Dshade.exclude.artifactId=art1 will keep this time A.class from the dependency art2 since the one from art1 was excluded.

like image 144
Tunaki Avatar answered Mar 11 '23 06:03

Tunaki