Annotation-processor based builder pattern with Java 14 records

259 Views Asked by At

At my org we extensively use @Value.Immutable annotation with interfaces or abstract classes to generate Immutable classes with builders for our internal data transfer objects (DTOs) [ref].

We are writing a new service in Java 17 and want to leverage records for DTOs, but we don't want to give up on builder-pattern for construction. We do understand that immutability provided by records and builder-pattern are two unrelated concepts, but for our DTOs use-case builder-pattern is absolutely essential

A quick literature survey reveals that as of Sep 2023, the available options for getting builder-pattern out of Java records are

  1. Hand-written Builder class nested within Java record file
    • manual effort, no annotation-magic
  2. Lombok's @Builder annotation
    • Lombok is evil (no offense) and our entire org is moving away from it
  3. RecordBuilder library
    • I'm sceptical as to how long would it be supported by community
    • plus it also offers several customizations around pure / simple builders that i'm not too keen to adopt & don't want those unnecessary loopholes in my project

Are there any other workarounds of getting builder-pattern with Java records? We are even okay to start-off with hand-written nested builder-classes within records (since both options 2 & 3 make us uneasy), provided our beloved Immutables library starts supporting them in future so that we could seamlessly migrate to them.

1

There are 1 best solutions below

0
y2k-shubham On BEST ANSWER

We had created an issue [#1484] against Immutables library for this query and as per their response

  • They are planning to add full support for records. Most probably it will be Immutables 3
  • Till then Immutables library does in fact offer a workaround by means of @Builder.Constructor annotation
record Uio(
  int x,
  String b,
  boolean z) {

  @Builder.Constructor
  Uio {
    // ...
  }
}

var b = new UioBuilder()
  .x(4)
  .b("xx")
  .z(true)
  .build();