JavaOne – Project Jigsaw – Integration with Tools

“Project Jigsaw – Integration with Tools”

Speaker: Alexandru Jecan (author of Java 9 Modularity Revealed)

For more blog posts from JavaOne, see the table of contents


What expect build tools and IDEs to do

  • Code completion (IDEs only)
  • Make things easier
  • Work with class path and module path

Maven

  • Only Maven 3+ supports Java 9.
  • No changes to Maven core to run on Java 9
  • presence of module-info.java decides if Maven uses module path
  • Need Maven compiler plugin 3.6.1 to compile Java 9 code
  • Discourages using automatic module name
  • GAV not related to module name. Continue to use GAV.
  • Use module name in module-info.java – double work
  • Maven does not generate “requires” clauses for module-info.java
  • Can add <compilerArgs> options for -add-modules or -add-exports
  • New tag <release> which takes precedence over source/target tags. Recomended compiling twice or backward compatbility. once for java 9 modules and once for java 8. [why? isn’t that what multi release ars are for?]
  • maven-exec-plugin – can configure module path
  • taked abut updating maven toolchain file [not clear how this differs than prior versions of java]
  • maven-jdeps-plugin – can automatically generate module descriptor [but said earlier couldn’t]
  • maven-jmod-plugin – new plugin; not yet released. Creates and lists content of jmod files. Merge native code into jar
  • maven-jlink-plugin – new plugin; not yet released. Creates runtime images
  • maven-depdendency-plugin – said lists GAV [not clear how changed

Gradle
No first class support for Java 9 yet. Coming soon. [but said using; puzled?]

Ant
Ant 1.9.8+ support JDK 9 modules for java/javac/junit. [yet Ant doesn’t support JUnit 5]

Loom

  • New build tool for Java 9
  • Uses YAML config. Uses Maaven repo.
  • Supports JUnit 5,

loom.builders

Moditect
Maven plugin that generates module-info.java based on dependencies. Says helps a little but doesn’t do all the work. [how?]

SonarJava
SonarJava 4.11+ recognizes module keywords

Graphviz
Open source visualization software
Reads jdeps input to generate graphical representation of Jigsaw. As can IDES

IDEs

  • NetBeans, Eclipse and IntelliJ all understand modules clauses [if you count pre-release versions]
  • Also offer autocompletion, syntax higlighting, etc
  • NetBeans 9 – not yet released; must build yourself. Showed editing module path, visual of module dependencies, jshell, jlink
  • Eclipse Oxygen with Java 9 support – came out 9/27/17. Ten second demo
  • IntelliJ 2017.1+ – Mark directory as source root so directory name matches module name. Errors on common module errors, Showed module editing, module dependencies and other features

Open source readiness

How to modularize your app

  • Introduce modue-info.java by creating manually or running jdeps to generate
  • Problems: using JDK internal APIs (ignore warning or fix), using odule not availalbe such as xml bindings (add-modules at compile and runtime), cyclic dependencies (can have at runtime but not compile time), split packages (Oracle plans to make change in later version of Java to deal with this)
  • [Note: He recommended renaming packags as a solution to spit packages. That sounds like a horrible idea unless you can guarantee only you call that code]

    My take before session: You know how they say that first impressions matter? The speaker is wearing a suit. 90% of the people in the room are wearing jeans. Two people in the room are wearing a suit The speaker and someone he knows. Then he showed the table of contents. There are 29 points in 45 minutes in the outline. Preparing to have my head spin!

    My take after session: He is in fact technical. The suit was misleading! The pace was way too fast though; drinking from a fire hose. Not enough time to understand/process many of the points. He talks fast (as do I), but key is to *pause* if you talk fast so people can catch up. Also the side transitions were distracting. A cube transition is cute. But if you are reading when it moves, it is disorienting. And due to the speed, there was a good chance of being reading when transitions started. This was good information, but should have been two sessions so split up and a decent pace. And omiting how to migrate your libraries; that’s a talk on its own There is a Maven BOF tonight; maybe folks can discuss more then!

    One minute after the official end time, he asked if there were questions. My head was spinning with questions. [I didn’t even have time to process which was most important]. Another attendee asked if having JUnit tests in a parallel directory with the same package name is a split package. The speaker said yes and went on to say to wait for Java 10 or rename. I interjected at that point. Unless you are distributing a test jar, I don’t think this is a problem. In fact, most IDEs compile both the /src/main/java and /test/main/java directories to the same folder. I stated this and asked the speaker if he agreed. He said yes.

preparing to run junit 5 with eclipse and maven

I’ve been playing with JUnit 5 for a while. Since I’m going to be speaking about it at JavaOne, I decided to write all my tests using JUnit 5 between now and then. Plus we are getting close to JUnit 5’s official release; it’s pretty stable now.

Since it is more than just playing, I wanted my IDE to support it. And my Maven POM needed to know about both JUnit 4 and 5. It wasn’t hard.

Note if you are using IntellIJ, it works out of the box so you just have to set up Maven.

Update Eclipse

I also decided to update my Eclipse so I could run JUnit 5 tests in the workspace.  I had to let Eclipse update 3 other plugins to be compatible with the latest version. It was easy to do though and I didn’t need to re-install my custom plugins. In September (or so), Eclipse will release with JUnit 5 support in it.

Update Maven POM

Then I updated my pom to use the dependencies in the JUnit 5 Maven sample. I also added failsafe support and junit-jupiter-params dependency (for parameterized tests which I use a lot)

<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>GROUP_ID_GOES_HERE</groupId>
  <artifactId>ARTIFACT_ID_GOES_HERE</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <properties>
    <java.version>1.8</java.version>
    <surefire.version>2.19.1</surefire.version>
    <junit.version>4.12</junit.version>
    <junit.jupiter.version>5.0.0-RC2</junit.jupiter.version>
    <junit.vintage.version>${junit.version}.0-RC2</junit.vintage.version>
    <junit.platform.version>1.0.0-RC2</junit.platform.version>
  </properties>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>${surefire.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-surefire-provider</artifactId>
            <version>${junit.platform.version}</version>
          </dependency>
        </dependencies>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.0</version>
        <configuration>
          <source>${java.version}</source>
          <target>${java.version}</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${surefire.version}</version>
        <configuration>
          <includes>
            <include>**/Test*.java</include>
            <include>**/*Test.java</include>
            <include>**/*Tests.java</include>
            <include>**/*TestCase.java</include>
          </includes>
          <properties>
            <!-- <includeTags>fast</includeTags> -->
            <excludeTags>slow</excludeTags>
          </properties>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-surefire-provider</artifactId>
            <version>${junit.platform.version}</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
  <dependencies>
     <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter-api</artifactId>
       <version>${junit.jupiter.version}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter-params</artifactId>
       <version>${junit.jupiter.version}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>${junit.version}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.junit.platform</groupId>
       <artifactId>junit-platform-launcher</artifactId>
       <version>${junit.platform.version}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter-engine</artifactId>
       <version>${junit.jupiter.version}</version>
       <!-- docs don't have this as test scope; trying anyway to see what happens -->
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.junit.vintage</groupId>
       <artifactId>junit-vintage-engine</artifactId>
       <version>${junit.vintage.version}</version>
       <!-- docs don't have this as test scope; trying anyway to see what happens -->
       <scope>test</scope>
     </dependency>
     <!-- other dependencies my project needs like selenium go here -->
  </dependencies>
</project>

Problems I encountered (with solutions)

  1. Maven doesn’t run failsafe tests – Originally I didn’t have failsafe version 2.19.1 because I had copied the pom from the junit sample. And the JUnit sample didn’t have any integration tests so no reason to include failsafe.
  2. Eclipse doesn’t recognize migrated JUnit 5 tests – If you’ve ever run JUnit 4 tests against that project/test, Eclipse has a stored configure with the test runner set to JUnit 4. You can go to “run configurations” and either delete the existing configuration or change the runner to JUnit 5 for that configuration. I choose the later:

Remember that with this configuration, you are merely prepared to have JUnit 5 tests in your project. Since JUnit 5 is (mostly) backward compatible, the tests still work as is.

 

github two factor and eclipse

I was talking to a coworker recently about using Eclipse with Git. I had done this back in 2010, but it has been a while. I use git at the command line. He also said Eclipse Oxygen support for Git is better than in the past. Could be. To be honest, I don’t remember doing this in 2010 other than the command line being far easier.

Anyway, I decided to try again. The UI was intuitive. I went to commit. The git staging view (confirmation dialog) showed up at the bottom where the console is rather than popping up like SVN does, but that’s minor. It gave me a choice of “commit and push” which is nice as it isn’t a two step operation.

Then I hit a problem. I turned on GitHub two factor authentication back in 2014. Which means my user id/password isn’t accepted through Eclipse. Luckily this is easy to get past:

  1. Go to github and choose settings (from the upper right pulldown under your avatar)
  2. Click the very last link which is Personal Access Tokens
  3. Choose “Create new token”
  4. Enter a description. I choose “Mac Eclipse”
  5. Choose which permissions you want to grant. I chose the Repo checkbox.

Then I tried to commit and push using my git username and the generated token string as the password. Success. (I didn’t pull because nobody else use this repo)

Note: I got an error “git-receive-pack not permitted” when I didn’t choose the Repo checkbox. In Eclipse, it showed my change as committed (which it was), but it wasn’t pushed.