This article is a follow-up of Hexagonal Architecture with Gradle in which I gave an example of a what a hexagonal architecture would look like with Gradle and Java8. We'll now focus more on the upcoming JDK.

Java9 is around the corner and should arrive on Sept 21, 2017. One of its main features is Project Jigsaw. It is also the most awaited feature since it was proposed for Java7! Project Jigsaw aims to bring modularization to Java. The reason it took so long is that the JDK had to be itself modularized.

This is great news as modularization is at the root of Hexagonal Architecture. It wouldn't be possible without it. Only it is a special type of modularizing as every module except the domain module itself imports the domain module.

The structure of the example is the same as in the previous article and the source code can be found on branch java9 on GitHub.

Gradle migration to Java9

In order to compile for Java9, I followed Gradle's guide to building Java9 modules. To make it even simpler, using the recommended (but experimental) jigsaw plugin worked too.

Modules

Existing modules remained the same. Jigsaw requires that in order to make named modules, there should be a filename module-info.java at the root of a module. Here is the one for the module facebook-connector.

module org.detoeuf.hexagonal.facebook {
    exports org.detoeuf.hexagonal.facebook;
    requires org.detoeuf.hexagonal.domain;
    provides org.detoeuf.hexagonal.domain.SocialMedia
            with org.detoeuf.hexagonal.facebook.FacebookConnector;
}

The first line gives the name of the module. Convention requires that it is in reverse DNS order, just like packages. The second line export the package which coincidentally has the same name so that it is exposed. The third line states that in order for this module to be compiled, module org.detoeuf.hexagonal.domain needs to be visible. And finally, the fourth line is there to register FacebookConnector as an implementation of SocialMedia

This is no surprise as Gradle's dependencies were already aligned this way.

Services

Java 9 builds on ServiceLoader. Services implemented or used should be declared in module-info.java.

Modules which need to use a service should declare it with the uses keyword.

module org.detoeuf.hexagonal.domain {
    exports org.detoeuf.hexagonal.domain;
    uses org.detoeuf.hexagonal.domain.Persistence;
    uses org.detoeuf.hexagonal.domain.SocialMedia;
}

Whereas modules which publish service implementation should do so with the provides keyword.

module org.detoeuf.hexagonal.facebook {
    exports org.detoeuf.hexagonal.facebook;
    requires org.detoeuf.hexagonal.domain;
    provides org.detoeuf.hexagonal.domain.SocialMedia
            with org.detoeuf.hexagonal.facebook.FacebookConnector;
}

Automatic modules

Java 9 does its best to convert regular jars into modules. In order to do so, the module name is derived from the jar name. Basically, ".jar" extension is removed as well as the version number. Remaining non-alpha-numeric characters are replaced by dots.

Ratpack

That works well, but the jar has to obey certain rules to become an automatic module. One of these rules is that the same package cannot be read from two different modules. This is called a split package. This is an effort to make package architecture cleaner, but many existing dependencies do not comply with this rule. Ratpack, which was the web server used in the previous example had this kind of problem. There are ways to go around the split package problem, but since this application has a hexagonal architecture, it very simple to change the web server implementation.

Vert.x

Looking around, I found that Vert.x seems very modular and lean enough for my needs. I didn't want a framework like Spring Framework as it would be too intrusive in this hexagonal architecture example and it would pull out many more dependencies, of which all could cause modularity problems. It turns out, Vert.x had another problem making it incompatible with the Java 9 module system. vertx-web has a META-INF/services directory. This directory is used by vertx-web to add Groovy Extension Modules. Java 9 Service Loader mechanism also scans files in this directory looking for potential services. It causes an error at runtime, which is described on Stack Overflow.

Spark

Next web server in line was Spark Framework. This time, launching the app worked as it didn't suffer from the two previous problems.

Even though two libraries didn't play nice with Java 9, this shows the benefit of hexagonal architecture as migrating from one to the other was simple. Of course, this example is simple, but only a small part of the application had to be modified in order to do so, leaving the rest untouched and free from regressions.

Conclusion

Moving to Java 9 was simplified with Gradle. When doing so, one has to be careful to check if dependencies are compatible with the module system. A step towards migration would probably be to use the unnamed module, which contains all classes on the classpath. This should be a temporary approach as even though classpath and module path are not mutually exclusive, dealing with both requires more caution.

Hexagonal Architecture fits in very well with Java 9's module system. These are two designs in clean architecture that complement each other.