Skip to content

Record Builder

pawel_labaj edited this page Jun 8, 2023 · 11 revisions

Builders are a useful pattern that allow you to specify a set of optional parameters when creating a record, which can improve readability and reduce the need for constructor overloading.

AutoRecord provides support for generating builders using the Randgalt/record-builder library.

Enabling Builder Generation

To enable builder generation for a given interface, simply add the @AutoRecord.Options(withBuilder = true) annotation to it. This will cause AutoRecord to add the @RecordBuilder annotation to generated record and this will cause generating a builder.

The generated record includes a static builder() method, which return a new builder instance. It includes also a toBuilder() method, which returns a builder instance with the values from the existing record.

Example interface and generated record

Here's an example interface:

import pl.com.labaj.autorecord.AutoRecord;

@AutoRecord
@AutoRecord.Options(withBuilder = true)
interface Person {
    String name();
    int age();
}

Here's the corresponding generated record that demonstrates builder generation:

import static java.util.Objects.requireNonNull;

import io.soabase.recordbuilder.core.RecordBuilder;
import java.lang.Override;
import java.lang.String;
import javax.annotation.processing.Generated;
import pl.com.labaj.autorecord.GeneratedWithAutoRecord;

@Generated("pl.com.labaj.autorecord.AutoRecord")
@GeneratedWithAutoRecord
@RecordBuilder
@RecordBuilder.Options(
        addClassRetainedGenerated = true
)
record PersonRecord(String name, int age) implements Person {
    PersonRecord {
        requireNonNull(name, () -> "name must not be null");
    }

    static PersonRecordBuilder builder() {
        return PersonRecordBuilder.builder();
    }

    PersonRecordBuilder toBuilder() {
        return PersonRecordBuilder.builder(this);
    }
}

You can create the record instance with using builder:

PersonRecord person = PersonRecord.builder()
    .name("Joe")
    .age(25)
    .build();
PersonRecord olderPerson = person.toBuilder()
    .age(50)
    .build();

It is recommended to provide in your interface:

  • a factory method with a clear and descriptive name to get the record builder
  • an abstract toBuilder method that is implemented in the record

Here is an example of what it might look like:

import pl.com.labaj.autorecord.AutoRecord;

@AutoRecord
@AutoRecord.Options(withBuilder = true)
interface Person {
    String name();
    int age();

    static PersonRecordBuilder builder() {
        return PersonRecord.builder();
    }

    PersonRecordBuilder toBuilder();
}

Customizing Builder Generation

If you want to customize the builder generation process, you can add the RecordBuilder.Options annotation to the interface.

Example interface and generated record

Here's an example interface:

import io.soabase.recordbuilder.core.RecordBuilder;
import pl.com.labaj.autorecord.AutoRecord;

@AutoRecord
@AutoRecord.Options(withBuilder = true)
@RecordBuilder.Options(suffix = "_Creator")
interface Person {
    String name();
    int age();
}

Here's the corresponding generated record that demonstrates builder generation:

import static java.util.Objects.requireNonNull;

import io.soabase.recordbuilder.core.RecordBuilder;
import java.lang.String;
import javax.annotation.processing.Generated;
import pl.com.labaj.autorecord.GeneratedWithAutoRecord;

@Generated("pl.com.labaj.autorecord.AutoRecord")
@GeneratedWithAutoRecord
@RecordBuilder
@RecordBuilder.Options(suffix = "_Creator", addClassRetainedGenerated = true)
record PersonRecord(String name, int age) implements Person {
    PersonRecord {
        requireNonNull(name, () -> "name must not be null");
    }

    static PersonRecord_Creator builder() {
        return PersonRecord_Creator.builder();
    }

    PersonRecord_Creator toBuilder() {
        return PersonRecord_Creator.builder().name(name).age(age);
    }
}
📝 Note
It is recommended to use builder() and toBuilder() methods from an interface or generated record and not from generated builder.

For more information, refer to the RecordBuilder library's documentation.

Clone this wiki locally