Search code examples
javalogginglog4j2builderrollingfileappender

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?


Solution

  • 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?