For a scala compiler, what are the differences between 'Symbol '***' is missing from the classpath' error and 'object *** is not a member' error? - scala

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:
What are the differences between these 2 error information?
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

Related

maven assembly:single doesn't resolve dependency

I am trying to make a single jar with all dependencies resolved so that I can run this jar from command prompt. I am using maven's assembly:single but whenever I am doing so, I get an issue
[ERROR] com.XXX.XXXX.XXX:XXX-XXX-XXX:jar:XXX
[ERROR]
[ERROR] from the specified remote repositories:
[ERROR] A (http://XXXXX/, releases=true, snapshots=true),
[ERROR] B (http://XXXX/, releases=true, snapshots=true),
[ERROR] C (https://repo.maven.apache.org/maven2/, releases=true, snapshots=true
),
[ERROR] D (https://XXXXX, releases=false, snapshots=true)
[ERROR] Path to dependency:
[ERROR] 1) com.test.Report:myjar:jar:0.0.1-SNAPSHOT
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e swit
ch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please rea
d the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionE
xception
This is the pom I am working with
Now these jars are already resolved and are present in Maven Dependency folder. I can run the whole project from Eclipse but need to give this jar to client with all the jars included. Any help is appreciated. Thanks :)
One approach is to use the "jar-with-dependencies" configuration in your pom.xml. This will package all your dependencies in the jar.
For eg:
<build>
<plugins>
<!-- any other plugins -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Another approach is to use the maven shade plugin.
For eg:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
The maven shade plugin will basically create two jars at the end. The first jar is the normal jar which contains just the compiled classes of your source code.
The second jar will also contain your compiled classes but it will also include the class files from all your dependencies. This is the jar that you should give to your client.
Ok. Probably no one would be looking at this answer but still I would like to have a note for my future self. This issue was different from what exception I was getting. To run any plugin make sure that <plugin> is inside <plugins> inside <build> (not under <pluginManagement>). Doing this ran the plugin and jar with dependencies was formed upon mvn install.

Maven Eclipse multi-module shaded dependency

In a multi-module Maven project, one of the modules is a shaded module (e.g. no source, but generates a jar during package phase). Other modules reference this module as a dependency (all under same parent). Is there a way to have Eclipse recognize the shaded module as a dependency? Eclipse only covers up to compile.
Currently it works on the command line (since package is run), but in Eclipse it shows errors.
I have not been able to find a solution to this.
Details:
- Parent project
- Module A
- Module B
Module A is a shaded module meaning it has something like:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<id>shade</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>com.third.party</pattern>
<shadedPattern>my.shaded.third.party</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Module B has Module A as a dependency (under dependencies-dependency). Module B tries to use classes from Module A by importing the relocated paths ...e.g:
import my.shaded.third.party.Foo;
This doesn't work because it can't find Foo. This makes sense since only compile phase is run in Eclipse build.
Rightclick on dependent project > Maven > Disable Workspace Resolution
This will tell Eclipse to use Maven's compilation instead, meaning you will be able to use my.shaded.* imports.
However, this does have the consequence that your projects will not be updated until you build them using maven. It is a solution to get Eclipse to recognise shaded dependencies, nevertheless.

GWT compilation is skipped in maven when module packaging is pom

I am trying to reuse a assembled gwt compilation in another war. For this i am try to change the current maven module's packaging from war to pom. I then plan to use maven-assembly-plugin to zip up gwt's module js output and use that later on in another war module.
I tried changing the packaging tag from <packaging>war</packaging> to <packaging>pom</packaging> in pom.xml from Validation sample . gwt-maven-plugin never enters into compilation. Instead, it skips compilation!!!!!
What is happening?
Is this expected?
Is there any workaround?
To join multiple gwt compiled modules into a single .war file, it is very easy with the maven-dependency-plugin
Package all your gwt examples as habitual (.war), and install them mvn install or mvn deploy if you have a private maven repo.
Create an empty maven module of type war, with no code but with the maven folder structure, you can put any additional stuff you need here like a global src/main/webapp/index.html.
Configure the new module to use the maven-dependency-plugin like shown below, and run mvn package:
<dependency>
<groupId>my.group</groupId>
<artifactId>example1</artifactId>
<version>...</version>
<type>war</type>
</dependency>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-gwt-examples</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>my.group</includeGroupIds>
<includes>**/example1/**</includes>
<outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Finally and related with the gwt-maven-plugin, like with any other maven pluging, it would be enough to select an appropriate phase of the pom-packaging life cycle (package, install or deploy):
...
<packaging>pom</packaging>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
...
<configuration>
...
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
Unfortunately, gwt-maven-plugin specifically disallows compilation when packaging is pom, take a look to line #269 of CompileMojo.java
You can create the reusable modules (that you mention as samples in the comments) as separate GWT projects with no EntryPoint. Package them as jar and add the following as resources:
the client side source code
other resource items that will be necessary for the final compilation (images, xml files, etc.)
Something like this:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
...
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/services/**</include>
<include>**/client/**</include>
<include>**/public/**</include>
<include>**/*.gwt.xml</include>
</includes>
</resource>
</resources>
</build>
That's it, you can reuse it in any other GWT project. When you will do so, you just have to add the dependency (to the reusable module) in the pom.xml and import in the *.gwt.xml.
As for Maven's behaviour, it seems correct. pom packaging is going through package, install and deploy phases and
By default, the compile goal is configured to be executed during the ''prepare-package'' phase to run as late as possible.
You could change the phase in the plugin's execution, but I think it's risky because you can't know when exactly during the package phase will your code get compiled.

m2e shade eclipse "project main artifact does not exist"

I'm trying to make a deployment package that bundles all the dependencies of my maven module that has dependencies to another maven project in eclipse.
I have this in my pom.xml
<modelVersion>4.0.0</modelVersion>
<groupId>com.my.proj</groupId>
<artifactId>AAA</artifactId>
<version>0.0.2-SNAPSHOT</version>
<name>btc</name>
<dependencies>
<dependency>
<groupId>com.another.proj</groupId>
<artifactId>BBB</artifactId>
<version>1.4-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.group.id.Launcher1</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
I use that "m2 Maven Build" in eclipse with the goal "org.apache.maven.plugins:maven-shade-plugin:shade" and the "Resolve Workspace artifacts" ticked.
It's failing with
--- maven-shade-plugin:1.6:shade (default-cli) # AAA ---
[ERROR] The project main artifact does not exist. This could have the following
[ERROR] reasons:
[ERROR] - You have invoked the goal directly from the command line. This is not
[ERROR] supported. Please add the goal to the default lifecycle via an
[ERROR] <execution> element in your POM and use "mvn package" to have it run.
[ERROR] - You have bound the goal to a lifecycle phase before "package". Please
[ERROR] remove this binding from your POM such that the goal will be run in
[ERROR] the proper phase.
I ran out of idea at this point.
[ERROR] The project main artifact does not exist. This could have the following
We were getting this problem recently. What resolved it for us was to not do mvn shade:shade but instead use:
mvn package
This does additional compilation and package work before running the shade plugin and so the main class was available on the classpath.
The shade plugin is attempting to include the project's artifact in the shaded JAR. Since it doesn't exist (yet), you're getting this error. You either need to build/package the project artifact first (e.g., by attaching the shade goal to the package phase)
If you don't have any project artifact to include in the shaded JAR, you can add an excludes node to remove the project's artifact.
Here's an example:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.group.id.Launcher1</mainClass>
</transformer>
</transformers>
<excludes>
<exclude>com.my.proj:AAA</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>

How do I set the Scala compiler to use a plugin when I build using Maven?

So I have a Maven project with two submodules. The first is the compiler plugin itself, which gets compiled as I expect it to.
The second submodule is some example code that I want to compiler with the previously built compiler plugin.
So I have this in the pom file:
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDir>.</sourceDir>
<!--jvmArgs>
<jvmArg>-Xms64m</jvmArg>
<jvmArg>-Xmx1024m</jvmArg>
</jvmArgs-->
<args>
<arg>-Xplugin:../plugin/target/plugin-1.0-SNAPSHOT.jar</arg>
</args>
</configuration>
</plugin>
Which based on what I could read about it, should give the right arguments to the compiler, but it doesn't seem to do anything at all.
Edit: As suggested, I tried to use the compilerPlugins tag, so the relevant area became:
<configuration>
<sourceDir>.</sourceDir>
<compilerPlugins>
<compilerPlugin>
<groupId>*groupid*</groupId>
<artifactId>plugin</artifactId>
<version>1.0-SNAPSHOT</version>
</compilerPlugin>
</compilerPlugins>
</configuration>
And that did indeed work, unfortunately it now produces this error:
Unable to find resource 'groupid:plugin:jar:1.0-SNAPSHOT' in repository scala-tools.org (http://scala-tools.org/repo-releases)
Which is quite understandable, as it isn't there.
I tried to add it as a dependency to the dependencies list, but that didn't change anything.
final edit:
executing:
mvn clean install
fixed it.
Thanks
Doesn't it work using the compilerPlugin configuration to set the artifact?
http://scala-tools.org/mvnsites/maven-scala-plugin/compile-mojo.html#compilerPlugins
Update: It's basically an artifact like a dependency. You will add your compiler plugin as artifact inside it:
<compilerPlugins>
<compilerPlugin>
<groupId>_your plugins groupId_</groupId>
<artifactId>plugin</artifactId>
<version>1.0-SNAPSHOT</groupId>
</compilerPlugin>
</compilerPlugins>