Coming Up for Air

Compiling for Java 8 and Java 9

Saturday, April 15, 2017 |

In a project I’m working on for my book, I need to share classes between two applications. One, an Android project, requires Java 8. The other, a desktop JavaFX application, needs to run under Java 9, complete with module support. The problem with this is that the Maven tooling isn’t quite ready for Java 9, so it’s not as simple as I would like. I have, however, found a solution that seems to work.

In this setup, I have three projects: the shared module, the Android project, and the JavaFX project. The shared module looks roughly like this:

1
2
3
4
5
6
7
8
9
src
    main
        java
            module-info.java
            com
                steeplesoft
                    foo
                        model
                            Message.java

Our module is defined this way:

1
2
3
module foo.shared {
    exports com.steeplesoft.foo.model;
}

We want to compile everything so that the bytecode is usable via the Java 8 JVM, but module-info.java won’t compile for Java 8. Here, we apply some Maven magic:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.6.1</version>
            <executions>
                <execution>
                    <id>default-compile</id>
                    <configuration>
                        <excludes>
                            <exclude>**/module-info.java</exclude>
                        </excludes>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </execution>
                <execution>
                    <id>module-infos</id>
                    <phase>compile</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <configuration>
                        <excludes>
                            <exclude>**/*</exclude>
                        </excludes>
                        <includes>
                            <include>**/module-info.java</include>
                        </includes>
                        <source>1.9</source>
                        <target>1.9</target>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

We accomplish our goal by configuring the Maven compiler plugin with two different executions. In the first, we compile everything using a source and target of 1.8. For this pass, though, we exclude module-info.java. For the next pass, we compile with a source and target of 9. We also exclude everything so that our Java 8-compatible .class files aren’t overwritten, but we also explicitly include our module-info.java source file. Once this build runs, we’ll have mostly Java 8 .class files in our output directory, with a single Java 9-specific file, module-info.class. The normal Maven process than jars everything up and installs it in our local repository.

Over in our Android application, we can then declare the dependency on this jar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    repositories {
        jcenter()
        mavenCentral()
        mavenLocal()
    }
// ...

dependencies {
    compile 'com.steeplesoft:foo-shared:1.0-SNAPSHOT'
}

We can then import and use our model class, Message, and build and run our application.

On the Java 9 side, we declare a dependency on our module in the POM, and can configure our application’s Java module like this:

1
2
3
4
5
6
7
module foo.desktop {
    requires foo.shared;

    requires javafx.graphics;
    requires javafx.controls;
    requires javafx.fxml;
}

And we can successfully build and run our JavaFX application. Both Android and Java 9 are, as they say, fat, dumb and happy, and we have our shared code in a single project that can be used by both. It’s a bit more XML than we’d probably like, but, as Maven users, we’re probably used to that by now. :)

Search

    Quotes

    Sample quote

    Quote source

    About

    My name is Jason Lee. I am a software developer living in the middle of Oklahoma. I’ve been a professional developer since 1997, using a variety of languages, including Java, Javascript, PHP, Python, Delphi, and even a bit of C#. I currently work for Red Hat on the WildFly/EAP team, where, among other things, I maintain integrations for some MicroProfile specs, OpenTelemetry, Micrometer, Jakarta Faces, and Bean Validation. (Full resume here. LinkedIn profile)

    I am the president of the Oklahoma City JUG, and an occasional speaker at the JUG and a variety of technical conferences.

    On the personal side, I’m active in my church, and enjoy bass guitar, running, fishing, and a variety of martial arts. I’m also married to a beautiful woman, and have two boys, who, thankfully, look like their mother.

    My Links

    Publications