Skip to content

Usage Guide

Effi Ban edited this page Oct 12, 2024 · 21 revisions

Preparation

As explained in Limitations, the tool cannot always generate Java code which compiles and/or is 100% logically correct.
However you can improve the quality of the output by doing some modifications to the Scala code in advance.
Here are some suggestions:

Removing advanced Scala features

Since some advanced Scala features cannot be handled by the tool, you can remove all usages of them in advance.
There are many of these and it can be time-consuming. I recommend to focus on:

  • implicit-s
  • self-types
  • import-s inside classes and code blocks
  • Named parameters and method arguments

Desugaring

Scala has so-called "syntactic sugar" which allows one to write more concise code while omitting certain keywords and language elements, which are mandatory in Java. Although the tool is able to handle some of them, in other cases it has to "guess" and might fail to correctly determine the missing elements.
You can help it by "de-sugaring" the syntax into the more verbose and complete syntax.
Examples of this:

  • Explcitly specify variable and method types
  • Add missing return keywords
  • Add empty parentheses to method invocations with no arguments
  • Add explicit new keyword to case-class instantiations
  • Add explicit apply method invocations

NOTE: If you work in IntelliJ, the Scala plugin has support for automatic desugaring by right-clicking in the editor (or Ctrl+Alt+D). However, be careful with this - there are lots of configurable options, and sometimes the code produced is not so readable and would actually make things more difficult for the tool. You may want to try an iterative approach where you run the tool several times and use the desugaring to help fix its mistakes.

Adding JOOL and VAVR dependencies

Scala has more extensive support for functional programming than Java, and some of the relevant types and methods cannot be easily translated into Java. In order to avoid extra complexity, Scala2Java will translate some of these into the equivalents from the JOOL (Jooq Lambda) and VAVR frameworks.
If your project doesn't already have these dependencies, you must add them before running the tool.

Some of the types that Scala2Java will translate into are:

  • From JOOL:
    • Tuple
    • Function#
  • From VAVR:
    • Either
    • Try

Running the tool

Scala2Java is published to Maven Central at these coordinates (also given in the README):
Group: io.github.effiban
Artifact: scala2java-core_2.13

The tool receives one or more Scala source files and translates them one by one to Java.
The output can either be printed to the console or save to a given directory.
In the second case, each Scala file will be translated into a corresponding file with the same name and a .java suffix

There are currently two options for running the tool: With a CLI and as an SDK. In the future, I plan to add an IntelliJ plugin as well.

Important: The tool must be executed with the runtime classpath of your project. This will allow the tool to accurately determine imports and perform translations of terms and types from Scala to Java.

Option 1 - CLI

  1. Download the executable jar - which is the one with the -all suffix
  2. To generate output to the console run the following command:
    java -cp scala2java-core_2.13-<version>-all.jar:<project_classpath> io.github.effiban.scala2java.core.Scala2JavaRunner MyClass1.scala MyClass2.scala
  3. To generate output to a directory:
    java -cp scala2java-core_2.13-<version>-all.jar:<project_classpath> io.github.effiban.scala2java.core.Scala2JavaRunner --outDir=myDir MyClass.scala MyClass2.scala

Option 2 - SDK (currently supports only one file at a time)

  1. Add the scala2java-core dependency to your project

  2. To generate output to the console (Scala example)

    import io.github.effiban.scala2java.Scala2JavaTranslator.translate
    import java.nio.file.Path
    
    class Translator {
        def doTranslate(): Unit = {
            val scalaPath = Path.of("myRootDir", "mypackage", "MyClass.scala")
            translate(scalaPath)
        }
    }
  3. To generate output to a directory (Scala example)

    import io.github.effiban.scala2java.Scala2JavaTranslator.translate
    import java.nio.file.Path
    
    class Translator {
        def doTranslate(): Unit = {
            val scalaPath = Path.of("myScalaRoot", "mypackage", "MyClass.scala")
            val javaOutputDir = Path.of("myJavaRoot", "mypackage")
            translate(scalaPath, Some(javaOuptutDir))
        }
    }
Clone this wiki locally