yvasyliev opened a new issue, #2026:
URL: https://github.com/apache/logging-log4j2/issues/2026

   # Description
   In `log4j2` (ver `2.21.1`), we can create custom appender plugins with 
nested elements.
   
   Let's say we have the following `log4j2.xml` configuration:
   ```xml
   <?xml version="1.0" encoding="UTF-8"?>
   <Configuration status="warn">
       <Appenders>
           <MyAppender name="myAppender">
               <MessageTemplate prefix="Hello, " suffix="!"/>
           </MyAppender>
       </Appenders>
       <Loggers>
           <Root level="ALL">
               <AppenderRef ref="myAppender"/>
           </Root>
       </Loggers>
   </Configuration>
   ```
   
   `MyAppender` is a custom appender and `MessageTemplate` is a custom nested 
element.
   
   A source code of `MyAppender` class:
   ```java
   @Plugin(name = "MyAppender", category = Core.CATEGORY_NAME, elementType = 
Appender.ELEMENT_TYPE)
   public class MyAppender extends AbstractAppender {
       private final MessageTemplate messageTemplate;
   
       public MyAppender(String name, MessageTemplate messageTemplate) {
           super(name, null, PatternLayout.createDefaultLayout(), true, 
Property.EMPTY_ARRAY);
           this.messageTemplate = messageTemplate;
       }
   
       @PluginFactory
       public static MyAppender createAppender(@PluginAttribute("name") String 
name,
                                               
@PluginElement("MessageTemplate") MessageTemplate messageTemplate) {
           return new MyAppender(name, messageTemplate);
       }
   
       @Override
       public void append(LogEvent event) {
           var prefix = messageTemplate.getPrefix();
           var formattedMessage = event.getMessage().getFormattedMessage();
           var suffix = messageTemplate.getSuffix();
   
           var text = prefix + formattedMessage + suffix;
           System.out.println(text);
       }
   }
   ```
   A source code of `MessageTemplate` class:
   ```java
   @Plugin(name = "MessageTemplate", category = Core.CATEGORY_NAME, elementType 
= Appender.ELEMENT_TYPE)
   public class MessageTemplate {
       private final String prefix;
       private final String suffix;
   
       public MessageTemplate(String prefix, String suffix) {
           this.prefix = prefix;
           this.suffix = suffix;
       }
   
       @PluginFactory
       public static MessageTemplate createAppender(@PluginAttribute("prefix") 
String prefix,
                                                    @PluginAttribute("suffix") 
String suffix) {
           return new MessageTemplate(prefix, suffix);
       }
   
       public String getPrefix() {
           return prefix;
       }
   
       public String getSuffix() {
           return suffix;
       }
   }
   ```
   
   Let's create a main class:
   ```java
   public class Log4j2Demo {
       private static final Logger LOGGER = 
LoggerFactory.getLogger(Log4j2Demo.class);
   
       public static void main(String[] args) {
           LOGGER.info("World");
       }
   }
   ```
   
   If we run the code above, we'll get the following output:
   ```
   Hello, World!
   ```
   # Problem
   If the project is developed with Java 17, you may think of making 
`MessageTemplate` a record:
   ```java
   @Plugin(name = "MessageTemplate", category = Core.CATEGORY_NAME, elementType 
= Appender.ELEMENT_TYPE)
   public record MessageTemplate(String prefix, String suffix) {
       @PluginFactory
       public static MessageTemplate createAppender(@PluginAttribute("prefix") 
String prefix,
                                                    @PluginAttribute("suffix") 
String suffix) {
           return new MessageTemplate(prefix, suffix);
       }
   }
   ```
   Now the code extremely clean.
   But if we run it now, we'll get the following error:
   ```
   ERROR StatusConsoleListener MyAppender contains an invalid element or 
attribute "MessageTemplate"
   ERROR StatusConsoleListener An exception occurred processing Appender 
myAppender
    java.lang.NullPointerException: Cannot invoke 
"com.github.yvasyliev.log4j2.appenders.MessageTemplate.prefix()" because 
"this.messageTemplate" is null
        at 
com.github.yvasyliev.log4j2.appenders.MyAppender.append(MyAppender.java:31)
        at 
org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:161)
        at 
org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:134)
        at 
org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:125)
        at 
org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:89)
        at 
org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:686)
        at 
org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:644)
        at 
org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:620)
        at 
org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:556)
        at 
org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:81)
        at org.apache.logging.log4j.core.Logger.log(Logger.java:163)
        at 
org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2165)
        at 
org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2119)
        at 
org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2102)
        at 
org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:1982)
        at 
org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1835)
        at org.apache.logging.slf4j.Log4jLogger.info(Log4jLogger.java:174)
        at com.github.yvasyliev.log4j2.Log4j2Demo.main(Log4j2Demo.java:10)
   ```
   # Suggestion
   
   My suggestion is to add support of Java records to Log4j 2 annotations so we 
can create clean plugin code.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to