Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Java Generics – Need explanation for the signature of this Log4j2 class – RollingFileAppender.Builder

Can someone please explain me the meaning of the signature of this class –

org.apache.logging.log4j.core.appender

Class RollingFileAppender.Builder<B extends RollingFileAppender.Builder<B>>

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

as documented – Log4j2 apidocs

I read it as Builder for type B, where B extends the Builder for type B, which confuses me like anything.

Also, this is a static class and it has a constructor as well. Is this normal? Can somebody please share a reference that can help me understand and use this in program?

PS –
About what I am doing here – I am working on modifying log4j code to make it compatible with log4j2, in which there is a RollingFileAppender created using RollingFileAppender constructor in a util class.

>Solution :

Builders usually have a fluent API. I.e. their building methods return the builder class to be able to directly call other building methods. For example, the class in question – RollingFileAppender.Builder – can be used like this:

var appender = builder.withAppend(true).withLocking(true).build();

That means that the building methods (the ones that are prefixed with with in this case) must return the same builder instance. But … If you design a builder class for being subclassed, you have a problem. What type shall the building method return?

Consider the following classes:

abstract class Builder {
    abstract Object build();
    Builder withProperty(String property) { return this; }
}
class ChildBuilder extends Builder {
    Object build() { return new Object(); }
    ChildBuilder withChildProperty(String childProperty) { return this; }
}

The actual return type of the build method does not matter for this explanation. The problem now is … you can’t do the following:

var obj = new ChildBuilder()
    .withProperty("property")
    .withChildProperty("child property") // Compiler error here!
    .build();

The return type of withProperty is Builder, and this type does not know about the building method withChildProperty. So you are breaking the fluent API.

The solution: A parameterized builder class! For our example, you do the following:

abstract class Builder<B extends Builder<B>> {
    abstract Object build();
    B withProperty(String property) { return this; } // Note the return type here.
}
final class ChildBuilder extends Builder<ChildBuilder> {
    Object build() { return new Object(); }
    ChildBuilder withChildProperty(String childProperty) { return this; }
}

Now you can do the code as I mentioned above.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading