Skip to main content

POJO Builders

Juneau parsers can use builders to instantiate POJOs. This is useful in cases where you want to create beans with read-only properties.

Note that while it's possible to do this using the @Beanc annotation, using builders can often be cleaner.

A typical builder usage is shown below:

MyBean bean = MyBean.create().foo("foo").bar(123).build();

The typical code for such a builder using a static inner class is shown below:

public class MyBean {

// Read-only properties.
public final String foo;
public final int bar;

// Private constructor.
private MyBean(Builder builder) {
this.foo = builder.foo;
this.bar = builder.bar;
}

// Static method that creates a builder.
public static Builder create() {
return new Builder();
}

// Builder class.
public static class Builder {
String foo;
int bar;

// Method that creates the bean.
public MyBean build() {
return new MyBean(this);
}

// Bean property setters.

@Beanp
public Builder foo(String foo) {
this.foo = foo;
return this;
}

@Beanp
public Builder bar(int bar) {
this.bar = bar;
return this;
}
}
}

The POJO class can be any type including beans. Builders MUST be beans with one or more writable properties.

  • The bean properties themselves do not need to be readable (i.e. getters are optional).

Builders require two parts:

  1. A way to detect and instantiate a builder using reflection.
  2. A way to instantiate a POJO from a builder.

The first can be accomplished through any of the following:

  • A static create() method on the POJO class that returns a builder instance.
    public static Builder create() {...}
  • A public constructor on the POJO class that takes in a single parameter that implements the Builder interface.
    The builder class must have a public no-arg constructor.
    public MyBean(Builder builder) {...}
  • A @Builder annotation on the POJO class to explicitly identify it.
    The builder class must have a public no-arg constructor.
    @Builder(Builder.class) public class MyBean {...}

The second can be accomplished through any of the following:

  • The existence of a build() method on the builder class.
    public MyBean build() {...}
  • The existence of a public constructor on the POJO class that takes in the builder instance.
    public MyBean(Builder builder) {...}