How do you create a single runnable jar that contains all the files it needs to run? This is one of those questions that should be easier to answer. Here’s how to do it in eclipse and NetBeans.
First, eclipse, following the post here:
1. Create a Java class to run your Scala main:
package scala.loader;
import java.util.*;
public class ScalaEntryPoint
{
public static void main(String[] args) {
List<string> argList = new ArrayList<string>();
argList.add("YourScalaObjectWithMain");
for (String s : args) argList.add(s);
scala.tools.nsc.MainGenericRunner.main(argList.toArray(new String[0]));
}
}
Be sure to change YourScalaObjectWithMain to your class. Also, you’ll have to add the Scala tools jar to your projects classpath: Project | Properties | Java Build Path tab | Libraries tab | Add External Jars… button. Then pick the scala.tools.nsc file in your eclipse/plugins folder.
2. Create a Run Configuration to run the Java class. Check that it runs.
3. Then choose File | Export…, then Java | Runnable JAR File, then pick the Java run configuration to export and a destination. Optionally, you can save the ant XML file that does the export. Later, after some edits, you can rejar using
ant -f yourjarXMLfile.xml
If you change your libraries, be sure to repeat the complete Export process to make sure your jar scrips includes the correct jars.
Tags: eclipse, runnable jar
Thanks for posting this Garry. This ended a long and agonising trial as to how to deploy my Scala app.
Ooops … sorry about the erroneous extra “r” in “Gary”. A little quick on the trigger finger.
Thanks for taking the time to post this. I’m just looking into Scala. I’m having trouble with your example in Eclipse:
The java file fails to run in Eclipse with error:
no such file: vg.os.ScalaMain
If I jar it up it fails to run with:
chris@vostro:~$ java -jar scalatest.jar
Exception in thread “main” java.lang.NoClassDefFoundError: scala/ScalaObject
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
at vg.os.Main.main(Main.java:15)
Caused by: java.lang.ClassNotFoundException: scala.ScalaObject
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
… 14 more
Any idea what silly mistake I’m making?
Thanks,
Chris.
Main.java:
package vg.os;
import java.util.ArrayList;
import scala.tools.nsc.MainGenericRunner;
public class Main {
public static void main (String[] args) {
ArrayList argList = new ArrayList();
argList.add(”vg.os.ScalaMain”);
for (String s : args) {
argList.add(s);
}
MainGenericRunner.main(argList.toArray(new String[0]));
}
}
ScalaMain.scala:
package vg.os
object ScalaMain {
def main(args : Array[String]) : Unit = {
println(”hello world from ScalaMain”)
}
}
Worked fine on scala 2.7.7, but now, after installing scala-ide, scala 2.8.0, I cannot find the appropriate scala.tools.nsc referred to above in ScalaEntryPoint.
After reading a bit more about the new scala-ide () I realized that it is now even easier, since you can now call your scala main method directly from the java main method.
package scala.loader;
public class ScalaEntryPoint {
public static void main(String[] args) {
sourceHandling.Compiler.main(args);
}
}
The editor does complain about the syntax, but it builds fine.
You then have to add scala-library.jar to the project as an “external JAR” before export.