Another builder pattern for Java

Whenever you have a domain object, data transfer object, parameter object or any other object that can’t be instantiated with constructor parameters only, you need to create a builder for its class.

The great thing about Java is that it is strongly (statically) typed so a builder can give you compiler errors if you forget to set the compulsory parameters. If you use the builder in this pattern, you also get a very fluent interface that imposes order on the parameters. When using the builder, your IDE will suggest the next parameter to set.

Update 2017-08-21: Due to the interest still being upheld for this old post, I have created a GitHub repository so that you can try out the different versions of builders. I also added one version where I use the prefixes “Required” and “Optional” for interfaces, based on a suggestion in the comments sections of this post. Thanks for commenting, all of you! The GitHub repository is here.

Update 2017-08-24: I have updated the post with a more complex example with nested builders. It is based on setting up a Http request and serves to illustrate how an API can be more supportive using this pattern. The inspiration comes from a reader. See end of post for more.

Update 2020-10-21: I found a plugin to IntelliJ that refers to this post. I am honored. Check out the Step Builder Generator: https://plugins.jetbrains.com/plugin/8637-step-builder-generator

Problem

An object is to be initialized and it takes a number of attributes to do that. Some of the attributes are compulsory while others are optional. You don’t want to set up a long parameter list as your clients may make mistakes by placing the arguments incorrectly.

Consider a class representing email message objects:

public class EmailMessage {

private String from;
private String to;
private String subject;
private String content;
private String mimeType;  // optional

public EmailMessage(String from, String to, String subject, String content) {
this(from, to, subject, content, null);
}

public EmailMessage(String from, String to, String subject, String content, String mimeType) {
this.from = from;
this.to = to;
this.subject = subject;
this.content = content;
this.mimeType = mimeType;
}

Now that will make it possible to make a mistake, although there is a natural order to the arguments.


new EmailMessage("gojko@example.com",
"me@crisp.se",
"hello comrade",
"some content");

Solution

To make it more readable, we could use a builder:

EmailMessage.builder()
.from("gojko@example.com")
.to("me@crisp.se")
.subject("hello comrade")
.content("Some content")
.build();

This makes it more obvious to anyone reading the client code about what is going on.

The implementation of the builder is an inner class.

private EmailMessage() {}

public static Builder builder() {
return new EmailMessage.Builder();
}

public static class Builder {
private EmailMessage instance = new EmailMessage();

private Builder() {
}

public Builder from(String from) {
instance.from = from;
return this;
}

public Builder to(String to) {
instance.to = to;
return this;
}

public Builder subject(String subject) {
instance.subject = subject;
return this;
}

public Builder content(String content) {
instance.content = content;
return this;
}

public Builder mimeType(String mimeTypeName) {
instance.mimeType = mimeTypeName;
return this;
}

public EmailMessage build() {
return instance;
}
}

However, this is version 1 and so looked my builders for long, what could be better?

Firstly, there are compulsory and optional parameters, so we must check that the compulsory are all there. We could use exceptions for that. A revised “Builder.build”:

public EmailMessage build() {
assert instance.from != null;
assert instance.to != null;
assert instance.subject != null;
assert instance.content != null;
return instance;
}

But that delays the feedback until runtime and if we can shorten a feedback loop we should. What if we could get it already at compile time ?

It is not impossible and it will give us a even more fluent interface IDE-wise, so to speak.

By using a series of internal interfaces that the Builder class implements, we set up a chain of methods that guides the client.

The picture shows how this looks in IntelliJ and it will be similar in Eclipse and Netbeans. Notice that the “from” method returns the interface “ITo”. That interface has one method.

public interface ITo {
ISubject to(String to);
}

Thus a chain is created where “from” returns “ITo” which method returns “ISubject” that has method that returns “IContent” that returns “IBuild”, the last interface.

The IBuild interface has the job of handling the optional parameter “mimeType” and creation of the now correctly instantiated object. Therefore, there is no method returning a IMimeType interface.

public interface IBuild {
IBuild mimeType(String mimeTypeName);

EmailMessage build();
}

The client code looks almost the same. We did not need to, but we skipped the “builder” method and hit the “from” method directly. Since we are leaning on the language rules, the IDE tells us immediately which static method we should use.

EmailMessage
.from("gojko@example.com")
.to("me@crisp.se")
.subject("hello comrade")
.content("Some content")
.build();

Although the end result looks almost the same to the client, the feedback is more immediate and it is quicker to select one method than among several. You can no longer do this mistake:

EmailMessage
.from("gojko@example.com")
.to("me@crisp.se")
.subject("hello comrade")
.from("Some content")            //compilation error
.build();

So there is version 2 of the builder pattern for you. A bit more work for you when defining your classes but it is healthy to think about what is optional and what is not. And your clients will thank you. Not to mention when you must add another compulsory attribute. All client code will stop compiling which is so much better than crashing in runtime.

Nested builders for better API

A reader, Kenneth Stoner, commented and asked about more complex examples. This inspired me to create an example for Http requests. A request (in this example) has an URL, headers and parameters. Header fields may be more than one and same goes for parameters. We wish to get a clean interface where it is obvious that you enumerate the headers you want and then the parameters for the request.

I solved that with nested classes with each having a nested Builder class. Here is how the client code looks.


HttpRequest request = HttpRequest
.url(SOME_URL)
.headers(HttpRequest.Headers
.header(ContentType, SOME_MIME_TYPE)
.header(SOME_CUSTOM_HEADER, SOME_CUSTOM_VALUE)
.build()
)
.parameters(HttpRequest.Parameters
.parameter(SOME_KEY, SOME_VALUE)
.parameter(SOME_KEY_2, SOME_VALUE_2)
.build())
.build();

The complete code is found in the GitHub repository.

Check out the test files also and notice how the tests became fewer when we did not rely on exceptions for checking that the required fields had been set.

Happy coding!

27 responses on “Another builder pattern for Java

  1. Really enjoy the “required fields” enhancement to the Builder pattern! I did change your ISubject and IContent names (I’ve never felt the “I” added any value) to RequiresSubject and RequiresContent, which I thought provided an even more readable hint from the IDE…

  2. There is a capilization typo in this article that caused me a bit of confusion. Should be this instead: EmailMessage.Builder().from(“gojko@example.com”)

  3. I really love the work you have done here. In addition to making it clear what is required and what is optional, I really like how it makes an API more discover-able and self-documenting. I use this pattern extensively to write test-infrastructure APIs for integration tests which follow a BDD/given-when-then pattern which make my tests so much more readable.

    I would love to see some follow-on work on this around building API’s where an expression can have different end-points, operations/verbs which need to be called one or more times, such as add, and ways to build related but not identical expressions without rewriting code which looks similar for similar operations and verbs.

    1. Thanks, Kenneth, for those kind words.

      I like what you say about doing a follow-on, although I’m not sure that I fully understand. Perhaps if you would describe the problems you liked to be solved, it would be clear to me.

      1. As an example, lets say that an expression optionally requires 0 or more key value pairs – such as an expression which make a call to a web service which may need certain headers to be set. The way I am doing this now is with two different expression builders – the “outer” expression has a method, withHeaders(List) which takes a list of headers. In order to specify a new list of headers, I use another expression builder HeaderList which does nothing more than build the headers:

        whenAnSyncConnectionIsMadeTo(URL)
        .withHeaders(
        HeaderListBuilder.Create()
        .add(key1).and(value1)
        .add(key2).and(value2))
        .withBody(…)
        .usingPOST()

        The use of a different expression builder inside of the withHeaders() method seems somewhat clunky to me, and so I am wondering if there is a better way that you might recommend.

        A theme for such an article might be – Building Expression Builders that can work together?

  4. What’s you thought on moving the interfaces to the Builder class?

    It seems to me like something that fits better in it, but I could be wrong! 😀

    Very helpful article, thanks a lot.

    1. Thanks for the appreciation. I am not sure if I follow, wouldn’t that be a circular reference? I mean a class that has an internal interface that it implements?

      I’ll get the code on to GitHub so you can try easily and perhaps create a pull request!

  5. I came across this post and wanted to say thanks! It’s awesome!
    I did notice a couple of typos that were a bit confusing to me when I was trying to grok it.

    public interface IContent {
    IBuild content(String content);
    }

    // shouldn’t there be an interface for iMimeType here, referenced from previous method
    // and returning the iBuild method?

    public interface IBuild {
    IBuild mimeType(String mimeTypeName);
    EmailMessage build();
    }

    // Actually on closer inspection I guess there doesn’t need to be an extra interface for iMimeType
    You can just use IDE autocompletion for the last part since both content(String content) and mimeType(String mimeType) both return iBuild. I might be a bit slow, but hopefully my comment will help someone figure out very simply how this all works.

    1. Thank you for your comment.

      The idea is the Mime type is optional, that is why there is no IMimeType. I’ll revisit the post and see if I can make it clear.

  6. Can it be automatically generated, for example Lombok, or AutoValue,… something else?

    1. Thanks for asking. There are several ways of creating builders automatically, I know about IntelliJ and Lombok. No one that can generate this pattern, though.

      If there was one, it would need to now if attributes are mandatory or optional, plus the desired order of them. Doable, of course.

      You could mimic Lombok with annotation. You would need to write plugins for the major IDE, though.

      You could write a plugin for a specific IDE, like IntelliJ and when the user activates it, the code is generated.

      You could make an external program that generates the code from a specification, similar to those that generate code from XML or WSDL.

  7. Great article!
    You have provided a great insight here of builder design pattern in java. Designer pattern allows to develop complicated object phase by phase and also makes sure a way to develop an object as a finished object. It is very helpful for all java debvelopers to know about builder pattern in java, i have enjoyed this article, thanks a lot for sharing!

Leave a Reply to Adding Data To Objects – Another Builder Pattern – aspiringtogeekdom Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.