Probably the most painful thing for software developers is to be restricted in technology choice which they want to use in a development. You pay for a conference ticket, listen about new cool frameworks, development approaches or tools… Then you return to office with huge enthusiasm and desire to try at least something on real project. Unfortunately such initiative very frequently meets resistance from different sides: team members don’t want to learn something new, a manager thinks it is risky, a product owner hurries with a next release, etc.

Well, if to be honest I described this situation too dramatic. Of course nobody will punish you for proposal to integrate something new in a project. Another question is how to do it right?

Today I want to discuss an interesting topic – how to use Scala in Java project? This case will be interesting for those developers who want to try Scala in real scenarios. Doesn’t matter what type of app you have: Spring or Spark or something else. I’m going to demonstrate how to integrate Scala to Maven project.

Let’s start!

Abstract Java Maven project

Let’s assume you are working on some Java project. Also Maven is used as project management tool. Such project always looks like this:

maven-java-project-structure

As you see, project structure is pretty simple. It has standard layout and only three Java classes. Let’s consider them:

package com.app.model;

public class Book {

    private String name = null;
    private String author = null;

    public Book(String name, String author) {
        this.name = name;
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book {" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                '}';
    }

    //getters & setters
}

Then so-called data store 😀

package com.app.storage;

import com.app.model.Book;
import java.util.ArrayList;

public class BookStorage {

    private ArrayList<Book> books = new ArrayList<Book>();

    public BookStorage() {
        books.add(new Book("White Fang", "Jack London"));
        books.add(new Book("The Sea-Wolf", "Jack London"));
        books.add(new Book("The Road", "Jack London"));
        books.add(new Book("The Adventures of Tom Sawyer", "Mark Twain"));
        books.add(new Book("Around the World in 80 Days", "Jules Verne"));
        books.add(new Book("Twenty Thousand Leagues Under the Sea", "Jules Verne"));
        books.add(new Book("The Mysterious Island", "Jules Verne"));
        books.add(new Book("The Four Million", "O. Henry"));
        books.add(new Book("The Last Leaf", "O. Henry"));
    }

    public ArrayList<Book> getBooks() {
        return books;
    }
}

And finally Runner:

import com.app.model.Book;
import com.app.storage.BookStorage;

public class Runner {

    public static void main(String[] args) {
        BookStorage storage = new BookStorage();
        storage.getBooks().stream().forEach((Book b) -> System.out.println(b));
    }

}

Don’t forget that we have pom.xml file. Definitely it may contain some dependencies, plugins and build goals. This is actually not very important.

Mixing Scala into Java Maven project

In order to make Scala available inside of Java Maven project we need to use a Maven plugin. Yes, you understood correctly! There is only one required step. So let’s customize pom.xml file:

...
<!-- Make Scala available in project. Pay extra attention to the version -->
<dependencies>
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>2.11.7</version>
    </dependency>
</dependencies>

<build>
    <plugins>
<!-- This plugin compiles Scala files -->
        <plugin>
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>scala-compile-first</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>add-source</goal>
                        <goal>compile</goal>
                    </goals>
                </execution>
                <execution>
                    <id>scala-test-compile</id>
                    <phase>process-test-resources</phase>
                    <goals>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
<!-- This plugin compiles Java files -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
<!-- This plugin adds all dependencies to JAR file during 'package' command.
Pay EXTRA attention to the 'mainClass' tag. 
You have to set name of class with entry point to program ('main' method) -->
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.5.3</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifest>
                        <mainClass>ScalaRunner</mainClass>
                    </manifest>
                </archive>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        
    </plugins>
</build>
...

After this update you need to wait when Maven will download all this stuff and validate it. This is possible if you set auto-update for Maven, otherwise you have to force it manually.

Now we can use Scala in the project. For this purpose you need to create two new folders ‘src/main/scala‘ and ‘src/test/scala‘. Scala Maven plugin looks at this directories and compiles Scala files in them.

Let’s add some Scala code in the project:

package com.app.service

import java.util
import scala.collection.JavaConversions._

import com.app.model.Book

object BooksProcessor {

  def filterByAuthor(author: String)(implicit books: util.ArrayList[Book]) = {
    books.filter(book => book.getAuthor == author)
  }

}

After this I want to create an alternative entry point to the program:

import com.app.service.BooksProcessor
import com.app.storage.BookStorage

object ScalaRunner extends App {

  implicit val books = (new BookStorage()).getBooks
  BooksProcessor.filterByAuthor("Jack London").foreach(b => println(b))

}

Here is how project looks after the adding of Scala files:

java-maven-scala-project

Try to run this code from IDE. It works as expected 🙂

Package Scala-Maven project in JAR

What if you want to package this project in JAR file and then run it somewhere? For this you need run mvn package command or use its analogy in IDE. This action produces two jars in the ‘target‘ folder. You need to work with that one which has ‘*-jar-with-dependencies.jar‘ in its name.

scala-maven-project-run-from-command-line

On the screenshot above I highlighted two options to run the JAR. In the first one you may specify which on class you want to run. In the second one we run the JAR and it run default class specified in the pom.xml ScalaRunner.

By the way, you can generate executable JAR by using maven-assembly-plugin and its ‘single‘ goal.

Summary

Integration of Scala in Java project is pretty straightforward. As you see it can be done in 10 minutes. Of course it make sense only if you are already know at least Scala basics and know that with help of it you can develop a project more efficiently or rewrite an existing functionality. Everything depends on you 🙂

About The Author

Mathematician, programmer, wrestler, last action hero... Java / Scala architect, trainer, entrepreneur, author of this blog

Close