On Tue, Nov 7, 2023 at 5:04 AM Ralph Goers <ralph.go...@dslextreme.com> wrote:
> You know, I almost didn’t want to answer this email because after reading > the text it was quite obvious to me that the question you are really trying > to ask is: > “What more needs to be done to kill off 3.x?” That being said I will > still answer your question. > I am glad you took the effort to answer. We stand on the shoulders of your (and others') work. Your insight is invaluable. Thanks for taking time to share it. I am trying to improve the JPMS support in `2.x`. If there are things we can improve without breaking backward compatibility, I would like to know. I don't want to kill `3.x` – I support a new major release that rid us of the bloat. > First, I will say that the work to create module-info files in 2.x > wouldn’t have been possible without all the effort put in to figure out how > to separate the tests from the code. You have absolutely no idea how many > hours I put in trying various permutations and asking around. > I agree with the effort that you/others put into this. But that experience is incorporated into both `3.x` and `2.x` too. Hence, I don't think this counts as an argument. > Second, providing a module-info.class does not, in and of itself, make a > library JPMS compliant. That is a requirement for it to be a named module, > but it is only one facet of JPMS. > > Ask yourself, why was JPMS created? To allow Oracle to keep its JDK > developers busy? No. The JDK had become bloated and even a simple > HelloWorld app required the whole thing. Likewise, for a library like Log4j > to depend on anything besides java.base will force the application to be > bloated. > Consider this (decompiled by IntelliJ - I am not really sure why none of > them are listed as optional).: > > requires com.fasterxml.jackson.annotation; > requires com.fasterxml.jackson.core; > ... > requires org.osgi.core; > > With this: > // Required Dependencies > requires transitive org.apache.logging.log4j; > requires transitive org.apache.logging.log4j.plugins; > ... > requires static org.fusesource.jansi; > > And even this list for 3.x is larger than we would like. I believe it has > been identified how to eliminate all the java.* dependencies, but I would > be surprised if even more of the non-java dependencies can be extracted. > A lot of this was gained by splitting the modules in 3.x, which you > admitted cannot be done in 2.x. Since that is one of the primary benefits > of JPMS I am not sure how that makes 2.x better. > I am not able to follow you here. That is exactly what I said in my email: `3.x` has better modularization *and* we can do the same for `2.x`. As a matter of fact, we already had a tiny fake shot at it by moving `log4j-core` test JAR to `log4j-core-test`, which was a success. Exercising this "breaking down into more fine-grained modules" practice in `2.x` will not only improve the JPMS quality we deliver in `2.x`, but also immensely ease porting fixes between `2.x` and `3.x`, which is right now impossible without a full merge conflict. > Yes, we had to generate the module-info.java files by hand. Why? Because > tooling didn’t exist. If it does now great1 But I am not sure why you are > calling that out as if it is a negative thing. I mean, you still had to > create the list of dependencies in the pom.xml by hand. What really is the > difference? > Using `bnd-maven-plugin` to generate JPMS descriptors compared to writing `module-info.java` by hand has following advantages: 1. No `module-info.java` in the sources rendering IDEs unusable (I explained this in the first post.) 2. We tweak `b-m-p` in `pom.xml` for *only* optional dependencies, the plugin figures out the rest itself. Hence, in an ideal `3.x` where there are no optional dependencies, no `b-m-p` tweaking should be necessary. 3. Manually maintained `module-info.java` is prone to be broken when sources are moved between modules and classes. `b-m-p` captures this in `module-info.java` automatically. Next, there is a good chance that users really using JPMS won’t be able to > access any plugins outside of log4j-core. See > https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ClassLoader.html#getResource(java.lang.String). > This is precisely why 3.x uses ServiceLoader to locate all plugins. > > So, while you may have successfully create module-info.class files was > that a good thing? As an automatic module the rules in getResource() don’t > apply. > > Next, Java supports ModuleLayers. See > https://stackoverflow.com/questions/61195909/what-is-the-relation-between-modulelayer-and-classloader. > If you get nothing out of this other than “it is complicated” that is > enough. The bottom line here is again that you can’t rely on > ClassLoader.getResource() to find plugins. > > As you may or may not have noticed, annotation processors cannot be > located on the module path and must be strictly declared. In 2.x the > processor is always included inside log4j-core. In 3.x it is simpler as it > is its own module. Not necessarily a big deal but it provides better > encapsulation. > Agreed that the new plugin system in `3.x` establishes a stronger JPMS foundation. It is already compatible with the user code targeting `2.x` and that is why I also think we can (should?) port (a minimalistic version of?) it to `3.x` too. > So is 2.x really the “clear winner”? I don’t think so, at least as far as > JPMS is concerned. You haven’t even touched on the other benefits of 3.x . > JPMS in `2.x` works; in `3.x`, it doesn't. `3.x` has a better modularization and plugin system, both of which can be ported to `2.x` without breaking backward compatibility. > And the above hasn’t even touched on the other improvements in 3.x that > are listed at https://logging.apache.org/log4j/3.x/, which unfortunately > doesn’t call out the DI system Matt created (yet). > I am not able to follow what this has anything to do with the JPMS support in `2.x`.