Using Lombok's @SuperBuilder concept on a class extended from a 3rd party library

Viewed 766

I have a class hierarchy as below.

Child --> Parent --> SuperParent

Since the Child class has extended the Parent class I have to use Lombok's @SuperBuilder annotation instead of the @Builder. Also, as far as I know, all the superclasses need to have the @SuperBuilder annotation. But in my case, the SuperParent class comes from an external library, where I cannot add the @SuperBuilder annotation. I am getting the below compilation error.

The constructor SuperParent(DocumentUploadedResponseDto.DocumentUploadedResponseDtoBuilder<capture#1-of ?,capture#2-of ?>) is undefined.

Any solution or an alternative for this? Thank you.

2 Answers

It's a bit ugly, but it's possible. You have to insert a helper class into your inheritance chain between Parent and SuperParent; let's call it SuperParentBuilderEnabler. In this class, you have to manually implement all neccessary builder elements. Especially, you have to write all setter methods for the fields from SuperParent. This will allow the Parent and Child classes to simply use a @SuperBuilder annotation without any further modifications.

I assume that SuperParent has an int superParentField field, just to demonstrate how you can write such a setter method in the builder class. Furthermore, I assume that this field can be set via constructor argument. Here is what you have to do:

public abstract class SuperParentBuilderEnabler extends SuperParent {
    public static abstract class SuperParentBuilderEnablerBuilder<C extends SuperParentBuilderEnabler, B extends SuperParentBuilderEnablerBuilder<C, B>> {
        private int superParentField;

        public B superParentField(int superParentField) {
            this.superParentField = superParentField;
            return self();
        }

        protected abstract B self();

        public abstract C build();
    }

    protected SuperParentBuilderEnabler(SuperParentBuilderEnablerBuilder<?, ?> b) {
        super(b.superParentField);
    }
}

Now let Parent extend SuperParentBuilderEnabler and you're done.

I'm sharing how I applied the accepted answer for RepresentationModel.

abstract class BaseTypeParent<T extends BaseTypeParent<T>>
        extends RepresentationModel<T> {

    protected abstract static class BaseTypeParentBuilder<
            T extends BaseTypeParent<T>,
            C extends BaseTypeParent<T>,
            B extends BaseTypeParentBuilder<T, C, B>
            > {

        protected abstract B self();

        public abstract C build();
    }

    protected BaseTypeParent(final BaseTypeParentBuilder<T, ?, ?> b) {
        super();
    }
}
Related