Running Scala Maven Project - scala

I am a scala beginner, and was running a starter project on Maven and using IntelliJ as IDE.
This is the link to project on github which I am using Github project and I compiled the project against OpenJDK8.
The HelloJava class runs successfully, however, when I try running the HelloScala class I come across the following error:
java -cp scala-maven-example-1.0.0-SNAPSHOT.jar com.jesperdj.example.HelloScala
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: scala/Function0
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: scala.Function0
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more

Scala has its own runtime libraries above JVM. A compiled Scala .class has imported some classes from Scala runtime libraries. When you try to run a Scala .class file, you need to append the Scala runtime to the classpath.
If you are running inside IntelliJ IDEA, the Scala Plugin will automatically do this, but when you run java from command line, you should do this yourself.
If you are using Maven, then you can add a <plugin>. From Scala Docs -> Scala with Maven -> Creating a Jar:
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.your-package.MainClass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
After adding this, mvn package will also create [artifactId]-[version]-jar-with-dependencies.jar under target. Note: this will also copy the Scala library into your Jar. This is normal. Be careful that your dependencies use the same version of Scala, or you will quickly end up with a massive Jar.

To run your programs on Intellij you need to install scala sdk along with JDK.
Once you have scala SDK in your Intellij classpath you are good to go with scala coding.

Tick the checkbox 'include dependencies with "Provided" scope' under: 'Run\Debug Configurations'.
(Helps if yours is a maven project and you added the 'scala-library' dependency scope as 'Provided')
'Run\Debug Configurations'

Related

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

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

Creating Windows Executable for OpenJFX 11 Project in Eclipse with Maven Integration

I'm switching over from Java 8 (Oracle JDK) to OpenJDK 11 and OpenJFX 11. I've successfully gotten my project to work in Eclipse through Maven via the clean javafx:run command using the maven-compiler-plugin however I am having issues building a runnable jar and windows executable. I do not need a linux or mac runnable as this project is just an internal product and we only use windows.
I have already tried several plugins such as the maven-shade-plugin and also tried running mvm package to no avail. I've tried this Build executable JAR with JavaFX11 from maven and this How to deploy a JavaFX 11 Desktop application with a JRE.
In the past I could just build a executable jar through Eclipse's "Export Runnable Jar" option and then creating an executable through launch4j, however this does not seem to work anymore and I understand this probably due to the modular structure of OpenJDk 9+.
I have all the JavaFX dependencies added as well as the JAXB ones that I needed and it runs in the IDE when I build it (although I can't get it to run as a Java Application Run Configuration once I made it run in Maven Run Configuration.
Here are my plugins:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.3</version>
<configuration>
<mainClass>com.tapestry.testertools.ApplicationMainFrame</mainClass>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.tapestry.testertools.ApplicationMainFrame</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Here is the error message when i attempt to run mvn clean package
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.325 s
[INFO] Finished at: 2019-09-20T09:19:35-07:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project testertools: Fatal error compiling: invalid flag: --module-path -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[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 read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

Exclude Maven Dependency during Eclipse Application Runtime

When I try to run a Java Application on Eclipse, a conflict between two dependencies is causing the application to fail.
I am trying to upgrade my project Java version from OracleJDK 8 to OpenJDK 11. As a result, I also had to also needed to update a GWT dependency from 2.6.0 to 2.8.2, as well as switch from MOJO gwt-maven-plugin to the tboyer version as well. Additionally, the build is done on Maven 4.0.0 on Eclipse IDE 4.9.0.
Snippet of the pom.xml
<properties>
<gwt.version>2.8.2</gwt.version>
...
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt</artifactId>
<version>${gwt.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<scope>provided</scope>
</dependency>
...
<build>
<plugins>
<plugin>
<groupId>net.ltgt.gwt.maven</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>1.0-rc-10</version>
<executions>
<execution>
<id>compile-common</id>
<goals>
<goal>compile</goal>
<goal>test</goal>
</goals>
<configuration>
<moduleName>XXXXModule</moduleName>
</configuration>
</execution>
<execution>
<id>XXXX</id>
<goals>
<goal>compile</goal>
<goal>test</goal>
</goals>
<configuration>
<moduleName>XXXXModule</moduleName>
</configuration>
</execution>
<execution>
<id>XXXX</id>
<goals>
<goal>compile</goal>
<goal>test</goal>
</goals>
<configuration>
<moduleName>XXXXModule</moduleName>
</configuration>
</execution>
<execution>
<id>XXXX</id>
<goals>
<goal>compile</goal>
<goal>test</goal>
</goals>
<configuration>
<moduleName>XXXXModule</moduleName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
So when I run the application on Eclipse, I get the following error:
SEVERE: Application encountered an exception during Start.
XXXX.ApplicationException: Failed to reflect on start method.
at XXXX.ApplicationLauncher.startApplication(ApplicationLauncher.java:471)
at XXXX.ApplicationLauncher.doRun(ApplicationLauncher.java:185)
at XXXX.ApplicationLauncher.main(ApplicationLauncher.java:67)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at XXXX.ApplicationLauncher.startApplication(ApplicationLauncher.java:469)
... 2 more
Caused by: java.lang.NoSuchMethodError: org.apache.tomcat.util.ExceptionUtils.preload()V
at org.apache.catalina.startup.Tomcat.<init>(Tomcat.java:181)
....
After investigating, I discovered that two of my dependencies tomcat-embed-core-7.0.91 & apache-jsp-8.0.9.M3 both contain ExceptionUtils with several difference, hence the Exception. Furthermore, the apache-jsp is being pulled by the gwt-dev dependency which is only required during the Maven build to run the gwt-maven-plugin.
gwt-dev:2.8.2
apache-jsp:9.2.14.v20151106
apache-jsp:8.0.9.M3
But for some reason, Eclipse is including gwt-dev and it's dependency as part of the runtime path even though I have the 'provided' scope tag in the pom.xml.
I have tried excluding the apache-jsp dependency, but a compile issue occurs because apparently gwt-dev is still being added which depends on apache-jsp.
Summary
The TBroyer GWT-Maven-Plugin requires the pom file to include gwt-dev as a dependency in order to run correctly during a build.
However, when running the application on Eclipse, a NoSuchMethodException occurs on org.apache.tomcat.util.ExceptionUtils.preload()V
The issue is there are two ExceptionUtil classes with same package from different jars and methods.
One of the jars is apache-jsp which is a dependency of gwt-dev. Gwt-dev and it's dependencies should not be part of the runtime classpath.
Question: Is there a way to ensure the gwt-dev is only used during the Maven build and not part of the Eclipse Java Application runtime classpath?
Yes, you can ensure isolated classpath for client and server sides. You need to apply the multimodule layout. This is also the main difference between the old MOJO gwt maven plugin and the new generation tbroyer gwt maven plugin, the new one support multimodule correctly. Check this archetype as a reference for the multimodule layout. Also, use the packaging:gwt-app to configure the gwt maven plugin executions automatically.
Making it work with eclipse run action (tomcat or gwt) is a bit more difficult. Until you correctly apply the tbroyer gwt maven plugin and the multimodule layout, you will be able to use mvn tomcat7:run and mvn gwt:codeserver in the terminal. Then, the recommended strategy to use it in your IDE is to configure this maven goal and run it using the maven tooling of your IDE. This makes it work exactly the same in all your environments (terminal, CI, eclipse, intellij, etc).

maven .ClassNotFoundException how to make the jar executable

I am new with Maven and I have the following problem. I have a project A which I have added as dependency in another project.
This is what I have added to my pom
</build>
<dependencies>
<dependency>
<groupId>the id</groupId>
<artifactId>artifact id</artifactId>
<version> the version</version>
<scope>compile</scope>
</dependency>
In Eclipse everything is working, but when I try to open the jar file I get this message:
Caused by: java.lang.ClassNotFoundException: the name of project A
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 3 more
So what am I missing ?
Any suggestions would be helpful
When you want to run your application as:
java -jar yourapp.jar
you have take care of two things:
Make sure you have your main class listed in MANIFEST.MF, which I belive you did already.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>your.package.YourMainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Make sure that when you run you application your classpath is properly built. There are couple of ways to do that, but the easiest way would be to use the shade plugin. It will unpack all your dependencies and put them into one jar.
<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>
</execution>
</executions>
</plugin>
If you need the other solution without using the shade plugin, just let me know.
Eclipse does its own compilations automatically in the background. The result is that your dependency's jar file is probably available in Eclipse but not in your local maven repository. Try running "maven clean install" in the terminal on your local dependency first (this will add it to your local maven repository), then afterwards build your downstream project with another "maven clean install".
This will create a jar file in the "target" directory at the root of your maven project.

Error running Maven Project in Eclipse using jdk1.5

OS: Ubuntu 12.10
Eclipse: 4.2
Java: jdk1.5.0_22 and jdk1.7
Apache Maven: 3.0.4
Maven home: /usr/share/maven
m2e: 1.2.020120903-1050
I have created a very simple "Hello, World" Maven Project in Eclipse, in order to test it to migrate our own project (which uses 1.5). My pom.xml is as follows:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>br.com.contmatic</groupId>
<artifactId>maven-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>MavenTest</name>
<description>teste do maven</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
I have set J2SE-1.5 (jdk1.5.22) in my project build path.
Yet, trying to run Maven Clean or Maven Install from within Eclipse, I get the following error:
Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version number in .class file
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClassFromSelf(ClassRealm.java:386)
at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:42)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:244)
at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:230)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
at org.apache.maven.cli.MavenCli.container(MavenCli.java:375)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:191)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:592)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
Googling around, I found out that this happens when the jre version used to compile is different than the one used to run. Changing everything to 1.7 (both pom.xml and build path) fixes the errors, which suggest that it either compiles or runs using java 1.7.
But I can't seem to find the error in my configuration.
when running
mvn clean install
in the terminal, maven builds the project without errors.
What could I be doing wrong in Eclipse?
Turns out some of my Maven dependencies weren't compiled with 1.5, which caused the problem. It wasn't happening in the console because I had already set java 1.7 as default.
Fortunately, I was able to build my project using 1.7 and specifying 1.5 to run compile and execute. Here's how:
in Eclipse>Run>Run Configurations>Maven Build>New, I had this configuration:
Main Tab
Base Directory:
${project_loc}
Goals:
clean install
I just chose the JRE tab and chose and Alternate JRE, using my 1.7 SDK installation.
Next, I had to include 1.5 as source and target for the maven-compiler-plugin my pom.xml, as such:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<encoding>ISO-8859-1</encoding>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
And it works.