-
Notifications
You must be signed in to change notification settings - Fork 2
Record Builder
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.
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.
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();
}
If you want to customize the builder generation process, you can add the RecordBuilder.Options
annotation to the interface.
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.