Re: Problems creating custom appender using JPMS service in 3.0.0-beta3
PavelTurk <[email protected]> Thu, 28 Nov 2024 20:26:05 +0200
| Newsgroups | gmane.comp.jakarta.log4j.user |
|---|---|
| Message-ID | <[email protected]> |
Hi Piotr,
Thank you very much for your detailed and quick help.
However, to tell the truth, I’m a bit confused. I’ve been waiting for a long time for Log4j to finally work according to the JPMS rules. But in your message, you talk about compile-time and, as I understood, the use of some plugin-processor (from your project pom):
<annotationProcessorPaths>
<path>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-plugin-processor</artifactId>
<version>3.0.0-beta3</version>
</path>
</annotationProcessorPaths>
Doesn’t all this completely contradict JPMS? When we talk about JPMS, we’re talking about modules, layers, and services. For example, if we need some plugin, then we:
a) create a module with the implementation of this plugin b) add the created module to the appropriate layer.
This is very convenient and works perfectly (even when classes have annotations). For instance, I have a project where console commands can be added by user. I created:
public interface CommandFactory {
Set<Class<? extends Command>> getSupportedCommands();
<T extends Command> T command(Class<? extends Command> klass);
}
And any module that has commands implements this interface and declares `provides ... with ...` in module-info, along with `opens` for the package containing the commands. As a result, the command manager gets the command classes, can analyze them, and create a command if needed.
By the way, I noticed something seemed off when I saw code duplication in your project:
@Configurable(elementType = Appender.ELEMENT_TYPE, printObject = true)
@Plugin(ConsoleAppender.PLUGIN_NAME)
public final class ConsoleAppender...
and
PluginEntry.builder()
.setKey("console")
.setClassName("org.apache.logging.log4j.core.appender.ConsoleAppender")
.setName("Console")
.setNamespace("Core")
.setElementType("appender")
.setPrintable(true)
.get(),
Or am I mistaken (which is always possible) and misunderstood everything?
Best regards, Pavel
On 11/28/24 19:45, Piotr P. Karwasz wrote:
> Hi Pavel,
>
> On 28.11.2024 15:47, PavelTurk wrote:
>> Hello everyone.
>>
>> I am trying to create my own appender using JPMS service in 3.0.0-beta3. This is my code:
>
> Apparently two small bugs made their way to `3.0.0-beta3`([1] and [2]), which make compilation under JPMS challenging, but not impossible.
>
> You can find a complete example of a custom appender on my repo:
>
> https://github.com/copernik-eu/bug-reproducibility/tree/main/log4j-core-3.0.0-beta3-jpms
>
> [1] https://github.com/apache/logging-log4j2/issues/3250
> [2] https://github.com/apache/logging-log4j2/issues/3251
>> import org.apache.logging.log4j.plugins.model.PluginEntry;
>> import org.apache.logging.log4j.plugins.model.PluginService;
>>
>> public class PluginProvider extends PluginService {
>>
> This is usually not needed, you just need to have `log4j-plugin-processor` on the annotation processor path. If you disabled the automatic annotation processor detection, you also need to add `org.apache.logging.log4j.plugin.processor.PluginProcessor` to the list of annotation processors.
>
> The plugin processor generates a class named `<pluginPackage>.plugins.Log4jPlugins`, where `<pluginPackage>`:
>
> * Can be provided explicitly using `-ApluginPackage=...`,
>
> * If it is not provided explicitly, it is the common prefix of all your Log4j Core plugins.
>
> If you just have `com.example.FooAppender`, the generated `PluginService` will be: `com.example.plugins.Log4jPlugins`.
>
> [1] https://logging.apache.org/log4j/3.x/components.html#log4j-plugin-processor
>
>> Result:
>> Exception in thread "main" org.apache.logging.log4j.plugins.di.spi.ReflectionException
>> at [email protected]/org.apache.logging.log4j.plugins.di.spi.ReflectionAgent.invokeMethod(ReflectionAgent.java:84)
>> at [email protected]/org.apache.logging.log4j.plugins.di.DefaultInstanceFactory.lambda$registerBundleMethod$13(DefaultInstanceFactory.java:306)
>>
> Do you have a message and a cause for this exception? If this is not issue #3250 I mentioned before, please share the entire stack trace.
>
>
>> So, java dies in main class where I initializer my logger.
>> Could anyone say: 1) how to fix it 2) How to use custom Namespace for my appender in configuration?
>> For example, if I do PluginEntry.builder().setNamespace("FooNS")?
>
> The purpose of namespaces is to distinguish between plugins that have the same name, but have different functions. For example the `<Replace>` configuration element is in the "Core" namespace, while the `%replace` pattern is in the `Converter` space. In general you shouldn't be concerned by namespaces:
>
> * The plugins that correspond to XML elements in the configuration file MUST be in the "Core" namespace.
>
> Piotr
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>