'Why doesn't Lombok Builder work with mutating an existing object?
Why doesn't Lombok Builder work with mutating an existing object?
What if I want to create a partially build object, and then later on update the object with the remaining fields?
Notice that this is not working. The pre-compiler doesn't like what I am trying to do.
Code Provided:
private static final ObjectMapper objectMapper = new ObjectMapper();
{
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
@Test
public void testBuilderMutating() throws JsonProcessingException {
Book unfinishedBook = Book.builder()
.isbn(String.valueOf(UUID.randomUUID()))
.title("Title")
.genre("Science Fiction")
.author("me")
.published(LocalDateTime.now())
.description("description ...")
.build();
Book completedBook = rebuildBook(unfinishedBook)
.sectionCount(4)
.sectionNames(List.of("A", "B", "C"))
.chapterCount(16)
.chapterNames(List.of("1", "2", "3"))
.build();
log.info(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(completedBook));
}
public Book.BookBuilder rebuildBook(Book unfinished) {
return Book.builder()
.isbn(unfinished.getIsbn())
.title(unfinished.getTitle())
.genre(unfinished.getGenre())
.author(unfinished.getAuthor())
.published(unfinished.getPublished())
.description(unfinished.getDescription())
.sectionCount(unfinished.getSectionCount())
.sectionNames(unfinished.getSectionNames())
.chapterCount(unfinished.getChapterCount())
.chapterNames(unfinished.getChapterNames());
}
POJOs are:
@ToString
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
public class Chapters extends Sections {
private int chapterCount;
private List<String> chapterNames;
}
@ToString
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
public class Sections {
private int sectionCount;
private List<String> sectionNames;
}
@ToString
@Data
@AllArgsConstructor
@SuperBuilder
public class Book extends Chapters {
private String isbn;
private String title;
private String genre;
private String author;
private LocalDateTime published;
private String description;
}
Solution 1:[1]
It happens because @SuperBuilder is defined as BookBuilder<?, ?> and java could not infer type if raw type is used Book.BookBuilder. To fix it change definition to
public Book.BookBuilder<?, ?> rebuildBook(Book unfinished) {
...
Also, to have correct implementation of toString and equals you need to use callSuper = true.
In addition, having @NoArgsConstructor, @AllArgsConstructor, @SuperBuilder and @Data looks a little too much. There is a way to define immutable POJO with Lombok and be able to deserialize using builder by applying @Jacksonized annotation.
@Getter
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Jacksonized
@SuperBuilder
public class Chapters extends Sections {
private int chapterCount;
private List<String> chapterNames;
}
@Getter
@ToString
@EqualsAndHashCode
@Jacksonized
@SuperBuilder
public class Sections {
private int sectionCount;
private List<String> sectionNames;
}
@Getter
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Jacksonized
@SuperBuilder
public class Book extends Chapters {
private String isbn;
private String title;
private String genre;
private String author;
private LocalDateTime published;
private String description;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Alex |

