Embracing the Messiness in Search of Epic Solutions

IntelliJ: Auto-generating POJO Builder

Posted

in

,

I have been searching for an elegant way to auto-generate a POJO fluent builder with minimal typing and configuration. A builder is a great way to promote object immutability, however it is also a pain to create and mantain yet another class that looks almost like the POJO class we create.

There are a few promising fluent builders out there in the wild, however, almost all of them still require some manual typing. After poking around, it seems like IntelliJ has its own fluent builder generator too.

Here’s how to do it without too much of typing…

Step 1: Define Fields in a Bean

The first step is to define the fields we need in a bean.

public class PersonBean {
    private String name;
    private LocalDate birthDate;
    private Double height;
    private Double weight;
}

Step 2: Auto-Generate Constructor and Getter Methods

The constructor and getter methods can be easily auto generated directly from IntelliJ. Do not generate setter methods.

public class PersonBean {
    private String name;
    private LocalDate birthDate;
    private Double height;
    private Double weight;


    public PersonBean(String name, LocalDate birthDate, Double height, Double weight) {
        this.name = name;
        this.birthDate = birthDate;
        this.height = height;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

    public LocalDate getBirthDate() {
        return birthDate;
    }

    public Double getHeight() {
        return height;
    }

    public Double getWeight() {
        return weight;
    }

}

Step 3: Auto-Generate Builder

Once we are satisfied with the constructor, right click on the contructor > Refactor > Replace Constructor with Builder….

In the popup dialog, click Refactor button.

By the way, if the bean allows optional fields, don’t bother hand typing the default values and checking the Optional Setter checkboxes right now because they are very tedious and they go against my “minimal typing” rule. My “Step 4” hack below will do exactly that.

IntelliJ will generate the following builder class in the same package as the POJO class:-

public class PersonBeanBuilder {
    private String name;
    private LocalDate birthDate;
    private Double height;
    private Double weight;


    public PersonBeanBuilder setName(String name) {
        this.name = name;
        return this;
    }

    public PersonBeanBuilder setBirthDate(LocalDate birthDate) {
        this.birthDate = birthDate;
        return this;
    }

    public PersonBeanBuilder setHeight(Double height) {
        this.height = height;
        return this;
    }

    public PersonBeanBuilder setWeight(Double weight) {
        this.weight = weight;
        return this;
    }

    public PersonBean createPersonBean() {
        return new PersonBean(name, birthDate, height, weight);
    }
}

Step 4: Create Nullable Fields in Builder Class

Do a regular expression “find and replace” to set null as the default value for all fields.

Find: (private \w+ \w+)(;)
Replace With: $1 = null$2

Now, we should see something like this:-

public class PersonBeanBuilder {
    private String name = null;
    private LocalDate birthDate = null;
    private Double height = null;
    private Double weight = null; 


    public PersonBeanBuilder setName(String name) {
        this.name = name;
        return this;
    }

    public PersonBeanBuilder setBirthDate(LocalDate birthDate) {
        this.birthDate = birthDate;
        return this;
    }

    public PersonBeanBuilder setHeight(Double height) {
        this.height = height;
        return this;
    }

    public PersonBeanBuilder setWeight(Double weight) {
        this.weight = weight;
        return this;
    }

    public PersonBean createPersonBean() {
        return new PersonBean(name, birthDate, height, weight);
    }
}

Step 5: Reduce POJO Constructor Visibility

The very last step is to change the POJO’s public-access constructor to package-access constructor by removing public .

The key here is to have all consumers to rely on the builder class to create the POJO.

public class PersonBean {
    private String name;
    private LocalDate birthDate;
    private Double height;
    private Double weight;

    PersonBean(String name, LocalDate birthDate, Double height, Double weight) {
        this.name = name;
        this.birthDate = birthDate;
        this.height = height;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

    public LocalDate getBirthDate() {
        return birthDate;
    }

    public Double getHeight() {
        return height;
    }

    public Double getWeight() {
        return weight;
    }
}

Step 6: Using the Builder

Finally, we can use the builder class to generate the POJO:-

PersonBean personBean = new PersonBeanBuilder()
        .setName("Hulk")
        .setBirthDate(new LocalDate(1900, 12, 1))
        .setHeight(7.5)
        .setWeight(250.0)
        .createPersonBean();

Comments

Leave a Reply