Update on the state of Java modularization
Tags: java, jpms, modularization, jigsaw
Published: 2020-10-25 16:40:42

At the beginning of 2019, I wrote about [the state of Java modularization](https://blog.frankel.ch/hard-look-state-java-modularization/). I took a sample of widespread libraries and for each of them, I checked whether:

1. It supports the module system _i.e._ it provides an automatic module name in the manifest
2. It's a full-fledged module _i.e._ it provides a <code>module-info</code>

The results were interesting. 14 out of those 29 libraries supported the module system, while 2 were modules in their own right.

Nearly 2 years later, and with Java 16 looming around the corner, it's time to update the report. I kept the same libraries, and added Hazelcast and Hazelcast Jet. I've checked the latest version.

<table>
  <thead>
    <tr>
     <th></th>
     <th colspan=3>Jan. 2019</th>
     <th colspan=3>Oct. 2020</th>
    </tr>
    <tr>
      <th>Name</th>
      <th>Analyzed version</th>
      <th>Module name</th>
      <th>Modularized?</th>
      <th>Analyzed version</th>
      <th>Module name</th>
      <th>Modularized?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><a href="https://www.slf4j.org/">SLF4J</a></td>
      <td>1.8.0-beta2</td>
      <td><code>org.slf4j</code></td>
      <td>&#10003;</td>
      <td>1.8.0-beta4</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://github.com/FasterXML/jackson/">Jackson</a></td>
      <td>2.11.8</td>
      <td><code>com.fasterxml.jackson.core</code></td>
      <td>&#10060;</td>
      <td>2.11.3</td>
      <td><code>com.fasterxml.jackson.core</code></td>
      <td>&#10003;</td>
    </tr>
    <tr>
      <td><a href="https://github.com/google/gson">GSon</a></td>
      <td>2.8.5</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>2.8.6</td>
      <td><code>com.google.gson</code></td>
      <td>&#10003;</td>
    </tr>
    <tr>
      <td><a href="https://junit.org/junit5/">JUnit</a></td>
      <td>5.3.2</td>
      <td><code>org.junit.jupiter.api</code></td>
      <td>&#10060;</td>
      <td>5.7.0</td>
      <td><code>org.junit.jupiter.api</code></td>
      <td>&#10003;</td>
    </tr>
    <tr>
      <td><a href="https://site.mockito.org/">Mockito</a></td>
      <td>2.23.4</td>
      <td><code>org.mockito</code></td>
      <td>&#10060;</td>
      <td>3.5.15</td>
      <td><code>org.mockito</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://github.com/powermock/powermock">PowerMock</a></td>
      <td>2.0.0-RC.4</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>2.0.7</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://commons.apache.org/proper/commons-lang/">Commons Lang</a></td>
      <td>3.8.1</td>
      <td><code>org.apache.commons.lang3</code></td>
      <td>&#10060;</td>
      <td>3.11</td>
      <td><code>org.apache.commons.lang3</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://commons.apache.org/proper/commons-math/">Commons Math</a>
      <td>3.6.1
      <td>&#10060;
      <td>&#10060;
      <td colspan="3">No new release
    </tr>
    <tr>
      <td><a href="https://github.com/google/guava">Guava</a></td>
      <td>27.0.1</td>
      <td><code>com.google.common</code></td>
      <td>&#10060;</td>
      <td>30.0-jre</td>
      <td><code>com.google.common</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://hc.apache.org/httpcomponents-client-ga/index.html">Http Client</a></td>
      <td>4.5.6</td>
      <td><code>org.apache.httpcomponents.httpclient</code></td>
      <td>&#10060;</td>
      <td>4.5.13</td>
      <td><code>org.apache.httpcomponents.httpclient</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://xerces.apache.org/xerces2-j/">Xerces 2</a></td>
      <td>2.12.0</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td colspan="3">No new release</td>
    </tr>
    <tr>
      <td><a href="https://x-stream.github.io/">XStream</a></td>
      <td>1.4.11.1</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>1.4.13</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://dom4j.github.io/">dom4j</a></td>
      <td>2.1.1</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>2.1.3</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td>JAXB</td>
      <td>2.3.1</td>
      <td><code>java.xml.bind</code></td>
      <td>&#10003;</td>
      <td colspan="3">No new release</td>
    </tr>
    <tr>
      <td><a href="https://poi.apache.org/">Apache POI</a></td>
      <td>4.0.1</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>4.1.2</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://commons.apache.org/proper/commons-pool/">Commons Pool</a></td>
      <td>2.6.0</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>2.9.0</td>
      <td><code>org.apache.commons.pool2</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://github.com/vladmihalcea/flexy-pool">Flexipool</a></td>
      <td>2.1.1</td>
      <td><code>com.vladmihalcea.flexypool.core</code></td>
      <td>&#10060;</td>
      <td>2.2.3</td>
      <td><code>com.vladmihalcea.flexypool.core</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://brettwooldridge.github.io/HikariCP/">HikariCP</a></td>
      <td>3.2.0</td>
      <td><code>com.zaxxer.hikari</code></td>
      <td>&#10060;</td>
      <td>3.4.5</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://commons.apache.org/proper/commons-dbcp/">Commons DBCP</a></td>
      <td>2.5.0</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>2.8.0</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td> <a href="https://itextpdf.com/">iText</a></td>
      <td>5.5.13</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>5.5.13.2</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://xmlgraphics.apache.org/fop/">FOP</a></td>
      <td>2.3</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>2.5</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="http://commons.apache.org/proper/commons-collections/">Commons Collections</a></td>
      <td>4.2</td>
      <td><code>org.apache.commons.collections4</code></td>
      <td>&#10060;</td>
      <td>4.4</td>
      <td><code>org.apache.commons.collections4</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://www.eclipse.org/collections/">Eclipse Collections</a></td>
      <td>9.2.0</td>
      <td><code>org.eclipse.collections.api</code></td>
      <td>&#10060;</td>
      <td>10.4.0</td>
      <td><code>org.eclipse.collections.api</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://bitbucket.org/trove4j/trove">Trove</a></td>
      <td>3.1.0</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td colspan="3"> No new release</td>
    </tr>
    <tr>
      <td><a href="https://commons.apache.org/proper/commons-email/">Commons Email</a></td>
      <td>1.5</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td colspan="3"> No new release</td>
    </tr>
    <tr>
      <td><a href="https://jsoup.org/">JSoup</a></td>
      <td>1.11.3</td>
      <td><code>org.jsoup</code></td>
      <td>&#10060;</td>
      <td>1.13.1</td>
      <td><code>org.jsoup</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://commons.apache.org/proper/commons-codec/">Commons Codec</a></td>
      <td>1.11</td>
      <td><code>org.apache.commons.codec</code></td>
      <td>&#10060;</td>
      <td>1.15</td>
      <td><code>org.apache.commons.codec</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://github.com/p6spy/p6spy">P6Spy</a></td>
      <td>3.8.1</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>3.9.1</td>
      <td><code>p6spy</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://developers.google.com/protocol-buffers/">ProtoBuf</a></td>
      <td>3.8.1</td>
      <td>&#10060;</td>
      <td>&#10060;</td>
      <td>3.13.0</td>
      <td><code>com.google.protobuf</code></td>
      <td>&#10060;</td>
      <td>
    </tr>
    <tr>
      <td><a href="https://hazelcast.org/">Hazelcast</a></td>
      <td colspan="3">First check</td>
      <td>4.0.1</td>
      <td><code>com.hazelcast.core</code></td>
      <td>&#10060;</td>
    </tr>
    <tr>
      <td><a href="https://jet-start.sh/">Hazelcast Jet</a></td>
      <td colspan="3">First check</td>
      <td>4.2</td>
      <td><code>com.hazelcast.jet</code></td>
      <td>&#10060;</td>
    </tr>
  </tbody>
</table>

## Analysis

Oracle released Java 9 in September 2017. Three full years after that release, 10 out of 31 libraries still don't provide a module-compatible JAR. Granted, 3 of them didn't release a new version in the meantime. That's still 7 libraries that didn't add a simple line of text in their <code>MANIFEST.MF</code>.

On the good side, Jackson, GSon, and Junit migrated to the module system. This is not a trivial effort and deserves some praise.

On the other side, SLF4J migrated back from the module system to an automatic module name. That's an issue. If developers decide to use the module system and declare the dependencies of their app, they cannot upgrade libraries that follow this practice. I don't know what to make out of it.

I checked the new v2 version (still in alpha), and it even has no <code>Automatic-Module-Name</code>.

## Conclusion

Before writing this post, I assumed the penetration of  <abbr title="Java Platform Module System">JPMS</abbr>  in the ecosystem was close to none. I'm pleasantly surprised. However, while there's progress, it's slow. And modularizing your application if you have non-modularized dependencies is [not trivial](https://blogs.oracle.com/javamagazine/containerizing-apps-with-jlink#anchor_7).

**To go further:**

* [A hard look at the state of Java modularization](https://blog.frankel.ch/hard-look-state-java-modularization/)
* [Explicitly Naming Automatic Java Modules](http://marxsoftware.blogspot.com/2019/01/explicitly-naming-automatic-java-modules.html)
* [Migrating the ServiceLoader to the Java 9 module system](https://blog.frankel.ch/migrating-serviceloader-java-9-module-system/)
* [Migrating a Spring Boot application to Java 9 - part 1](https://blog.frankel.ch/migrating-to-java-9/1/)
* [Migrating a Spring Boot application to Java 9 - part 2](https://blog.frankel.ch/migrating-to-java-9/2/)
* [Containerizing Apps with jlink](https://blogs.oracle.com/javamagazine/containerizing-apps-with-jlink)
* [ModiTect - Tooling for the Java Module System](https://github.com/moditect/moditect)

_Originally published at [A Java Geek](https://blog.frankel.ch/update-state-java-modularization/) on October 25<sup>th</sup>, 2020_