Can you use Lombok toBuilder on an Abstract Class?

Can you use Lombok toBuilder on an Abstract Class?

Yes, you can, and you just need an additional line of code in the Abstract Class. Let's take a look at how we can do so.

Context

If you have an abstract class with various subclasses, and you need to define some values through builder method, you won't be able to do so by default because Lombok does not know if all the subclasses are annotated with toBuilder but we can force all subclasses to implement toBuilder method.

Setup

To make it simple, we only have an abstract class with 2 subclasses, and a couple of fields.

@SuperBuilder(toBuilder = true)
public abstract class AddressDO {
    private String id;
    private String street;
    private String postalCode;
    private String unit;
}

@SuperBuilder(toBuilder = true)
public class HomeAddressDO extends AddressDO {
    private boolean isRental;
}

@SuperBuilder(toBuilder = true)
public class OfficeAddressDO extends AddressDO {
    private String building;
}

Now, imagine we have a method that takes in AddressDO as the argument

public AddressDO createAddress(AddressDO addressDO) {
    // 1
    return addressDO;
}
  • We would like to call toBuilder on addressDO to define some fields

Problem

Take a look at the GIF below

From the GIF, we can see that even though we defined @SuperBuilder(toBuilder = true), we are unable to call toBuilder method. As mentioned above, this is done on purpose by Lombok, since it cannot ensure all subclasses are annotated with toBuilder.

Resolution

So how can we resolve this?

public abstract class AddressDO {
    public abstract AddressDOBuilder<?, ?> toBuilder(); // added this
    // omitted
}

We create an abstract toBuilder method which will ensure that all subclasses also implement this method.

This is what happens if the subclass did not implement toBuilder method

The type HomeAddressDO must implement the inherited abstract method AddressDO.toBuilder()

And now, if we try again

Limitation

The limitation is that it only allows for modification to the fields on the abstract class unless we cast it first. However, if we were to cast it, then there is no (less) need for the abstract method in the first place.

Conclusion

We have seen how we can overcome the limitation of calling toBuilder in an abstract class, and the limitation of doing so. I wouldn't call this a hack, but do use it only when you need it.

Source Code

As usual, the full source code is available on GitHub