1

In a recent experiment, I tried to use maven-shade plugin to move all classes in a package com.original.work under a scala library into a different package, and compile into a new project JAR:

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>

            <configuration>
              <shadeTestJar>true</shadeTestJar>

              <createSourcesJar>true</createSourcesJar>
              <shadeSourcesContent>true</shadeSourcesContent>

              <createDependencyReducedPom>true</createDependencyReducedPom>
              <dependencyReducedPomLocation>
                ${project.build.directory}/dependency-reduced-pom.xml
              </dependencyReducedPomLocation>
              <!--              <generateUniqueDependencyReducedPom>true</generateUniqueDependencyReducedPom>-->

              <!--              <keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>-->
              <promoteTransitiveDependencies>true</promoteTransitiveDependencies>

              <!--              <shadedClassifierName>${spark.classifier}</shadedClassifierName>-->
<!--              <useBaseVersion>true</useBaseVersion>-->

              <relocations>
                <relocation>
                  <pattern>com.original.work</pattern>
                  <shadedPattern>com.relocated.work</shadedPattern>
                </relocation>
              </relocations>

              <artifactSet>
                <includes>
                  <include>com.original.work:work</include>
                </includes>
              </artifactSet>
            </configuration>
          </execution>
        </executions>
      </plugin>

Unfortunately, this JAR behave strangely if being used by other scala projects. E.g. if the project 'work' already has a trait defined under a package:

package com.original.work.utils

trait IDMixin {

...

Then for any other scala project that use the new JAR, using IDMixin will fail. Specifically:

  • If I import com.original.work.utils.IDMixin directly, I will get the following exception:
[ERROR] .../ExampleOld.scala:4: object original is not a member of package com
[ERROR] object ExampleOld extends com.original.work.utils.IDMixin{}
[ERROR]                               ^

  • If I import com.relocated.work.utils.IDMixin, I will get the following exception:
[ERROR] .../Example.scala:3: Symbol 'term com.original.work.utils' is missing from the classpath.
This symbol is required by ' <none>'.
Make sure that term utils is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
A full rebuild may help if 'IDMixin.class' was compiled against an incompatible version of com.original.work.

So my questions are:

  1. What are the differences between these 2 error information?

  2. If this problem is caused by maven-shade plugin, what should I do to fix it? If not possible, are there any other build tools (sbt, gradle, mill) capable of completing the relocation job?

Thanks a lot for your opinion

tribbloid
  • 4,026
  • 14
  • 64
  • 103
  • 1
    Well, literal answer to your first question is that the error "Symbol is missing from the classpath" comes from `scala-reflect` JAR ([`scala.reflect.internal.pickling.UnPickler`](https://github.com/scala/scala/blob/2.13.x/src/reflect/scala/reflect/internal/pickling/UnPickler.scala#L262-L265)) while "is not a member of" comes from `scala-compiler` JAR ([`scala.tools.nsc.typechecker.ContextErrors`](https://github.com/scala/scala/blob/2.13.x/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala#L443)). – Dmytro Mitin Nov 24 '20 at 01:22
  • It's a sharp observation, but it baffles even more as my code doesn't even use runtime reflection, and the error wasn't thrown on runtime – tribbloid Nov 25 '20 at 20:09
  • `scala-reflect` doesn't mean runtime reflection, it means reflection (both compile-time and runtime). – Dmytro Mitin Nov 25 '20 at 20:12
  • If your code doesn't use reflection it's still possible that maven plugin does. And Scala compiler definitely does. – Dmytro Mitin Nov 25 '20 at 20:15
  • Try to use compiler option `-Xprint: ...` in order to see how your code looks after maven plugin worked. – Dmytro Mitin Nov 25 '20 at 20:22

0 Answers0