Maven Shade plugin , main class not found (Scala, Intellij) - scala

I tried to look around a lot to solve this problem but I can't really solve it.
In my scala project i'm trying to build a fatjar with all the dependencies in it, so here is my pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.my.project.start.CommandStarter</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
So i'm pointing to my main class, and in the manifest , inside the jar , i can see that the main class is there too..
But when i run my jar by launching : scala myjar.jar i have a
java.lang.ClassNotFoundException
Any suggestion?
Thank you!

Related

Generate two jars of same Maven project using different Scala version

I am having a Maven project with Scala code and i want to generate the two jars based on the different Scala versions (2.10.6 and 2.11.8).
If someone please suggest the solution how i can achieve this in single maven install execution or if there is any other way of achieving this in Maven using some Maven plug in.
I am able to solve this problem using multiple executions.
<build>
<plugins>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>scala-version-2.10</id>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
<configuration>
<scalaVersion>2.10.6</scalaVersion>
<outputDir>${project.build.outputDirectory}/scala-2.10</outputDir>
</configuration>
</execution>
<execution>
<id>scala-version-2.11</id>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
<configuration>
<scalaVersion>2.11.8</scalaVersion>
<outputDir>${project.build.outputDirectory}/scala-2.11</outputDir>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>scala-2.10</id>
<goals>
<goal>jar</goal>
</goals>
<phase>package</phase>
<configuration>
<classifier>scala-2.10</classifier>
<excludes>
<exclude>scala-2.11/**</exclude>
<exclude>sparkScala/**</exclude>
<exclude>sparksql/**</exclude>
<exclude>*.timestamp</exclude>
</excludes>
</configuration>
</execution>
<execution>
<id>scala-2.11</id>
<goals>
<goal>jar</goal>
</goals>
<phase>package</phase>
<configuration>
<classifier>scala-2.11</classifier>
<excludes>
<exclude>scala-2.10/**</exclude>
<exclude>sparkScala/**</exclude>
<exclude>sparksql/**</exclude>
<exclude>*.timestamp</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Create profiles that have dependency overridden for different versions of Scala. You will need to run mvn install on both profiles. For more information see: different-dependencies-for-different-build-profiles-in-maven
Also you need to alter artifact name / version in profiles to make distinction between those two.

increase scala stack size during maven build

While compiling a scala project using maven (mvn compile) , I am getting error: java.lang.StackOverflowError.
I got the same from eclipse as well, but could solve it by giving Additional command line parameters: -J-Xss256m for scala compiler , as given here How to increase scala stack size
But I am getting the same error while doing "mvn compile". How can I solve this ? Basically how to increase scala stack size while building via maven
You can configure the scala-maven-plugin in the pom.xml like bellow
<project>
...
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<jvmArgs>
<jvmArg>-Xms256m</jvmArg>
<jvmArg>-Xmx1024m</jvmArg>
</jvmArgs>
</configuration>
</plugin>
...
</project>
For more see http://davidb.github.io/scala-maven-plugin/example_compile.html

scala-maven-plugin : ClassNotFoundException

I am trying to run a simple Scala Hello World program using scala-maven-plugin from the command line in my Ubuntu VM running in Win-7 host OS.
I tried to execute in the following two ways :-
mvn scala:run -DmainClass=com.infoobjects.HelloWorld
Declaring the main class in a launcher tag in pom.xml and then executing mvn scala:run from the command line
But I am getting ClassNotFoundException in either case.
Directory Structure :-
Project > src > main > scala > com > infoobjects > HelloWorld.scala
Thanks in advance.
Here's my pom.xml
<build>
<finalName>sparkplay</finalName>
<plugins>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<configuration>
<launchers>
<launcher>
<id>launcher1</id>
<mainClass>com.infoobjects.HelloWorld</mainClass>
</launcher>
</launchers>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</configuration>
</plugin>
</plugins>
</build>
your pom.xml has schema's issue : <executions> should not be child of <configuration>. So everything under <executions> is ignored
see Maven Model

GWT 2.5.0 mvn install error "Rebind result <class> must be a class"

Problem: I run mvn install on my GWT 2.5.0 project that I built with the gwt-maven-plugin and get the error Rebind result 'c3gw.fwk.gui.client.ClientFactory' must be a class.
This is a snippet of my pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test</goal>
<goal>i18n</goal>
<goal>resources</goal>
<goal>generateAsync</goal>
</goals>
</execution>
</executions>
<configuration>
<runTarget>C3gwGui.html</runTarget>
<hostedWebapp>${webappDirectory}</hostedWebapp>
<i18nMessagesBundle>c3gw.fwk.gui.client.Messages</i18nMessagesBundle>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
<configuration>
<webappDirectory>${webappDirectory}</webappDirectory>
</configuration>
</plugin>
This is a snippet of my C3gwGui.gwt.xml:
<replace-with class="c3gw.fwk.gui.client.ClientFactoryImpl">
<when-type-is class="c3gw.fwk.gui.client.ClientFactory" />
</replace-with>
This is a snippet of the line where the error is thrown:
public void onModuleLoad() {
ClientFactory clientFactory = GWT.create(ClientFactory.class);
...
}
ClientFactory is an interface and ClientFactoryImpl implements the interface.
What I've figured out so far: The code works perfectly fine in Eclipse when I run debug, it just doesn't work when I do mvn install. I've run all the goals available for gwt-maven-plugin (clean, compile, sources, etc...) and they all work so the only conclusion I can have at this point is that something is happening during the maven-war-plugin phase or much later.
I also took the basics of this code from the following google tutorial and they use an interface so it should work, assuming that the example project also works that is.
Removing war:exploded, as Thomas indicated, solved the issue.

Export Scala application to runnable JAR

Can you tell me, if this is possible, how to export a Scala application to a normal runnable JAR that can run directly in the JVM ?
Thanks
It is perfectly possible, see for instance this: running a maven scala project. Since Scala compiles to Java bytecode, JVM is not even aware of the underlying implementation language.
In essence after compiling Scala sources using scalac you will get a bunch of .class files which you can later package into a JAR. Then you can simply run them using:
$ java -cp "your.jar:scala-library.jar" com.example.Main
Note that you must include scala-library.jar on the CLASSPATH (currently it is almost 9 MiB...) and specify class containing main method.
If you use sbt to build you can use one of the one-jar plugins. They will put all dependencys into one big jar file (inclusive all the scala.jar files). This means that you only need one jar file and don't have to manage all the dependencys.
As an example with sbt-assembly (mostly copied from https://github.com/sbt/sbt-assembly):
project/plugins.sbt:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "X.X.X")
build.sbt:
import AssemblyKeys._ // put this at the top of the file
seq(assemblySettings: _*)
then you can generate the jar with:
sbt assembly
As an alternative to Fabian's answer, if you're using Maven, you can use the assembly-plugin. Something like:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>package-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifestEntries>
<SplashScreen-Image>splash.png</SplashScreen-Image>
</manifestEntries>
<manifest>
<mainClass>se.aptly.epm.main.PrognosisApp</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
That will package all your deps up, including scala-library.jar (if it's in your deps), but will do so flattened with all classes unpacked. This is because runnable jar's cannot out of the box use code in jars in the jar.
To make that work (which is nicer), use http://code.google.com/p/onejar-maven-plugin/, I think it's a Maven mojo wrapper to one-jar: http://one-jar.sourceforge.net/
There is also an sbt-plugin for one-jar:
https://github.com/sbt/sbt-onejar
In order to package a swing application in a runnable jar, the solution that worked for me was to export my project as a normal jar file (non executable) and update the jar's manifest to:
add scala-library.jar scala-swing.jar packages to the path
indicate the main class
You can find the Manifest file inside the jar (that you can open with 7z for example) at the following path:
META-INF/MANIFEST.MF
Add the following lines at the end of the manifest:
Main-Class: myPackage.myMainClass
Class-Path: scala-library.jar scala-swing.jar
Now your jar should execute properly when clicking on it.
NOTE: You can find more information about manifest customizing here:
http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html.
Hers is my solution, maven -->create scala runnable jar.
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
<executions>
<execution>
<id>scala-compile-first</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<includes>
<include>**/*.scala</include>
</includes>
</configuration>
</execution>
<execution>
<id>scala-test-compile</id>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>xxx.xxx.xxx.Main</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>reference.conf</resource>
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>