Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preview compiler features in a mixed Java/Scala Project #727

Closed
aghasemi opened this issue Oct 17, 2023 · 12 comments
Closed

Preview compiler features in a mixed Java/Scala Project #727

aghasemi opened this issue Oct 17, 2023 · 12 comments

Comments

@aghasemi
Copy link

aghasemi commented Oct 17, 2023

Hi,

I have a project with both Java and Scala sources, and I want to use a preview feature of Java 21 (String templates) in the Java code. However, building the project with mvn compile results in:

 error: StringTemplate is a preview API and is disabled by default.
import static java.lang.StringTemplate.STR;
                       ^
  (use --enable-preview to enable preview APIs)

I have set --enable-preview in the maven compiler plugin, but the maven scala compiler does not have such a feature, does it? Is there anything I can do to have my Java code compiled, or preview features are unusable intentionally? By the way, Java 21 works fine with the plugin otherwise, and other new features of Java 21 such as pattern matching and virtual threads work as intended.

Many thanks

@slandelle
Copy link
Collaborator

@aghasemi
Copy link
Author

aghasemi commented Oct 17, 2023

Many many thanks. That solved the issue I mentioned, but there is still one issue:

When I actually use Java 21's String templates, e.g. by running System.out.println(STR."=\{2+2}");, I get the following error at the beginning of the compile step

invalid escape character

, which makes sense from the point of view of previous Java versions, but not Java 21. Moreover, java.lang.StringTemplate.STR is correctly imported and I can freely use it as long I don't have \{ in my String which of course defeats the purpose of templates. Is there any solution for this one?

@slandelle
Copy link
Collaborator

Please provide a reproducer as described here: https://stackoverflow.com/help/minimal-reproducible-example.

@aghasemi
Copy link
Author

aghasemi commented Oct 17, 2023

pom.xml:

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>io.aghasemi</groupId>
  <artifactId>mvntest</artifactId>
  <version>1.0-SNAPSHOT</version>
 
  <properties>
    <maven.compiler.source>21</maven.compiler.source>
    <maven.compiler.target>21</maven.compiler.target>
    <encoding>UTF-8</encoding>
    <scala.version>2.13.12</scala.version>
    <scala.compat.version>2.13</scala.compat.version>
  </properties>

  <dependencies>
    

    <!-- https://mvnrepository.com/artifact/org.scalatest/scalatest -->
    <dependency>
      <groupId>org.scalatest</groupId>
      <artifactId>scalatest_${scala.compat.version}</artifactId>
      <version>3.2.17</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.scalatestplus/junit-4-13 -->
    <dependency>
      <groupId>org.scalatestplus</groupId>
      <artifactId>junit-4-13_${scala.compat.version}</artifactId>
      <version>3.2.17.0</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.1</version>
      <scope>test</scope>
    </dependency>


  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>net.alchim31.maven</groupId>
        <artifactId>scala-maven-plugin</artifactId>
        <version>4.8.1</version>
        <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>
        <configuration>
          <javacArgs>--enable-preview</javacArgs>
          <jvmArgs>
            <jvmArg>--enable-preview</jvmArg>
          </jvmArgs>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>

        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.11.0</version>
        <executions>
          <execution>
            <phase>compile</phase>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>
          <enablePreview>true</enablePreview>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.21.0</version>
        <configuration>
          <!-- Tests will be run with scalatest-maven-plugin instead -->
          <skipTests>true</skipTests>
          <argLine>--enable-preview</argLine>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.scalatest</groupId>
        <artifactId>scalatest-maven-plugin</artifactId>
        <version>2.0.0</version>
        <configuration>
          <reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory>
          <junitxml>.</junitxml>
          <filereports>TestSuiteReport.txt</filereports>
          <!-- Comma separated list of JUnit test class names to execute -->
          <jUnitClasses>io.aghasemi.Tests</jUnitClasses>
          <argLine>
            --enable-preview
          </argLine>
        </configuration>
        <executions>
          <execution>
            <id>test</id>
            <goals>
              <goal>test</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.6.0</version>

        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>

        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>

      </plugin>
    </plugins>
  </build>
</project>

and then io.aghasmi.Tests.java:

package io.aghasemi;

import static java.lang.StringTemplate.STR;

public class Tests {

    public static void main(String[] args) {
         System.out.println(STR."=\{2+2}");

        return;
    }
}

Temurin JDk 21 and Maven 3.9.4.

@slandelle
Copy link
Collaborator

Could you please:

  • trim down your pom.xml to what's really necessary
  • push a maven project in a repo on GitHub

@aghasemi
Copy link
Author

Could you please:

  • trim down your pom.xml to what's really necessary
  • push a maven project in a repo on GitHub

Here it is: https://github.com/aghasemi/mavan-scala-java21-test

Thanks

@slandelle
Copy link
Collaborator

I have the exact same error with sbt.
It seems the Scala compiler doesn't support String templates yet (and I expect supporting an experimental Java feature to be very low priority).

Nothing we can do on our side. scala-maven-plugin will support automatically it once scalac supports it.

@aghasemi
Copy link
Author

aghasemi commented Oct 20, 2023

I see. Thanks. Quite a bit of a shame since the Scala compiler is actually OK with the preview features, except for this extension to escape characters it seems. Would not happen if \ was not chosen to use in templated strings :)

@slandelle
Copy link
Collaborator

2 different things: being able to pass the javac option to enable features in preview and specifically being able to parse this new Java code. Might be related to the version of asm currently shipped.

Anyway, nothing we can do here. I recommend that you open an issue directly against Scala.

@aghasemi
Copy link
Author

Thanks. I will. Just out of curiosity, why should the Scala compiler parse a Java source file?

@slandelle
Copy link
Collaborator

So it can figure out the types and methods in Java code and compile the Scala code that might import them.

But it just parses Java sources, it doesn't compile them in bytecode, javac is used for that.
That's why you only need a JRE to compile Scala code, but you need a full JDK to compile mixed projects with Java code.

@aghasemi
Copy link
Author

Of course! Many thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants