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 ;-)


8 Responses to “Fluent Interface and Reflection for Object Building in Java”  

  1. Gravatar Icon 1 afsina

    You may have a look at the Builder pattern introduced by Joshua Bloch. it is pretty good approach to this problem IMHO.
    http://developers.sun.com/learning/javaoneonline/2007/pdf/TS-2689.pdf

  2. Gravatar Icon 2 stephan

    Thanks, nice presentation, it looks interesting. I know the Builder pattern back from the GOF book and recently Groovy/Grails. Therefor I used the word “building” and not creating in the title. But I thought about how to implement this pattern with minimal implementation overhead, so I created the reflection solution.

    Perhaps the presentation will help me get rid of the suppress warning annotation.

  3. Gravatar Icon 3 prashant

    Stephan,

    Good idea.liked the implementation.BTW what’s the small bug?

    Thanks
    Prashant

  4. Gravatar Icon 4 stephan

    Thanks :-) Can’t find it anymore.

  5. Gravatar Icon 5 Timo Westkämper

    Nice idea. The following code

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

    might be a good addition. Because sometimes the instance is already available, but you still want to populate it fluently.

  6. Gravatar Icon 6 stephan

    Yes, very nice idea to add and seems useful.

  7. Gravatar Icon 7 Andrea Francia

    Your idea is a great idea.

    I wrote created an opensource library for creating Builders with fluent interface based on your idea in this post.
    I think I put the propert credits to you, if there are any problem let me know.

    I have also extended the builder to manage object lists.
    For example if Person has a property named ‘lovedThings’ of type List with the library I wrote you can write:

    Person person = Person.builder()
    .withFirstName(”John”)
    .withLovedThings(”pizza”, “soccer”, “jogging”)
    .build();

    The library can be found at http://www.andreafrancia.it/articoli/fluent-builder

  1. 1 Creating a fluent interface for Google Collections at Stephans Blog


Leave a Reply



RSS