Yes, I guess I am able to reproduce the error. Given the following code:

import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.util.StringBuilderFormattable;
import org.junit.Test;

public class TraceExitTest {

    @Test
    public void test() {
        System.setProperty(
                "log4j.configurationFile",
                "/tmp/traceExit.xml");
        Logger logger = LogManager.getLogger("TraceExit");
        int result = logger.traceExit(
                new CustomMessage("Volkan was here"),
                1);
        logger.warn("result = %d", result);
    }

    private static final class CustomMessage
            implements Message, StringBuilderFormattable {

        private final String text;

        private CustomMessage(String text) {
            this.text = text;
        }

        @Override
        public String getFormattedMessage() {
            throw new UnsupportedOperationException();
        }

        @Override
        public String getFormat() {
            return "";
        }

        @Override
        public Object[] getParameters() {
            return new Object[0];
        }

        @Override
        public Throwable getThrowable() {
            return null;
        }

        @Override
        public void formatTo(StringBuilder buffer) {
            buffer.append(text);
        }

    }

}

In combination with the following /tmp/traceExit.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="ERROR">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%msg%n%throwable"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="TRACE">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Log4j produces the "An exception occurred processing Appender Console
java.lang.UnsupportedOperationException" error message. In the case of
PatternLayout, it handles StringBuilderFormattable with a simple
instanceof check -- just like any other layout. Though check out the
following AbstractLogger#traceExit() implementation:

@Override
public <R> R traceExit(final Message message, final R result) {
    // If the message is null, traceEnter returned null because ...
    if (message != null && isEnabled(Level.TRACE, EXIT_MARKER, message, null)) {
        logMessageSafely(...,
flowMessageFactory.newExitMessage(result, message), null);
    }
    return result;
}

CustomMessage gets wrapped by a
DefaultFlowMessageFactory.SimpleExitMessage invalidating the
"instanceof StringBuilderFormattable" check. Would anybody mind
confirming the bug, please? If so, I will create a JIRA ticket and a
branch containing the reproduction test(s).

Kind regards.

On Wed, Jun 17, 2020 at 6:53 PM Fred Eisele <fredrick.eis...@gmail.com> wrote:
>
> You are right I need to give more detail.
>
> If the first argument is a String then it is presumed to be a format
> specification.
> In that case the second argument, if it is a StringBuilderFormattable, has
> its formatTo() method called.
> [All good]
>
> If the first argument is a Message then the formatTo() is not called.
>
> class Foo implements StringBuilderFormattable {
>    @Override
>    public void formatTo(StringBuilder buffer) {  buffer.append("bar"); }
> }
> ...
> final Message em = log.traceEntry();
> ...
> log.traceExit("{}", new Foo());    // logs the formatTo method [all good]
> log.traceExit(em, new Foo());    // logs the toString method  *[not what I
> expected]*
>
>
>
> On Wed, Jun 17, 2020 at 4:05 AM Volkan Yazıcı <volkan.yaz...@gmail.com>
> wrote:
>
> > Hello Fred,
> >
> > If the Message you pass to traceExit(Message,R) implements
> > StringBuilderFormattable, indeed formatTo(StringBuilder) will be used
> > by the layout for serialization. What do you mean by "this does not
> > seem to be the case"? Would you mind elaborating a bit more on what
> > you're exactly trying to do? Further, a reproduction path will be
> > greatly appreciated.
> >
> > Kind regards.
> >
> > On Tue, Jun 16, 2020 at 4:16 PM Fred Eisele <fredrick.eis...@gmail.com>
> > wrote:
> > >
> > > When traceExit(m,r) is used...
> > > Is there a mechanism for controlling the formatting of the result?
> > > Other than overriding the 'toString()' method.
> > > When formatted messages are used and the object's class implements
> > > the StringBuilderFormattable interface the 'formatTo()' method
> > > is used preferentially over 'toString()'.
> > > This does not seem to be the case for serializing the result by
> > traceExit.
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: log4j-user-unsubscr...@logging.apache.org
> > > For additional commands, e-mail: log4j-user-h...@logging.apache.org
> > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: log4j-user-unsubscr...@logging.apache.org
> > For additional commands, e-mail: log4j-user-h...@logging.apache.org
> >
> >

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-user-h...@logging.apache.org

Reply via email to