The best Markup Builder I could build in Java

Using Groovy MarkupBuilders spoiled me for other ways to create HTML pages from code. Others think the same. But in some organizations you have to use Java and can't use Groovy - at least when you can't sneak it in.

So I tinkered around in Java to see what's the best MarkupBuilder I can write with Java. Using DSLs and Fluent Interfaces (times(5).loop), I came up with a nice solution. It's not Groovy, but it works.

   Page page = page(
      html(
        body(
          // A comment
          h1("Name games"),
          p("Hello ${coolName}, and hello", "id:${id}"),
          ul(
            new Loop("stefanie", "${name}") {
              protected Element each(String item) {
                return li(item);
              }
            }),
          loop("[${number}] ", "number", 1, 2, 3),
          text("..."),
          box("Warning private!"),
          p("Are you dynamic?"),
          // Some dynamic content
          new Action() {
            protected String with(Context context) {
              return "I'm dynamic, " + context.get("name") + ".";
            }
          }
        )
      )
    );

There are some tricks to make it better than most such Markup Builders in Java. I tried to use ideas from building DSLs in Java. Those are using static imports and varargs. The body, html and other elements are static imports from a MarkupBuilder class.

  public static Element body(String body) {
    return new Element("body", body);
  }
  public static Element body(Element... elements) {
    return new Element("body", elements);
  }
  ...

The varargs helps with adding a variable number of childs to an element:

h1(
   p("One"),
   p("Two"),
   p("Three")
);

Another problem is how to put object values into the generated markup. String concatenation leads to noisy code

  "Hello " + name + "!"

so I decided to use a expression language where the Java unified expression language comes to mind. There is an open source version available called JUEL. Now I can use

  "Hello ${name}!"

Attributes are also treated as expressions and seperated by commas, their names and values seperated with a colon.

   p("Hello ${coolName}, and hello", "id:${id}, class:list"),

Loop and Action classes allow for dynamic content.

          
          ul(
            new Loop("stefanie", "${name}") {
              protected Element each(String item) {
                return li(item);
              }
           }),

I've used the template design pattern for this, again with expressions, in a way Spring provides JDBC templates. Another nice idea is with static methods it's also easy to develop custom, semantic tags, so the developer doesn't need to know or see the actual HTML markup which is created. For example I used a box "tag" which translates to

public static Element box(String text) {
  return div(
                 p(text)
           );
}

Closures in Java 7 will make it much easier to write a MarkupBuilder. The Action and Loop inner classes will go away and the code will be more Groovy like. When they add syntactic sugar to create maps I can drop the "name:value, name:${value}" style for attributes and move to [ "name" : value, "name": value ] instead, which doesn't need the EL to work. With some small things to add the MarkupBuilder can be used for JSON or XML.

I'm interested and open to all techniques and ideas to improve the markup builder.

Thanks for listening.

People don’t get the difference between business and UI logic

People most of the time use business logic in their templates, be them JSP, Velocity or Rails. They confuse business logic and UI logic. Those are two different things. I always found it very useful to make UI logic explicit and only have UI logic in my JSPs or templates. So when using IF JSTL tags only test for UI logic not business logic. The examples are for JSP, but nevertheless are valid for other templating engines like Rails or Velocity. Where is the difference between UI and business logic?

<c:if test="${showMenu}">
// show menu
</c:if>

and

<c:if test="${user.loggedIn && user.bookedProducts}">
// show menu
</c:if>

The first example contains only UI logic, the second one contains business logic and should be avoided. With the second version your templating code is depending on your business layer. This makes it hard to refactor or reuse. Somewhere in the controller or an adapter it's best to translate your business logic to UI logic

 boolean showMenu = user.loggedIn() && user.bookedProducts();

Such a separation makes refactoring and reuse easier and encapsulates the rules how business logic maps to UI logic in one place. You could even write the mapper with rule engines. It also eases the understanding of the template code. Often when using business logic in their templates, people use copy & paste to reuse the logic. So the user.loggedIn code gets distributed over lots of templates. If the logic changes so the menu should only be show for paid users, you need to modify all templates where the logic is used.

<c:if test="${user.loggedIn && user.bookedProducts && user.hasPaid}">
...
</c:if>

(I know about components, sub-templates etc. but people nevertheless use cut & paste for reuse. So make sure they cut&paste the right things)

When externalizing business-to-UI logic into seperate classes, it's also much easier to test.

public class UserUIState {
 private User user;
 public UserUIState(User user) {
    this.user = user;
  }
 public boolean showMenu() {
   return user.loggedIn() && user.bookedProducts();
 }
}

can be easily tested from a Unit test.

  User user = with().isLoggedIn().addProduct("Intellij IDEA").create();
  UserUIState state = new UserUIState(user);
  assertThat( state.showMenu(), is(true));

The test uses fluent interfaces to create a user and a pseudo Hamcrest DSL to specify assertions. The assertions would be nicer written as specs with easyb.

Another aspect of templating is the power of the templating engine. Turing completeness is not a good thing for templating as the power introduces bugs. Less power leads to less bugs. Examples for engines who make this a virtue are String Template and RIFE. The same goes for variables. Never set variables in templates. Never modify state in templates. The best paper on this topic is Terence Parrs "Enforcing Strict Model-View Separation in Template Engines".

And of course never use Scriptlets in your JSP or other templating code, the main reason that the developer has to manage two hierarchies in her head. The <html> on one side and the Java { ... } hierarchie on the other.

<% if (loggendIn) { %>
<p>Logged in<p>
<% } %>

With larger pages this leads to bugs. With only one <html> hierarchie, your IDE is able to verify the hierarchie at edit-time which prevents invalid HTML.

You can enfore these rules with code reviews or automatic style and architecture checkers. Probably best to use both to reduce your bug count and enable reusability.

Thanks for listening.

Update: Gavin King got me wrong. Reading simple attributes like "test=${user.loggedIn}" doesn't contain a lot of "logic" so it's no must to encapsulate the logic and it leads to unnecessarilly complex code. YAGNI. But "test=${user.loggedIn && user.hasBookProducts && sales.hasPromotion(user)}" does contain logic which should be encapsulated and tested. Perhaps I'm a stronger believer in TDD than Gavin. I wanted to stress that there is a difference between UI and business logic and a lot of people don't see the difference.

@Getter annotation?

With all the innovation in annotations, see Web Beans or Google Guice, just a saturday morning idea: Why not drop the annoying get* convention and replace it with some annotations? The API wouldn't be as short, but the usage of a getter looks nicer and more fluent. And of course the IDE could hide the @Getter annotation, just as it hides the imports.

@Getter
public Context context() {
	return context;
}

public Context getContext() {
	return context;
}

Beautiful Java: Reflection and the BeanCopier

When reading about reflection on the beautiful code website I thought about solving some problems with reflection and finding new solutions to old problems. One problem is boring code when writing a copy constructor. A copy constructor is a constructor which takes another object and copies it's attributes. This is often useful when copying objects or moving objects to different system layers. One example would look like this:

public class Employee {
  public Employee(Employee other) {
      this.name = other.name;
  }
}

There are some pitfalls, especially that you only create shallow copies. And there is always clone() and Serializable, which can also be used to create deep copies without such pitfalls. JBoss provides a fast implementation of this technique. But often copy constructors are quite useful if you're careful and know what you do. I recently had a discussion on how to support domain objects in different parts of a system. One part might call an entity Employee, another part might call it Person. To make them talk together you can either create a composite, an adapter, a wrapper or use a copy constructor (or find a different solution). In such a case a shallow copy is all you want, because the new object should have the same "identity" as the first and not be a copy.

public class Employee {
  public Employee(Person person) {
      this.lastName = person.getLastName();
      this.name= person.getFirstName();
  }
}

This should be easier to implement. Copying bean attributes for large objects isn't much fun, leads to long constructors and unmaintanable code. What about changes in Person? New attributes? So I tinkered with Java reflection and ended with this:

 public Employee(Person person) {
    BeanCopier copier = new BeanCopier();
    copier.copy(person, this, "name:firstName", "age:");
 }

I've written a BeanCopier which can - well you guessed it - copy beans. The syntax is easy to learn. A BeanCopier has a copy method which takes a source, a copy and the attributes which should be specially handled. By default all attributes which have the same name and type in source and copy are copied. But if they have different names, like name and firstName, you need to specify "name:firstName". If a property shouldn't be copied, you can specify "property:" without a target attribute.

The copy method looks like this (the generics are not needed but I was also tinkering with caching where it was quite handy):

public <T, U>void copy(U source, T destination, String... attributes) {
  if (destination.getClass().getName().equals(source.getClass().getName())) {
    // copy all fields
  } else {
    // copy all bean properties
    try {
      BeanInfo sourceInfo = Introspector.getBeanInfo(source.getClass());
      PropertyDescriptor[] sourceDescriptors = sourceInfo.getPropertyDescriptors();
      for (PropertyDescriptor descriptor : sourceDescriptors) {
        String name = descriptor.getName();
        if (!"class".equals(name)) {
          String attribute = this.find(attributes, name);
          if (attribute == null) {
            copyAttribute(source, destination, name);
          } else if ((attribute.indexOf(':') >= 0) && !attribute.endsWith(":")) {
            int colonIndex = attribute.indexOf(':');
            String sourceName = attribute.substring(0, colonIndex);
            String copyName = attribute.substring(colonIndex + 1);
            copyAttribute(source, destination, sourceName, copyName);
          }
        }
      }
    } catch (IntrospectionException e) {
      e.printStackTrace();
    }
  }
}

and the copyAttribute method:

private void copyAttribute(Object source,
      Object copy,
      String sourceName,
      String copyName) {

  PropertyDescriptor writer;
  PropertyDescriptor reader;
  try {
    writer = new PropertyDescriptor(copyName, copy.getClass());
    reader = new PropertyDescriptor(sourceName, source.getClass());

    Object value = reader.getReadMethod().invoke(source);
    Class sourceType = reader.getPropertyType();
    Class destionationType = writer.getPropertyType();
    if (sourceType.getName().equals(destionationType.getName())) {
      writer.getWriteMethod().invoke(copy, value);
    }
}

The code is rough but works. The type test can be improved to work with super types.BeanCopier can be used outside of constructors, often a wise choice. And be careful with "copying" other objects, you might only create a shallow copy.

Of course, I could have taken a look at commons BeanUtils, but isn't it much more fun to tinker and find a nice solution yourself sometimes?

Thanks for listening.