Well, to be honest, I described this situation too dramatically. Of course, nobody will punish you for proposing 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 a 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 a 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 can see, the project structure is pretty simple. It has a 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, the 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 the pom.xml file. It might contain some dependencies, plugins ,and build goals. This is actually not very important.

Mixing Scala Into a Java Maven Project

In order to make Scala available inside of a Java Maven project, we need to use a Maven plugin. Yes, you understood correctly! There is only one required step. So let’s customize our 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 while Maven downloads all this stuff and validates it. This is possible if you set auto-update for Maven, but 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‘. The Scala Maven plugin looks at these directories and compiles Scala files within 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 the project looks after adding Scala files:

java-maven-scala-project

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

Package Scala-Maven Projects in a JAR

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

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

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

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

Summary

Integrating Scala in a Java project is pretty straightforward. As you see, it can be done in 10 minutes. Of course, it makes sense only if you already know at least the Scala basics and know that with some help, you can develop a project more efficiently or rewrite existing functionality. Everything depends on you.