Is there any need to switch to modules when migrating to Java 9 or later?
Asked Answered
P

2

107

We're currently migrating from Java 8 to Java 11. However, upgrading our services was less painful, than we anticipated. We basically only had to change the version number in our build.gradle file and the services were happily up and running. We upgraded libraries as well as (micro) services that use those libs. No problems until now.

Is there any need to actually switch to modules? This would generate needless costs IMHO. Any suggestion or further reading material is appreciated.

To clarify, are there any consequences if Java 9+ code is used without introducing modules? E.g. can it become incompatible with other code?

Pashm answered 17/7, 2020 at 9:1 Comment(5)
It's the same risk you already faced in Java 8: ending up in "Classpath Hell".Viticulture
The sotms/#summary would answer to an extent. You can check, if your project goals are aligned to the project Jigsaw. Apart from that, in my opinion, its a matter of being up to date as well that matters for libraries/services providing support to its consumers.Latanya
@Taschi I don't think classpath hell alone justifies going modular, as all code prior to Java 9 had that issue and in most case we've been fine with it (personally never had a problem with it).Pashm
@Latanya bringing up the goals of project jigsaw is indeed a very good argument.Pashm
@Younes El Ouarti, removing "Classpath Hell" is one of the two stated goals of Project Jigsaw. If you think that it is not a sufficient reason for dealing with Jigsaw, well... I agree with you, and I avoid Jigsaw whenever I can.Viticulture
P
179

No.

There is no need to switch to modules.

There has never been a need to switch to modules.

Java 9 and later releases support traditional JAR files on the traditional class path, via the concept of the unnamed module, and will likely do so until the heat death of the universe.

Whether to start using modules is entirely up to you.

If you maintain a large legacy project that isn’t changing very much, then it’s probably not worth the effort.

If you work on a large project that’s grown difficult to maintain over the years then the clarity and discipline that modularization brings could be beneficial, but it could also be a lot of work, so think carefully before you begin.

If you’re starting a new project then I highly recommend starting with modules if you can. Many popular libraries have, by now, been upgraded to be modules, so there’s a good chance that all of the dependencies that you need are already available in modular form.

If you maintain a library then I strongly recommend that you upgrade it to be a module if you haven’t done so already, and if all of your library’s dependencies have been converted.

All this isn’t to say that you won’t encounter a few stumbling blocks when moving past Java 8. Those that you do encounter will, however, likely have nothing to do with modules per se. The most common migration problems that we’ve heard about since we released Java 9 in 2017 have to do with changes to the syntax of the version string and to the removal or encapsulation of internal APIs (e.g., sun.misc.Base64Decoder) for which public, supported replacements have been available for years.

Pruter answered 17/7, 2020 at 17:28 Comment(0)
M
40

I can only tell you my organization opinion on the matter. We are in the process of moving to modules, for every single project that we are working on. What we are building is basically micro-services + some client libraries. For micro-services the transition to modules is somehow a lower priority: the code there is already somehow isolated in the docker container, so "adding" modules in there does not seem (to us) very important. This work is being picked up slowly, but it's low priority.

On the other hand, client libraries is an entirely different story. I can not tell you the mess we have sometimes. I'll explain one point that I hated before jigsaw. You expose an interface to clients, for everyone to use. Automatically that interface is public - exposed to the world. Usually, what I do, is have then some package-private classes, that are not exposed to the clients, that use that interface. I don't want clients to use that, it is internal. Sounds good? Wrong.

The first problem is that when those package-private classes grow, and you want more classes, the only way to keep everything hidden is to create classes in the same package:

  package abc:
        -- /* non-public */ Usage.java
        -- /* non-public */ HelperUsage.java
        -- /* non-public */ FactoryUsage.java
        ....

When it grows (in our cases it does), those packages are way too big. Moving to a separate package you say? Sure, but then that HelperUsage and FactoryUsage will be public and we tried to avoid that from the beginning.

Problem number two: any user/caller of our clients can create the same package name and extend those hidden classes. It happened a few times to us already, fun times.

modules solves this problem in a beautiful way : public is not really public anymore; I can have friend access via exports to directive. This makes our code lifecycle and management much easier. And we get away from classpath hell. Of course maven/gradle handle that for us, mainly, but when there is a problem, the pain will be very real. There could be many other examples, too.

That said, transition is (still) not easy. First of all, everyone on the team needs to be aligned; second there are hurdles. The biggest two I still see is: how do you separate each module, based on what, specifically? I don't have a definite answer, yet. The second is split-packages, oh the beautiful "same class is exported by different modules". If this happens with your libraries, there are ways to mitigate; but if these are external libraries... not that easy.

If you depend on jarA and jarB (separate modules), but they both export abc.def.Util, you are in for a surprise. There are ways to solve this, though. Somehow painful, but solvable.

Overall, since we migrated to modules (and still do), our code has become much cleaner. And if your company is "code-first" company, this matters. On the other hand, I have been involved in companies were this was seen as "too expensive", "no real benefit" by senior architects.

Mona answered 17/7, 2020 at 14:10 Comment(4)
Thanks for the incites! So what I'm getting is, that the modularization comes with the much need access restrictions we've been missing in previous versions. I can definitely see how this is useful for libraries. In case a service is communicated with via REST/AMQP/etc. this is again not so much of an issue, or rather, there are no benefits? Maybe we can't arbitrarily say that all java 9+ code should be modular? So we should regard it as a "tool" itself? Interesting nevertheless.Pashm
What you could find useful is an "accessor" API pattern (but please note that instead of a public static field, a private one with methods is preferred, to avoid deadlocks during class loading). See here: wiki.netbeans.org/…Hautesavoie
Thank you for sharing your experience! It would be good if you would share more details or links to the problems you mentioned that re painful, but still solvable.Listen
“Problem number two: any user/caller of our clients can create the same package name and extend those hidden classes.” Long before Java 9, packages could be sealed to prevent this. (I happen to think modules are an excellent idea and I use them in all my projects. I just wanted to point out that this particular use case doesn’t require them.)Flawy

© 2022 - 2024 — McMap. All rights reserved.