Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does maven-shade-plugin work with scala classes?

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>```
like image 381
Jas Bali Avatar asked Mar 23 '19 01:03

Jas Bali


People also ask

Does Maven work with scala?

If you're familiar with Maven, you can go ahead with the Scala Maven Plugin.

What is Maven Shade plugin used for?

This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies.

What is Maven scala plugin?

The scala-maven-plugin is used for compiling/testing/running/documenting scala code in maven.

How do you shade a dependency?

In Java, to “shade” a dependency is to include all its classes and the classes from its transitive dependencies in your project, often renaming the packages and rewriting all affected bytecode.

What is dependency reduced POM?

Short Answer. The dependency-reduced-pom. xml removes transitive dependencies which are already in your shaded jar. This prevents consumers from pulling them in twice.


Video Answer


1 Answers

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.

like image 105
Rorschach Avatar answered Oct 28 '22 22:10

Rorschach