What is “<release>” element on “<configuration>” for the “maven-compiler-plugin” in a JavaFX app

旧城冷巷雨未停 提交于 2020-08-24 10:49:07

问题


I used the org.openjfx:javafx-archetype-simple Maven archetype to start my first JavaFX project.

The resulting POM:

<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>com.example.invoicing</groupId>
    <artifactId>Invoicer</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>14</maven.compiler.source>
        <maven.compiler.target>14</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>14</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <release>14</release>  🡄 ???
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.4</version>
                <configuration>
                    <mainClass>com.example.invoicing.App</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

➥ What is the purpose of the <release>14</release> line in <configuration> for the plugin <artifactId>maven-compiler-plugin</artifactId>?

I found this documentation for the Maven Compiler Plugin, Compiling Your Java Sources. But it only mentions <!-- put your configurations here -->. So I do not know anything about specific configuration options here.

Is <release>14</release> the version of Java being used to compile? Is it the version of OpenJFX? Something else?

I tried using 28 arbitrarily. Doing a Maven > install threw this error with an unhelpful error message with no clue as to a release of what product:

Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project Invoicer: Fatal error compiling


回答1:


The release flag is equivalent to specifying the source and target of the same value for the compiler plugin. It supports the -release argument for the Java compiler since Java-9.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <source>14</source>
        <target>14</target>
    </configuration>
</plugin>

Note: For the same reason, you can get rid of the redundant properties declared as

<maven.compiler.source>14</maven.compiler.source>
<maven.compiler.target>14</maven.compiler.target>

Further: What is the --release flag in the Java 9 compiler? | The -release flag in javac was introduced to Compile for Older Platform Versions.


To complete the answer over the part where you've tried the version value as 28. While using Maven version -

Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-05T00:30:29+05:30)

The error message reads very clearly what it should (if you could share the complete logs in the question)

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project forty-bits-of-java: 
Fatal error compiling: error: release version 28 not supported 



回答2:


The compile options page states that this ends up as the -release argument passed to javac.

And about --release release:

Compiles against the public, supported and documented API for a specific VM version. Supported release targets are 6, 7, 8, and 9.

As I understand it, Java 9 introduced a feature that helps developers build on a recent compiler, targeting an older runtime, but at the same time preventing the old problem that let code compile with references to newer APIs while being targeted at old runtimes.

See: JEP 247: Compile for Older Platform Versions

Ex: If you use Java 8 to compile code that uses new Java 8 APIs (such as Collection.stream()), with a target of 1.7, this code compiles but will fail at runtime on Java 7 with a NoSuchMethodError.

On JDK 9, if you use --release 1.7, the compiler will know that Collection.stream() can't be correctly targeted at Java 7 and will fail the build.




回答3:


tl;dr

In your POM, replace the two tags source & target as seen here:

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--The following `source` and  `target` tags are now replaced by `release` seen further down below.-->
        <!--<maven.compiler.source>14</maven.compiler.source>-->
        <!--<maven.compiler.target>14</maven.compiler.target>-->
    </properties>

…with the new release tag, placed further down in POM:

<build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
        <plugins>
            …

            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <!--Enable Java language preview features. Specify Java version.-->
                    <!--This `release` tag replaced the pair of `source` and  `target` tags seen commented-out near top of this POM.-->
                    <release>14</release>
                </configuration>
            </plugin>
…

…to tell the Java compiler the version of Java on which you intend to deploy. This tag passes a release flag to the Java compiler. The compiler errors out any of your code trying to use an API added to later versions of Java.

See another Question: What is the --release flag in the Java 9 compiler?

Details

Both Answers by Naman and by ernest_k are correct and important. But I need to write this Answer to combine them and show the direct solution.

Problem

The issue is that JEP 247: Compile for Older Platform Versions added a feature in Java 9 for a new compiler flag -release to replace the combination of older -source, -target, and -bootclasspath flags. This plugs a hole that plagued programmers trying to work on the latest compiler while writing code limited to making API calls of an earlier version of Java.

For example, I may be writing on my Mac using Java 12 yet deploying to a server running Java 8. I want the compiler to stop me from accidentally using features that arrived in later versions of Java. Otherwise, my app will succeed at compile-time yet fail at run-time when those features are unavailable on the older JVM.

To quote the JEP:

Summary

Enhance javac so that it can compile Java programs to run on selected older versions of the platform.

Motivation

javac provides two command line options, -source and -target, which can be used to select the version of the Java language accepted by the compiler and the version of the class files it produces, respectively. By default, however, javac compiles against the most-recent version of the platform APIs. The compiled program can therefore accidentally use APIs only available in the current version of the platform. Such programs cannot run on older versions of the platform, regardless of the values passed to the -source and -target options. This is a long-term usability pain point, since users expect that by using these options they'll get class files that can run on the the platform version specified by -target.

Solution

In a Maven-driven project, we pass those flags to the Java compiler by setting tags on our Maven POM file.

In your Maven POM file’s tag hierarchy of:

<project> …
    <build> …
        <pluginManagement> …
            <plugins> …
                <plugin> 
                    <artifactId>maven-compiler-plugin</artifactId>

…nest the following tag hierarchy, within which we specify our desired deployment version of Java.

<configuration> 
    <release>14</release>

By the way, if using a version of Java offering "preview" features, we can nest a further tag and value if we wish to enable those preview features.

<compilerArgs>--enable-preview</compilerArgs>

The old-school settings replaced by the new release tag were a pair of tags, source and target. These two could be set in Maven to be passed along to the Java compiler. So if you add the release tag seen above, check to see if your POM has this pair of tags. If found, delete them.

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>14</maven.compiler.source>  🡄 Delete if using `release` tag.
    <maven.compiler.target>14</maven.compiler.target>  🡄 Delete if using `release` tag.
</properties>

Example POM file

Here is a complete example POM file for Maven 3.6.3, for a basic Java project.

We are using all the latest versions of various plugins and dependencies. This example uses Java 15 with preview features such as Records enabled.

<?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>work.basil.demo</groupId>
    <artifactId>Demo5</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>Demo5</name>
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--The following `source` and  `target` tags are now replaced by `release` seen further down below.-->
        <!--<maven.compiler.source>15</maven.compiler.source>-->
        <!--<maven.compiler.target>15</maven.compiler.target>-->
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.7.0-M1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>

                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <!--Enable Java language preview features. Specify Java version.-->
                        <!--This `release` tag replaced the pair of `source` and  `target` tags seen commented-out near top of this POM.-->
                        <release>15</release>
                        <compilerArgs>
                            --enable-preview
                        </compilerArgs>
                    </configuration>
                </plugin>

                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.0.0-M4</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.2.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>3.0.0-M1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>3.0.0-M1</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.8.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

JavaFX

You mentioned JavaFX in your Question. Note that this discussion applies to any and all Maven-driven Java projects. This includes JavaFX projects as well as Jakarta Servlets, console apps, and so on. Nothing here is specific to JavaFX.



来源:https://stackoverflow.com/questions/60897480/what-is-release-element-on-configuration-for-the-maven-compiler-plugin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!