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`.

Reply via email to