Hi Pavel,

[NOTE: I am cross-posting this to `dev@logging`, since I believe it is more appropriate there]

On 29.11.2024 10:26, PavelTurk wrote:
In the world of JPMS, there’s a service, we implement it, and we add it. I haven’t heard of a service + PROCESSOR that needs to be used. Can you point out any other projects that involve a service + processor? The reasoning is that we should only need to know the INTERFACE, and we’ll handle the IMPLEMENTATION ourselves. After all, it’s possible to do without it—for example, by writing a PluginService manually, which would scan the module itself and return the necessary classes or just data(entries) about them. That’s why I said that using a processor here seems odd to me. In general, I think code generation should only be used as a last resort—for example, for JPA metamodels—but that’s just my opinion.

The processor doesn't need to be used, but it is quite useful, when you have hundreds of plugins (which is the case for Log4j Core). Feel free to update the Plugins documentation in `3.x`[1] to make that explicit. We do have a draft PR to update that page, but it is a little bit stale[2].

Note that currently `PluginService` fulfills multiple functions, that could be delegated to separate classes/files:

1. It provides a mapping between (namespace, pluginName) and a class name, so we don't need to scan the classpath/modulepath. In this role it replaces the binary `Log4j2Plugins.dat` file, with something that IMHO is even harder to manipulate. We could probably replace it with a Java properties file or a JSON file like the one in [3]. The metadata could be generated by an annotation processor.

2. In a JPMS environment, it forces HotSpot to load all the available modules containing Log4j Core Plugins. For this to work, `PluginService` could just be an empty interface (easy to implement ;-) ).

3. In a non-JPMS environment, it simplifies the common practice of shading. `Log4j2Plugins.dat` files are hard to merge and many shading tools do not handle them. On the other hand most tools know how to merge `META-INF/services` files.

It is a little bit late in the lifecycle of 3.x to make drastic changes to how `PluginService` works, but we could:

* Either make `PluginService` an interface. Those that prefer to implement the interface can do it themselves, but we will provide an annotation processor that generates a JSON file and creates a minimal implementation that reads the JSON file.

* Or merge the functionality of `ConfigurableInstanceFactoryPostProcessor`[4] and `PluginService`. Strongly simplifying, what the `PluginService` does is registering a plugin builder `Supplier<T>` for each Log4j plugin `T` using a specific namespace and name. CIFPP does the same thing, but for "global" services like `MessageFactory`.

The latter proposition needs to be confirmed by Matt, who wrote the dependency injection system from scratch. Since the DI in Log4j Core is only used in Log4j Core, personally I find that the less features it provides, the better.

[1] https://logging.apache.org/log4j/3.x/manual/plugins.html

[2] https://github.com/apache/logging-log4j2/pull/2716

[3] https://github.com/apache/logging-log4j-transform/blob/main/log4j-converter-plugin-descriptor/src/main/resources/Log4j2Plugins.schema.json

[4] https://logging.apache.org/log4j/3.x/javadoc/log4j-plugins/org/apache/logging/log4j/plugins/di/spi/ConfigurableInstanceFactoryPostProcessor.html

[5] https://logging.apache.org/log4j/3.x/javadoc/log4j-plugins/org/apache/logging/log4j/plugins/di/Key.html


I assume module-info was also generated automatically. The problem is that it’s not present in log4j-core-3.0.0-beta3-sources.jar see [1], but it does exist in log4j-core-3.0.0-beta3.jar see [2]. Additionally, it’s not in the repository see [3]. So, it is not possible to see what is in this file. Or was I looking in the wrong place?

You assume correctly. We use the JPMS Libraries plugins for BND[5] to generate the module descriptor. There are several reasons behind this choice:

* Last time I checked, JPMS support in IDEs was terrible, especially for unit tests. Right now it seems better (in IntelliJ), but for a Maven project I need to choose if `src/test` contains whitebox tests that will run on the classpath or blackbox tests in a different package, that will run on the module path.

* It is hard to maintain a module descriptor manually, especially to keep track of the `transitive` attribute or unused dependencies. BND computes that perfectly.

* We want to have OSGi descriptors perfectly aligned with the JPMS descriptor.

Piotr

[5] https://bnd.bndtools.org/chapters/330-jpms.html

Reply via email to