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.

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.

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 com.fasterxml.jackson.databind;
requires com.fasterxml.jackson.dataformat.xml;
requires com.fasterxml.jackson.dataformat.yaml;
requires com.lmax.disruptor;
requires disruptor;
requires java.activation;
requires java.base;
requires java.compiler;
requires java.desktop;
requires java.logging;
requires java.management;
requires java.naming;
requires java.rmi;
requires java.scripting;
requires java.sql;
requires java.xml;
requires javax.jms.api;
requires javax.mail.api;
requires jeromq;
requires kafka.clients;
requires org.apache.commons.compress;
requires org.apache.commons.csv;
requires org.apache.logging.log4j;
requires org.codehaus.stax2;
requires org.fusesource.jansi;
requires org.jctools.core;
requires org.osgi.core;


With this:
// Required Dependencies
requires transitive org.apache.logging.log4j;
requires transitive org.apache.logging.log4j.plugins;
// Optional Dependencies
requires static java.desktop;
requires static java.management;
requires static java.sql;
requires static java.rmi;
requires static java.xml;
requires static com.lmax.disruptor;
requires static org.jctools.core;
requires static org.osgi.framework;
requires static com.conversantmedia.disruptor;
requires static com.fasterxml.jackson.core;
requires static com.fasterxml.jackson.databind;
requires static com.fasterxml.jackson.dataformat.xml;
requires static com.fasterxml.jackson.dataformat.yaml;
requires static org.apache.commons.compress;
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.

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?

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.

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 .

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

Ralph





> On Nov 6, 2023, at 2:02 PM, Volkan Yazıcı <vol...@yazi.ci> wrote:
> 
> Could somebody help me to understand what we mean by JPMS support, please?
> Because I have the impression that people think `2.x` does not have JPMS
> support and `main` excels at it.
> 
> `2.21.0` brought `2.x` a fully-fledged JPMS support. JPMS and OSGi
> descriptors are auto-generated by `bnd-maven-plugin`. Piotr and I manually
> marked every single package that needs to be exported and checked every
> single generated `module-info.java` and `MANIFEST.MF`. IIRC, 3+ users
> shared positive feedback in GitHub Issues and the next `2.x` release will
> even support `jlink` due to #1896. Since there are no `module-info.java`
> files lying around (`bnd-maven-plugin` adds them to the JAR at the
> `package` phase), IDEs are not confused by the module-vs-class path dilemma
> too.
> 
> OTOH, JPMS support in the `main` branch was first established by
> hand-written `module-info.java` files and then later on reimplemented (work
> in progress!) by Piotr via porting stuff from `2.x`. Nobody has tested it
> yet, AFAIK. `jlink` is known to not work there.
> 
> In the context of JPMS support, `2.x` is a clear winner over `3.x`, AFAIC.
> If not, I would appreciate your help in explaining what I am missing.
> 
> Though `3.x` is good at two things regarding modularization:
> 
>   1. It breaks down `log4j-core` into more fine-grained modules (e.g.,
>   `log4j-csv`)
>   2. It has slightly improved package encapsulation. That is, some
>   internal classes are indeed moved to internal packages.
> 
> `2.x` can never implement #2, since it is a breaking change. Thought #1 can
> very well be implemented for `2.x` – users will just need to add a new JAR
> to their classpath.

Reply via email to