Ruslan Akhundov Ruslan Akhundov - 6 months ago 72
Java Question

Log4j2 RollingFileAppender builder methods wrong return type

using Log4j2 library version 2.9.1.

I am trying to create

RollingFileAppender
programmatically:

RollingFileAppender appender = RollingFileAppender.newBuilder()
.withName(name)
.withLayout(...some layout...)
.withStrategy(...some strategy...)
.build();


And I couldn't compile it because it says there is no method
withStrategy
in that builder.

If I reorder method calls:

RollingFileAppender appender = RollingFileAppender.newBuilder()
.withStrategy(...some strategy...)
.withName(name)
.withLayout(...some layout...)
.build();


It couldn't compile because it says there is no build() method now.
So it looks like this builder methods return some base builder instead of the same one.

Temporary workaround was to create separate method with generic parameter:

private <B extends RollingFileAppender.Builder<B>> RollingFileAppender createAppender() {
return RollingFileAppender.<B>newBuilder()
.withName("name")
.withStrategy(...some strategy...)
.withLayout(...some layout...)
.build();
}


Then it works fine. But this is not the usual way of using Builder.

So the question is: is this a bug and is there a better way to create RollingFileAppender without this workaround?

Answer Source

Moving replies to answer since I can't paste code into comment.

My Ivy import:

<dependency org="org.apache.logging.log4j" name="log4j-core" rev="2.9.1"/>

So here is my code and it worked fine:

package org.sandbox.log4j;

import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.RollingFileAppender;
import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
import org.apache.logging.log4j.core.appender.rolling.RolloverDescription;
import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy;
import org.apache.logging.log4j.core.layout.ByteBufferDestination;

import java.util.Map;

public class RollingAppenderNew {
    public static void main(String[] args) {
        Layout<String> myLayout = new Layout<String>() {
            @Override
            public byte[] getFooter() {
                return new byte[0];
            }

            @Override
            public byte[] getHeader() {
                return new byte[0];
            }

            @Override
            public byte[] toByteArray(LogEvent event) {
                return new byte[0];
            }

            @Override
            public String toSerializable(LogEvent event) {
                return null;
            }

            @Override
            public String getContentType() {
                return null;
            }

            @Override
            public Map<String, String> getContentFormat() {
                return null;
            }

            @Override
            public void encode(LogEvent source, ByteBufferDestination destination) {

            }
        };

        RolloverStrategy myStrategy = new RolloverStrategy() {
            @Override
            public RolloverDescription rollover(RollingFileManager manager) throws SecurityException {
            return null;
            }
        };

        RollingFileAppender appender = RollingFileAppender.newBuilder()
            .withName("MyAppender")
            .withLayout(myLayout)
            .withStrategy(myStrategy)
            .build();
    }
}

I am thinking that the strategy object may not be using the correct base class and confusing the compiler. What are the base classes are you using for your layout and strategy?

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download