AFAIK, @Data generates a @NoArgsConstructor, which is just wrong. Actually, @Data is wrong per se, as it's meant for mutable classes; @Value would be better, but it can't deal with the super constructor either.

So remove @Data, add @Getter, @EqualsAndHashCode, @ToString and whatever you need. Don't forget to add callSuper=true in the subclass.


This is effectively the constructor that Lombok should be constructing and invoking on the SuperBuilder.build() operation.

public Child(
    final String userId,
    final Instant requestingTime,
    final Instant beginningDate,
    final Instant endingDate,
    final Collection<String> fields) {

    super(userId, requestingTime);
    this.beginningDate = beginningDate;
    this.endingDate = endingDate;
    this.fields= fields;
}

No, that's not how SuperBuilder works. This is actually Lombok can't do as it can't see the super fields. Instead, the builder uses something like

public Child(ChildBuilder b) {    
    super(b);
    this.beginningDate = b.beginningDate;
    this.endingDate = b.endingDate;
    this.fields= b.fields;
}

You can believe what Jan Rieke says, he wrote it.

Answer from maaartinus on Stack Overflow
🌐
Baeldung
baeldung.com › home › java › lombok @builder with inheritance
Lombok @Builder with Inheritance | Baeldung
May 11, 2024 - As we noted earlier, version 1.18 of Lombok introduced the @SuperBuilder annotation.
🌐
Project Lombok
projectlombok.org › api › lombok › experimental › SuperBuilder
SuperBuilder (Lombok)
The SuperBuilder annotation creates a so-called 'builder' aspect to the class that is annotated with @SuperBuilder, but which works well when extending.
🌐
Lars-sh
lars-sh.github.io › lombok-annotations › apidocs › lombok › experimental › SuperBuilder.html
SuperBuilder (Lombok Annotations 1.18.48-SNAPSHOT API)
The SuperBuilder annotation creates a so-called 'builder' aspect to the class that is annotated with @SuperBuilder, but which works well when extending.
🌐
Code Like A Girl
code.likeagirl.io › java-why-lomboks-superbuilder-is-so-useful-0e6c34e61861
Java — Why Lombok’s @Superbuilder Is So Useful | by Cleopatra Douglas | Code Like A Girl
November 4, 2024 - The @SuperBuilder annotation in Java, provided by the Lombok library, is a powerful tool that simplifies the creation of complex builder patterns, especially in inheritance scenarios.
Top answer
1 of 2
5

AFAIK, @Data generates a @NoArgsConstructor, which is just wrong. Actually, @Data is wrong per se, as it's meant for mutable classes; @Value would be better, but it can't deal with the super constructor either.

So remove @Data, add @Getter, @EqualsAndHashCode, @ToString and whatever you need. Don't forget to add callSuper=true in the subclass.


This is effectively the constructor that Lombok should be constructing and invoking on the SuperBuilder.build() operation.

public Child(
    final String userId,
    final Instant requestingTime,
    final Instant beginningDate,
    final Instant endingDate,
    final Collection<String> fields) {

    super(userId, requestingTime);
    this.beginningDate = beginningDate;
    this.endingDate = endingDate;
    this.fields= fields;
}

No, that's not how SuperBuilder works. This is actually Lombok can't do as it can't see the super fields. Instead, the builder uses something like

public Child(ChildBuilder b) {    
    super(b);
    this.beginningDate = b.beginningDate;
    this.endingDate = b.endingDate;
    this.fields= b.fields;
}

You can believe what Jan Rieke says, he wrote it.

2 of 2
0

@Data annotation implicitly generate code for below mentioned functionalities:


  • setter
  • getter
  • toString
  • equallAndHashCode
  • constructor(for required arguments only)

It means constructor declaration of loombok will generate code for Parent class will be as mentioned below:

Person(String userId, Instant requestingTime)

Similarly for Child class:

Child(Instant beginningDate, Instant endingDate, Collection fields)


Now as your program is throwing exception that

Parent() is undefined in parent class.

Please annotate your class with :

@NoArgsConstructor

This will generate required default constructor.

🌐
Medium
medium.com › @drivaspedro › java-lombok-builder-annotation-with-inheritance-6541087040f2
Java Lombok Builder Annotation With Inheritance | by Drivaspedro | Medium
December 23, 2022 - @SuperBuilder public class Person { private String name; } @SuperBuilder public class Developer extends Person { private String language; } // Then instantiate the class like this: Developer developer = Developer .builder() .name("Drivas") .language("Java") .build(); This feature was introduced on the Lombok 1.18 release.
🌐
Google Groups
groups.google.com › g › project-lombok › c › Xrgh6Yy24ag
@SuperBuilder needs to be finalized.
Given Oracle's lack of desire to bring Java up to the features .Net developers are used to, I was creating a base class with the common properties. @Builder failed to do the required access to my "properties". @SuperBuilder does. Currently @SuperBuilder is in the "experimental" phase.
Find elsewhere
🌐
Project Lombok
projectlombok.org › features › SuperBuilder
@SuperBuilder
@SuperBuilder was promoted to the main lombok package since lombok v1.18.48.
🌐
GitHub
github.com › projectlombok › lombok › issues › 2209
[PROMOTION] @SuperBuilder - promote out of experimental · Issue #2209 · projectlombok/lombok
August 20, 2019 - I have been using the @SuperBuilder annotation for quite some time now yet it is still marked as experimental. In my opinion this is an essential feature when using builders in a class hierarchy. What is the current outlook for moving this out of the experimental stage and into mainstream? ... It's the youngest Lombok annotation, and it is not even implemented completely, e.g.
Top answer
1 of 2
24

Updated 2018-11-10: Lombok 1.18.4 released

Updated 2020-10-18: Lombok 1.18.16 released

Lombok 1.18.16 contains the new @Jacksonized annotation. With it, you can simply write:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
@JsonSubTypes({
  @JsonSubTypes.Type(value = SubA.class),
  @JsonSubTypes.Type(value = AnotherSub.class)
})
@Jacksonized
@SuperBuilder
// more annotations...
public abstract class AbstractA {

    @JsonProperty
    protected final String superProperty;
}

@Jacksonized
@SuperBuilder
@JsonTypeName("SubA")
// more annotations...
public class SubA extends AbstractA {

    @JsonProperty
    private final String fieldA;
}

This will automatically insert all necessary Jackson annotations and do some adjustments to the generated builder. No need to customized anymore.

For earlier Lombok versions between 1.18.4 and 1.18.12, this is the way to go:

For Lombok's @Builder and @SuperBuilder to work with Jackson, you have to add the builder class header manually and place a @JsonPOJOBuilder(withPrefix="") on it. Lombok will then generate only the remainder of the builder class. This is necessary because Jackson's default is that the builder's setter methods have "with" as prefix, but Lombok's builders don't have any prefix (and Lombok is not and will probably never be configurable in this regard).

When @SuperBuilder was introduced in Lombok 1.18.2, it was not customizable (i.e., you could not manually add the builder class header). As a result, using @SuperBuilder with Jackson was not easily possible.

This changed with Lombok 1.18.4 (see this pull request): @SuperBuilder is now (at least partially) customizable, and this allows us to add the annotation. Beware that the code generated by @SuperBuilder is quite complex and heavily loaded with generics. To avoid accidentally messing up the code, you should have a look at the delombok output and copy/paste the class header from there. Here, you need add the builder implementation class header and put the annotation on it:

@JsonPOJOBuilder(withPrefix="")
static final class SubABuilderImpl extends SubABuilder<SubA, SubABuilderImpl> {
}

Note that you have to broaden the visibility of SubABuilderImpl to at least package-private.

The @JsonDeserialize annotation must also refer to the builder implementation class, not the abstract builder:

@JsonDeserialize(builder = SubA.SubABuilderImpl.class)
2 of 2
5

A working solution in Eclipse, note that the Lombok IntelliJ integration is not supporting all features, therefore the code compiles fine in Eclipse and with javac but IntelliJ thinks it's broken but executes the code without an issue.

public static ObjectMapper createObjectMapper() {

    final ObjectMapper mapper = new ObjectMapper();
    mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {

        @Override
        public JsonPOJOBuilder.Value findPOJOBuilderConfig(final AnnotatedClass ac) {
            if (ac.hasAnnotation(JsonPOJOBuilder.class)) {
                return super.findPOJOBuilderConfig(ac);
            }
            return new JsonPOJOBuilder.Value("build", "");
        }
    });

    return mapper;
}

public static void main(final String[] args) throws Exception {
    final ObjectMapper objectMapper = createObjectMapper();

    final String serializedForm = objectMapper.writeValueAsString(SubA.builder().build());
    System.out.println(serializedForm);
    final SubA anA = objectMapper.readValue(serializedForm, SubA.class);
    System.out.println(anA);
}


@Getter
@EqualsAndHashCode(callSuper = true)
@Accessors(fluent = true, chain = true)
@SuperBuilder
@JsonDeserialize(builder = SubA.SubABuilderImpl.class)
@JsonTypeName("SubA")
public static class SubA extends AbstractA {

    @JsonProperty
    private final String fieldA;
}


@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = SubA.class)
})
@Getter
@Accessors(fluent = true, chain = true)
@SuperBuilder
public static abstract class AbstractA {

    @JsonProperty
    protected final String superProperty;
}
🌐
Google Groups
groups.google.com › g › project-lombok › c › YuG1h1eB93U
Depending on a generic SuperBuilder
to Project Lombok · I have a base entity which has a couple of properties and the concrete implementation with a couple of extra ones. On top of that I need the base class to access "self" of the child which I do through generics. Here is a simplified example of what I am trying: @Data · @SuperBuilder(toBuilder = true) @ToString(callSuper = true) public abstract class Entity<ENTITY extends Entity<ENTITY, BUILDER>, BUILDER extends Entity.EntityBuilder<ENTITY, BUILDER, ENTITY, BUILDER>> implements Mutable<ENTITY> { //... public abstract ENTITY mutate(Consumer<Context<ENTITY, BUILDER>> context) { var builder = createBuilder(); context.accept(new Context<>(self(), builder)); return builder.build(); } protected abstract ENTITY self(); protected abstract BUILDER createBuilder(); } @Data ·
🌐
GitHub
github.com › projectlombok › lombok › blob › master › src › core › lombok › experimental › SuperBuilder.java
lombok/src/core/lombok/experimental/SuperBuilder.java at master · projectlombok/lombok
* The SuperBuilder annotation creates a so-called 'builder' aspect to the class that is annotated with {@code @SuperBuilder}, but which works well when extending.
🌐
GitHub
github.com › projectlombok › lombok › issues › 2966
Call child constructor using @SuperBuilder · Issue #2966 · projectlombok/lombok
September 18, 2021 - In the docs there's a info telling that: @SuperBuilder generates a protected constructor on the class that takes a builder instance as a parameter.
Author: projectlombok
🌐
GitHub
github.com › vajpai › springboot-superbuilder
GitHub - vajpai/springboot-superbuilder: Lombok @SuperBuilder demo application · GitHub
This is possible with lombok 1.18.2 (and above) using the new (experimental) annotation @SuperBuilder. The only restriction is that every class in the hierarchy must have the @SuperBuilder annotation. There is no way around putting @SuperBuilder on all subclasses, because Lombok cannot know all subclasses at compile time.