Programming is hard by Stephan Schmidt

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

If you liked this post, subscribe to my free full RSS feed.
Filed under: Fluent Interface, Java

You can share this post!
Do you want to tell others about this article? Use the social bookmark icons to submit this artice to the service of your choice. Thanks.

Get free updates by email

If you did like this article you can get free updates with your RSS reader, you can follow me on Twitter or get free update to new posts by email. Enter your email:

 
About the author: Stephan has been working as a head of development and CTO. He has experiences in different technologies since 20 years including Java, Rails and Python. Stephans main field of interest is maintainablity and productivity in software development. Want to know more? All views are only his own.

Comments

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

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.

[...] Back to our example. I’ve recently shown how to create a fluent interface for object creation. One for Google Collections might look like this: [...]

Stephan,

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

Thanks
Prashant

stephan

Thanks :-) Can’t find it anymore.

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.

stephan

Yes, very nice idea to add and seems useful.

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

Uwe Langjahr

Hello Stephan,

how can you handle the modification of an instance with the fluent interfaces?

I have added a new method called “modify”, so that it is possible
to modify existing instances like:
person.modify().age(3).firstName(”Uwe”).lastName(”Langjahr”).active(false).age(109);

The method is implemented:
public PersonFluentInterface modify () {
return FluentInterface.create(this, PersonFluentInterface.class);
}

It works, but my problem is, that I’m not familiar with the reflection interface. Can you please
validate, that this implementation is correct (no unnecessary new instance are created etc.)

Greetings
Uwe

stephan

@Uwe: Yes, that should work.

Peace
-stephan

Leave a Reply