Code One - Day One

This year I’m returning to Oracle Code One (formerly JavaOne) for the third time. I’m planning to write some notes on interesting sessions or other content.

Keynote

The keynote, starting at 10, was a bunch of short contributions from various speakers. Topics included a book on learning how to code, quantum computing, the new Java release cycle and the announcement of Java 13.

During a contribution by Brian Goetz and Mikael Vidstedt on Java 13, an interesting feature was mentioned named Class Data Sharing. It’s not new in Java 13 - it’s been there since Java 10, but it has been further improved in Java 13. CDS uses a build time tool to create something that looks like a shared library. The JVM uses that file at startup to put it into memory more efficiently than it would do with regular class files. A more thorough description is at the CodeFX blog.

Current garbage collection algorithms (G1 and Shenandoah) are capable of returning unused memory back to the operating system. This is particularly interesting when you pay for your infrastructure as-you-go. The Z Garbage Collector (new in Java 11) couldn’t do this, but starting with Java 13 it can.

New Language Features

In Java 13, we can use Switch Expressions. Say goodbye to return or break statements inside a switch and the need for a default case:

static int numLetters(Day day) {
    return switch (day) {
        case MONDAY, FRIDAY, SUNDAY -> 6;
        case TUESDAY -> 7;
        case THURSDAY, SATURDAY -> 8;
        case WEDNESDAY -> 9;
    }
}

Also new in Java 13 are Text Blocks

String html = """
                <html>
                    <body>
                        <p>Hello, world</p>
                    </body>
                </html>
              """;

This means we can also say goodbye to "\n" and String concatenation.

Both Switch Expressions and Text Blocks are in Preview, meaning that you need to tell the compiler to enable these features using --release 13 --enable-preview.

Brian also mentioned something that isn’t in Java 13, but underway for a future release: Data Classes. It allows you to declare data carrying classes using a lot less code than you’re used to:

record Point (int x, int y) {
}

Inside such a class you can modify the constructor if you wish, for example:

record Range(int low, int high) {
  public Range {
    /* referring here to the implicit constructor parameters */
    if (low > high) {
      throw new IllegalArgumentException(String.format("(%d,%d)", low, high));
    }
  }
}

Of course, there are no promises on when exactly it will be delivered, but the guestimates say it’ll probably be next year…

Broken Build Tools and Bad Habits: The Maven Stories

Later this day I attended a talk by Robert Scholte, the chairman of the Maven project. He took inspiration from an episode of the Air Crash Investigation with an air crash which was probably caused by pilots following an older version of the manual “that was no longer valid”. The same can easily happen when using tools (e.g. for building software): we apply the same trick or technique over and over again because they have proven to work before. And we keep on doing that even when the tool has changed, or our environment has changed.

So what are common patterns why builds fail? Of course there’s differences in the developers environment: operating system, version of operating system, version of Java, and most importantly: local code changes that aren’t committed and pushed into version control. Second, there’s the Local Repository (~/.m2/repository) being broken. This can happen, for example, when concurrent builds use the same Local Repository which results in corrupt files residing in that file system location. Another common cause is checksum failures. Verification of those checksums is not enabled by default, but it might be in a future version of Maven.

Of course, a talk by Robert cannot be complete without mentioning mvn install and its undesired results. Maven 2 introduced the concept of a multi-module project It required to have all dependencies to be installed in the Local Repository, because it wasn’t aware of modules available in the reactor. That’s how people got the habit of running mvn install to make sure all modules would also exist in the Local Repository. Maven 3 is however aware of the Reactor when running a multi-module build, so no need to install the dependency modules first!

Another thing that can easily go wrong in a multi-module project is that you invoke the install or deploy goal, and after a few modules the build breaks. This is why the Maven Install Plugin introduces the installAtEnd option, and the Maven Deploy Plugin has a corresponding deployAtEnd option. These allow you to run all phases in all modules to make sure they work, and postpone installing or deploying the artifacts until Maven made sure all preceding steps have succeeded.

On the other hand, some bad behaviors also provide the option to improve upon your build experience. For example, very verbose logging in your tests slows down the build. Why instead not turn off logging at all, and save a few seconds in the build?

Maven CI Extension

Robert introduced the Maven CI Extension which (despite the name) has nothing to do with continuous integration. Instead, it detects that you run mvn clean install and if it wasn’t needed, it will start warning you. If you don’t change the habbit, it will eventually break your build and tell you to use mvn verify instead.