12

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

Radu Stoenescu
  • 3,187
  • 9
  • 28
  • 45

5 Answers5

15

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.

Community
  • 1
  • 1
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
15

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
Fabian
  • 1,224
  • 1
  • 11
  • 26
7

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

Viktor Hedefalk
  • 3,572
  • 3
  • 33
  • 48
1

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:

  1. add scala-library.jar scala-swing.jar packages to the path
  2. 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.

Antoine
  • 11
  • 1
0

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>
HHH
  • 311
  • 2
  • 7