Fluent Interface and Reflection for Object Building in Java

A post by Randy Patterson on creating fluent interfaces in C# got me thinking. Randy shows how to create a Fluent Interface to build an object. He uses a Person class (POJO) with setFirstName and a PersonFluentInterface class with firstName. Creating an object and setting some attributes needs quite a lot of code:

Person person = new Person();
person.setFirstName("Pat");
person.setLastName("Frank");
person.setAge(30);
person.setActive(true);

The alternative and the usual way is to use a constructor and set the attributes. Often this results in unreadable constructor calls when creating objects (no paramter names in Java):

Person person = new Person("Frank", "Pat", 30, true);

What is "Frank", "Pat" and especially "true" ? In Groovy and other languages we could write:

Person person = new Person(firstName: "Frank",  lastName: "Pat", age: 30, active: true);

Indeed this is one of the best Groovy features and can be utilized when writing unit tests for Java classes. With a fluent interface the PersonFluentInterface class, which calls the setters on the POJO for him, Randy can write something similiar:

Person person = new Person();
person.Set.FirstName("Pat").LastName("Frank").Age(30).IsActive();

The set method in Person returns the PersonFluentInterface wrapped around the Person class. This looks more readable than calling lots of setters on an object and more readable than a large constructor call. We can do even a little better than Randy. With an additional method call we can combine the two lines in his example into one:

    Person person = Person.with()
      .firstName("Stephan")
      .lastName("Schmidt")
      .create();

Randys approach requires the developer to implement a PersonFluentInterface class which calls the correct setters on the object. The only thing we would need is the interface description of the Fluent Interface to enable the IDE to support code completion and provide static checking.

public interface PersonFluentInterface {
  public PersonFluentInterface firstName(String firstName);
  public PersonFluentInterface lastName(String lastName);
  public Person create();
}

I thought about a class which then maps the interface to a POJO with reflection. Some minutes later I was done. Voila!

public class FluentInterface<T> implements InvocationHandler {
  Object obj;

  public FluentInterface(Object obj) {
    this.obj = obj;
  }

  public static <T> T create(Object object, Class fluentInterfaceClass) {
    FluentInterface handler = new FluentInterface(object);
    @SuppressWarnings("unchecked")
    T fluentInterface = (T) Proxy.newProxyInstance(
       fluentInterfaceClass.getClassLoader(),
        new Class[]{fluentInterfaceClass},
        handler);
    return fluentInterface;
  }

  public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
    try {
      String name = m.getName();
      if ("create".equals(name)) {
        return obj;
      } else {
        String setter = "set" + name.substring(0, 1).toUpperCase()
          + name.substring(1);
        Statement stmt = new Statement(this.obj, setter, args);
        stmt.execute();
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
    }
    return proxy;
  }
}

Together with the interface we can now extend our Person POJO with an additional static method and we're ready to use a fluent interface to create our POJOs.

public class Person {
  private String firstName;
  private String lastName;

  public static PersonFluentInterface with() {
    return FluentInterface.create(
      new Person(), PersonFluentInterface.class);
  }

  public Person() {
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
}

Some future ideas: when using byte code instrumentation instead of a proxy we could use a abstract class which extends Person and calls the setter on itself. This would allow us the drop the create() call and add custom builder methods like "isMemberOfGroup(group)".

I'm quite satisfied with the results. Some lines could be tweaked and optimized, but overall the solution works. I'm going to use this for some time to decide if it's worth writing and maintaining the additional interface. But most probably it will increase the readability of large constructor calls for others and for me - after I haven't read the code in question for some weeks.

Thanks for listening.

Update: There is a small bug in the examples 😉

Stephan Schmidt Administrator
CTO Coach , svese
Stephan is a CTO coach. He has been a coder since the early 80s, has founded several startups and worked in small and large companies as CTO. After he sold his latest startup he took up CTO coaching. He can be found on LinkedIn or follow him in Twitter.
follow me