views:

114

answers:

1

I'm tryign to export my project as a jar with IntelliJ 9.0. My project compiles and runs with no problem in Intellij, but when I write it to a .jar and open it, it will show an error.

My Main class is something like:

package Main

//Imports

object Main{
  def main(args: Array[String]) {
    println("Main: Hello, world!")
    //do stuff
}

Now, in the artifacts window I created a .jar with the following:

  1. Main Clas: Main.Main
  2. Class Path: lib/javacsv lib/scala-compiler.jar lib/scala-library.jar lib/scalatest-1.0-test.jar lib/scalatest-1.0.jar lib/tools.jar lib/jtds-1.2.2.jar lib/flex-messaging-common.jar lib/flex-messaging-core.jar lib/spring.jar lib/mysql-connector-java-5.1.7-bin.jar lib/ojdbc14.jar lib/commons-logging.jar lib/postgresql-8.4-701.jdbc3.jar lib/log4j-1.2.15.jar lib/poi-3.6-20091214.jar lib/poi-ooxml-3.6-20091214.jar lib/dom4j-1.6.1.jar lib/poi-ooxml-schemas-3.6-20091214.jar lib/geronimo-stax-api_1.0_spec-1.0.jar lib/xmlbeans-2.3.0.jar lib/rt.jar lib/ifxjdbc.jar lib/db2jcc4.jar

I have double checked that all those classes are on the project and are the onnly classes on it. Notice that it inlcudes lib/scala-compiler.jar and lib/scala-library.jar.

Build the project: java -jar myScalaApp.jar and I get:

Exception in thread "main" java.lang.NoClassDefFoundError: scala/ScalaObject
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
    at java.net.URLClassLoader.access$000(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 java.lang.ClassLoader.loadClass(ClassLoader.java:316)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:288)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:374)
    at Main.Main.main(Main.scala)
Caused by: java.lang.ClassNotFoundException: scala.ScalaObject
    at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:316)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:288)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:374)
    ... 13 more

I understand that it's not finding the scala classes but I made sure they are there. What else can be the problem and how could I fix it?

+4  A: 

I'd say one of two things has gone wrong:

  • scala-library.jar is not in your jar; or
  • the class path at runtime doesn't include scala-library.jar.

I don't know how IntelliJ builds your jar: Does it unpack all your library jars and mung them together with your code into one big jar, or does it add the library jars as-is to your big jar and manipulate the classpath to get at the jars-within-jar?

The first point is easy enough to check: Either use jar -tvf yourJar.jar to list out the contents of your jar, or use an archive viewer to look into it graphically. Note that a .jar is basically a .zip, so you can rename the extension and then use a tool that can look into .zip files.

Just had an idea about the second part: Can you build a simple Java main class that prints out System.getProperty("java.class.path") ? A Java class should be able to run in that jar even if a Scala class isn't.

Carl Smotricz
When IntelliJ builds a Jar it just adds jars inside the jar.That's a nice trick. I tried your idea and it returns the jar file. That is, it prints 'myScalaApp.jar'. Does that mean that he is not reding the manifest to get the jar's inside?
Skuge
Exactly, there's the problem: Those classes are *not* in yourScalaApp.jar, i.e. they are not directly inside its directory structure. Your classpath needs to contain references to each and every "inside" jar, and I'm not sure of the syntax for that, or if there is one. I've had good success with exploding all of the component jars and re-packing everything into one jar, but unless you have a tool (or an ant task) to do this, it's work.
Carl Smotricz
And yes, it looks like the manifest is not being respected. Since I'm only being of marginal help, I suggest you try asking this question again without referring to Scala. Lots of people can probably answer this question in a pure Java context.
Carl Smotricz
Ok, Thanks anyway it was very helpful.
Skuge