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 {@link oaj.annotation.Beanc @Beanc} annotation, using builders can often be cleaner.

A typical builder usage is shown below:

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

The code for such a builder is shown below:

public class MyBean { // Read-only properties. public final String foo; public final int bar; // Private constructor. private MyBean(MyBeanBuilder b) { this.foo = b.foo; this.bar = b.bar; } // Static method that creates a builder. public static MyBeanBuilder create() { return new MyBeanBuilder(); } // Builder class. public static class MyBeanBuilder { private String foo; private int bar; // Method that creates the bean. public MyBean build() { return new MyBean(this); } // Bean property setters. @Beanp public MyBeanBuilder foo(String foo) { this.foo = foo; return this; } @Beanp public MyBeanBuilder 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 MyBuilder create() {...}

- A public constructor on the POJO class that takes in a single parameter that implements the {@link oaj.transform.Builder} interface.
  The builder class must have a public no-arg constructor.

  public MyPojo(MyBuilder b) {...}

- A {@link oaj.annotation.Builder @Builder} annotation on the POJO class.
  The builder class must have a public no-arg constructor.

  @Builder(MyBuilder.class) public class MyPojo {...}

The second can be accomplished through any of the following:

- The existence of a build() method on the builder class.

  public MyPojo build() {...}

- The existence of a public constructor on the POJO class that takes in the builder instance.

  public MyPojo(MyBuilder b) {...}

- {@link oaj.annotation.Builder}
- {@link oaj.transform.Builder}