Mittwoch, 31. Juli 2013

Fluent API and JSF

A fluent-API-style builder is a nice way to create objects. I wrote about it in my previous post. Unfortunately this pattern does not work well together with JSF, because your domain model needs JavaBean-style properties if you want to use it in the expression language (EL) of JSF.

Accessing objects via EL

In fact this is not the whole truth. JSF provides many possibilities to access properties via EL: Besides properties of JavaBeans, you can access content of arrays, lists and maps - and most notably it provides a mechanism to extend this to your own need: The ELResolver. In general an ELResolver is responsible for the evaluation of expressions like #{address.city} (which could also be written as #{address['city']}). So, if we want to achieve that this expression matches a fluent-style Builder (i.e. calls a method like AddressBuilder.withCity(String)), we have to implement an ELResolver ourself.

Extending JSF via a custom ELResolver

The ELResolver itself is an abstract class with some abstract methods, that we have to implement, when we subclass an ELResolver.

JSF maintains a list of ELResolvers. When an expression is encountered, it is split at the dots (the actual parsing is a bit more complicated, since square brackets are allowed, too) and for every part of that expression the appropriate ELResolver is searched by walking through the chain and looking for the first ELResolver that feels responsible for that part of the expression.

A FluentELResolver

So how to write an ELResolver that accepts objects with a fluent api?

Let's take the example from my previous post: We have an AddressBuilder with a property streetNumber and a property street, that can be set by calling forStreetNumber(String).ofStreet(String).

In JSF we want to bind our input fields to the expressions #{address.streetNumber} and #{address.street}. The first part is easy. We have to create a CDI bean from our AddressBuilder that is accessible via the name "address". We can achieve this by adding @Named and a scope to the builder. I choose the conversation scope here:

@Named("address")
@ConversationScoped
public class AddressBuilder {
  ...
}

So when JSF encounters the expression #{address.street} it will first ask all ELResolvers, if they know an object of name "address". This will be done by calling the method getValue(ELContext context, Object base, Object property) of every ELResolver with the base parameter being null and the property parameter being the string "address". Well, our ELResolver does not have to care about resolving an object with name "address", since CDI will resolve it and return the appropriate bean. But then it comes to the part "street". Again JSF will call the method getValue(ELContext context, Object base, Object property) of every ELResolver. This time the base will be our AddressBuilder and the property will be "street". So what to do in our FluentELResolver? For the first shot, let's assume, that we have a getter for every property in our AddressBuilder. For this case, we could just extend an existing ELResolver, the javax.el.BeanELResolver and JSF will accept our builder to be responsible for the expression. The BeanELResolver is responsible for evaluation of JavaBean style properties. Later on I will discuss what to do, if we don't want our builder to contain getters. So for now the only difference of our FluentELResolver to the javax.el.BeanELResolver are the write operations. For this we have to override the methods boolean isReadOnly(ELContext context, Object base, Object property) and void setValue(ELContext context, Object base, Object property, Object value). Within this methods we have to check, if a method exists on the base object, that may be a fluent api method of the property:

public FluentELResolver extends BeanELResolver {

  public boolean isReadOnly(ELContext context,
                            Object base,
                            Object property) {
    return getFluentMethod(context,
                           base,
                           property.toString())
           != null;
  }

  public void setValue(ELContext context,
                       Object base,
                       Object property,
                       Object value) {
    invoke(getFluentMethod(context,
                           base,
                           property.toString),
           base,
           value);
  }

  private Method getFluentMethod(ELContext context,
                                 Object base,
                                 String name) {
    name = Character.toUpperCase(name.charAt(0))
           + name.substring(1);
    for (Method method: base.getClass().getMethods()) {
      if (isFluentWriteMethod(method,
                              context,
                              base,
                              name)) {
        return method;
      }
    }
    return null;
  }

  private boolean isFluentWriteMethod(Method method,
                                      ELContext context,
                                      Object base,
                                      String property) {
    return method.getName().endsWith(property)
           && method.getParameterTypes().length == 1
           && method.getParameterTypes()[0]
              == getType(context, base, property);
  }
}

Of course, for performance reasons the result of the method getFluentMethod should be cached. This is left as an excercise for the reader. Besides that the code is still not complete. As I mentioned earlier, JSF will walk through every ELResolver to ask, if it can handle a certain property. But how can JSF know, if our resolver has handled the property? We have to inform the ELContext. This can be done by calling context.setPropertyResolved(true). So we add this call and some null checks to the code:

public FluentELResolver extends BeanELResolver {

  public boolean isReadOnly(ELContext context,
                            Object base,
                            Object property) {
    if (base == null || !(property instanceof String)) {
      return true;
    }
    Method method = getFluentMethod(context,
                                    base,
                                    property.toString());
    if (method == null) {
      return true;
    }
    context.setPropertyResolved(true);
    return false;
  }

  public void setValue(ELContext context,
                       Object base,
                       Object property,
                       Object value) {
    if (base == null || !(property instanceof String)) {
      return;
    }
    Method method = getFluentMethod(context,
                                    base,
                                    property.toString());
    if (method == null) {
      return;
    }
    invoke(method, base, value);
    context.setPropertyResolved(true);
  }

  private Method getFluentMethod(ELContext context,
                                 Object base,
                                 String name) {
    ...
  }

  private void invoke(Method method,
                      Object base,
                      Object value) {
    try {
      method.invoke(base, value);
    } catch (IllegalAccessException e) {
      throw new ELException(e);
    } catch (InvocationTargetException e) {
      throw new ELException(e.getCause());
    }
  }
}

Registering the ELResolver

The registration of our FluentELResolver is very simple. Just put it into the faces-config.xml:

<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">
  <application>    
    <el-resolver>
      de.openknowledge.extensions.el.FluentELResolver
    </el-resolver>
  </application>
</faces-config>

Using builders without getters

Until this point, we assumed that our builder has getter methods to read-access the fields we want to set via the fluent api. What, if we don't have getters? If we want to do that, we no longer need to extend BeanELResolver, but can directly extend ELResolver and implement the remaining methods (most notable getValue) on ourselfs.

For the implementation of getValue I suggest scanning the available fields in the class by reflection. This should work for most cases. If you use the Inner Class Builder from my previous post, you should also scan the declaring class of the builder class and you may scan it for getters, too.

From a technical point of view, it would be possible to implement an ELResolver, that completely relies on reflection (also for the method setValue). I.e. we could implement a FieldAccessELResolver. Please don't do this! You would loose every validity check, that is implemented in your builder, since its methods are not used any more. Since you usually don't have validity checks in your getters, it seems to be ok, to use field access there. Btw. a FieldAccessELResolver as well as the field-access approach suggested above will get problems, if you deal with a contextual reference of CDI, since it is just a proxy and will not have its fields set.

The german version of this post can be found here.

Freitag, 14. Juni 2013

Thoughts on Builders

In my previous post I wrote about setters and that you should not use them in your domain model. The idea behind this is, that an object should be valid and consistent in every stage of its lifecycle. I.e. an empty address object is neither valid nor consistent. So I don't allow to create an empty address object. In fact an address may not be mutable. If I would change an attribute, it would be a completely new address and - the word new indicates this - should be a new object. So, if it is immutable, how to create it, so that it is valid and consistent from the beginning on? Btw., even objects that are mutable should be valid and consistent at any time. The easiest way to achieve this, is to provide a constructor that has a parameter for every non-optional attribute of the object.

public class Address {
  public Address(String street,
                 String streetNumber,
                 String zipCode,
                 String city,
                 String state,
                 String country) {
    ...
  }
}

Within that constructor you can ensure, that the object is valid and consistent from the beginning on. If the parameters are inconsistent, the constructor throws an exception. So far, so good, but as we can see from the example with an increasing number of attributes this is getting more and more ugly, since the number of constructor parameters increases (not to mention that your checkstyle plugin should complain). So what is the solution for this?

My favorite solution for this problem is the Builder pattern. Following the Single Responsibility Principle the builder is just responsible for creating the object. There are diffenent styles of builders, which I want to introduce now.

The JavaBean Style Builder

The first approach of a builder looks very close to a simple JSF bean (in fact it follows the JavaBeans standard). Just create a getter and setter for every attribute of the address.

Readers of my previous post may ask: in what kind is this builder better than the object with generated getters and setters I told you I hate. The answer is simple: The builder is just responsible to create a domain object. The actual validation of the parameters may take place at a single point in code and this point ensures that only valid and consistent address domain objects are created. We'll see later, where this single point in code may be (there are actually multiple choices). This is how you may use this kind of builder:

AddressBuilder builder = new AddressBuilder();
builder.setStreet(...);
builder.setStreetNumer(...);
builder.setZipCode(...);
builder.setCity(...);
builder.setState(...);
builder.setCountry(...);
Address address = builder.build();

This style of a builder is ok to me and it can even be used in JSF to create an object. But the code could be less verbose.

The Fluent-API Style Builder

We can reduce the code to create an address a lot, just by introducing method chaining for the builder. That means that every method of the builder returns this. This enables us to remove most of the references to the builder variable in the usage example above:

Address address = new AddressBuilder()
  .setStreet(...)
  .setStreetNumer(...)
  .setZipCode(...)
  .setCity(...)
  .setState(...)
  .setCountry(...)
  .build();

And we can even improve the readability of this code by using a fluent api:

Address address = new AddressBuilder()
  .forStreetNumber(...).ofStreet(...)
  .inCity(...).withZipCode(...)
  .lyingInState(...).ofCountry(...)
  .build();

Little problem with that code is that you cannot see from the builder code that it creates an address. You can further expose this by providing a static method within the builder:

public class AddressBuilder {
  public static AddressBuilder newAddress() {
    return new AddressBuilder();
  }
  ...
}

Using this method and a static import the above address creation code is even more readable:

Address address = newAddress()
  .forStreetNumber(...).ofStreet(...)
  .inCity(...).withZipCode(...)
  .lyingInState(...).ofCountry(...)
  .build();

Now we have seen two different styles of builders and how to use them. I don't think that there are two opinions about that the second variant is more elegant. Anyway, both variants have a method build() that returns an address object. For now we never mentioned how to implement this method. And this becomes tricky since we don't want the address to have a constructor with such number of arguments and we don't want to have an invalid and inconsistent address either. There are three ways to achieve this.

The obvious approach

The problem is, that we don't want to have many parameters in our constructor and we want to create our address at a single point in code, being valid and consistent? So let's give the Builder to the object and we are done.

public class Address {
  private String street;
  ...
  public Address(AddressBuilder builder) {
    street = validateStreet(builder.getStreet());
    ...
  }
  ...
}

The first disadvantage of this approach is, that our builder not only needs to have the fluent api, but also getters for all of its attributes. But that is not too bad. What people don't like with this approach is the dependency of the address to its builder. So what to do to invert this dependency? We can move the complete creation logic into a build() method of the builder. The problem is: How does the builder create the address object without using a constructor (and we neither want to use a constructor with many parameters nor a constructor taking the builder, because of the dependency)?

Package-access Builder

We can put the builder into the same package as the address and provide package-private (no modifier) setters for the attributes. This way you ensure that no code from outside the package can use the setters, but the builder can. Don't forget to make the constructor of the address package-private, too.

public class AddressBuilder {
  ...
  public Address build() {
    Address address = new Address();
    address.setStreet(validateStreet(street));
    ...
    return address;
  }
}

public class Address {
  ...
  Address() {
    // reduce visibility of the default constructor
  }

  public String getStreet() {
    return street;
  }

  // may just be used by the builder
  void setStreet(String initialStreet) {
    street = initialStreet;
  }
  ...
}

This approach works out very well and the creation logic for the address is at a single point in code, too: in the build() method. What I don't like at this approach is the re-introduction of setters, although they are package-private and may not be used from outside. It's just a feeling: If a programmer needs to modify an attribute, it's just to simple to put a public before that method and we are again at that point I was talking about in my previous post. This is why I don't like this approach much.

The Inner Class Builder

Remember, that our main problem is: How can the builder create an address and set its attributes without using a constructor that receives all this attributes and - in opposition to the previous approach - even without using setters. Well, this can be achieved, by making the builder an inner class of the address.

public class Address {
  public static Builder newAddress() {
    return new Address().new Builder();
  }
  private String street;
  ...
  public class Builder {
    public Builder ofStreet(String initialStreet) {
      street = validateStreet(initialStreet);
      return this;
    }
    public Address build() {
      validate();
      return Address.this;
    }
  }
}

This approach works out good as well, but it contains many code that a junior programmer may not have seen before, like new Address().new Builder() and Address.this. So this may be the most complex to understand code at a first glance, but if you once have understood it, it works out well, too. The drawback is, that the address object is created right before builder creation. But this is no problem, since code from outside can access the object only after it is validated by the builder.

It doesn't matter which approach you take, when it comes to JSF, you have the problem, that you cannot bind this builders directly to the UI (except for the JavaBean style one, which is not so elegant). In one of my next blog posts I will show what to do to directly use a fluent builder in JSF. Stay tuned.

The german version of this blog entry can be found here.

Freitag, 3. Mai 2013

A word on setters

I like the concepts of Clean Code and Domain Driven Design and thus like my domain model to express itself.

And - I hate setters! For those of you, who don't know, what I am talking about, please read the JavaBeans spec, especially chapter 7.1. Setters are almost always wrong! At least the one that where created automatically by the IDE. Developers that generate setters almost always don't care about business logic.

An example? Think of an domain model entity that represents a person. A simple person entity may have two attributes: firstName and lastName. I can't think of a use case where it makes sense to create such simple person without any of that attributes set. And further more, this attributes are not likely to change any time soon. So why should this person have a constructor that does not enforce to set this attributes? And why should it have setters for this attributes?

"Wait" does the attentive reader shout here: "What, if the person marries?" OK - thats a use case. Do we have to take this use case into account? If yes, let's implement that business logic. Is this a reason to implement setLastName(...)? No! setLastName(...) in no way expresses the fact that it belongs to the use case of marriage. And, if we have to take marriage into account, we surely need to know, if a person is married. So we at least need a third attribute boolean married within the person entity and, of course, we have to set it on marriage. So implement setMarried(boolean)?

That's what I sayed when I wrote "Developers that generate setters almost always don't care about business logic". We have this use case marriage and we need to change two attributes. There is no reason to set this attributes independently. So let's just implement one method that exactly does the job and expresses that it does the job:

public void marry(String newLastName) {
  lastName = notBlank(newLastName);
  married = true;
}

Now a reader of that code directly knows the intent of that method. This is not be true for a method named setLastName. So again, no need for a setter!

OK, normally at this point the technical argument comes in: When I want to create that person in JSF, I need to have a default constructor to create an empty person and I need to have setters to fill that person. My answer to this (referencing Matthew 22 21) is: Give to JSF, what belongs to JSF and give to your domain model, what belongs to your domain model. And setters almost always don't belong to your domain model! I don't want to pollute my domain model, just because a spec like JSF sticks on a sixteen year old standard (Take a look at the release date of JavaBeans).

So be happy and create a JavaBean with getters and setters for JSF with an action method that creates the the person entity using a constructor that ensures that both first name and last name are correctly filled.

This is not nice and an overhead that seems to be just a workaround for the incompetence of the framework. In one of my next blog posts I will show a way to get rid of the usage of setters for object creation in JSF. Stay tuned.

A german version of this blog entry can be found here.