26

I have a mixed Scala/Java project that doesn't compile well.

The problem arises when Java code is trying to call Scala code in the same package.

Of course, I have the standard layout:

  • src/main/java
  • src/main/scala
  • src/test/java
  • src/test/scala

I've looked at other similar Stackoverflow questions but this question is a little outdated. This other question doesn't help either.

I have also followed the scala-maven-plugin documentation page.

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <version>3.1.6</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <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>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

I have tried unsuccessfully to follow this blog post.

IDEA project with Scala plugin imported from the pom.xml can compile and run my project successfully.

What is the right way of doing it? Does the Java code gets compiled twice? First by the Scala plugin and the by the Java plugin?.

Community
  • 1
  • 1
david.perez
  • 6,090
  • 4
  • 34
  • 57

4 Answers4

19

Here is a working example of pom.xml :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
     http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>stackoverflow</groupId>
<artifactId>q24448582</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
    <scala.version>2.10.3</scala.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>${scala.version}</version>
    </dependency>

</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.scala-tools</groupId>
            <artifactId>maven-scala-plugin</artifactId>
            <version>2.15.2</version>
            <executions>

                <execution>
                    <id>compile</id>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <phase>compile</phase>
                </execution>
                <execution>
                    <id>test-compile</id>
                    <goals>
                        <goal>testCompile</goal>
                    </goals>
                    <phase>test-compile</phase>
                </execution>
                <execution>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

</project>
maksim07
  • 390
  • 2
  • 8
  • 1
    Interesting your solution. The maven-compiler-plugin isn't used. It's the first template I've seen that doesn't use it. – david.perez Jun 27 '14 at 10:04
  • 1
    You're using maven-scala-plugin version 2.15.2, and the current one is 3.1.6. It looks like a little outdated. – david.perez Jun 27 '14 at 10:05
  • 1
    Yes, it seems that scala-maven-plugin is a new version of maven-scala-plugin. Anyway I checked the pom and it works fine with the new version. – maksim07 Jun 27 '14 at 10:20
  • 1
    This worked for me, although I updated the versions to the latest one here: ;https://github.com/danyaljj/sampleMixedScalaJavaMavenProject – Daniel Aug 25 '15 at 01:32
  • Works like a charm. Thanks. – Pushkin Dec 27 '18 at 06:53
  • maven-scala-plugin compiles both java and sala, but maven-compiler-plugin compiles only java, that's why you can use only maven-scala-plugin but not the other way – Ahmed Gamal Feb 09 '21 at 09:26
13

Problem 1

At first I thought the problem was due to using a modern version of the maven-compiler-plugin. I was using version 3.0 instead of 2.0.2.

The solution has been: - Remove the maven-compiler-plugin - Add this setting: incremental

Finally my pom.xml is this:

<plugin>
    <groupId>net.alchim31.maven</groupId>
    <artifactId>scala-maven-plugin</artifactId>
    <version>3.1.6</version>
    <configuration>
        <recompileMode>incremental</recompileMode>
        <args>
            <arg>-deprecation</arg>
            <arg>-explaintypes</arg>
            <arg>-target:jvm-1.7</arg>
        </args>
    </configuration>
    <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>add-source</goal>
                <goal>testCompile</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Problem 2

Another problem I was experiencing is this:

<dependencies>
    <dependency>
        <groupId>org.json4s</groupId>
        <artifactId>json4s-native_${scala.version}</artifactId>
        <version>3.2.9</version>
    </dependency>
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>${scala.version}.4</version>
    </dependency>
</dependencies>

<properties>
    <scala.version>2.10</scala.version>
</properties>

This make this solved problem arise: https://issues.scala-lang.org/browse/SI-5733

Probably it was using an old version of the Scala compiler.

The solution has been to rename scala.version to scala.major, as this property has a special meaning.

david.perez
  • 6,090
  • 4
  • 34
  • 57
  • Why is add-source needed when we are not specifying any source path ? Doesn't scala-maven-plugin pick up default path without add-source ? – Zxcv Mnb Nov 14 '16 at 12:16
8

In order to get the scala-maven-plugin to respect Java 1.8, but still allow mixed compilation of java and scala, we use this:

...
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.5</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
    </configuration>
    <executions>
        <execution>
            <id>default-compile</id>
            <phase>none</phase>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>net.alchim31.maven</groupId>
    <artifactId>scala-maven-plugin</artifactId>
    <version>3.2.2</version>
    <configuration>
        <recompileMode>incremental</recompileMode>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
                <goal>testCompile</goal>
            </goals>
        </execution>
    </executions>
</plugin>
...
drsquidop
  • 428
  • 4
  • 12
  • why you have the phase=none for maven-compiler ? – Keith Aug 05 '17 at 09:43
  • 1
    I disable the default java compiler phase and let the scala compiler compile both scala and java. This way you can have class interdependencies between languages. – drsquidop Sep 08 '17 at 06:12
0

I add blow code at pom.xml file <build> block and working good!

    <build>
        <finalName>${project.artifactId}</finalName>

        <plugins>
            <!-- SCALA AND JAVA MIX COMPILATION -->
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>scala-compile</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </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>
                <version>2.4.2</version>
                <configuration>
                    <artifactSet>
                        <includes>
                            <include>*:*</include>
                        </includes>
                    </artifactSet>

                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*.SF</exclude>
                                <exclude>META-INF/*.DSA</exclude>
                                <exclude>META-INF/*.RSA</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>

                        <configuration>
                            <finalName>${project.artifactId}-shaded-${project.version}</finalName>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>

        <pluginManagement>
            ...
        </pluginManagement>

        <resources>
            ...
        </resources>
    </build>
Colin Wang
  • 771
  • 8
  • 14