Freemarker JavaBeans Databinding

Freemarker is a template engine for java which can be used to generate text (e.g. html) using a normal POJO/java beans data model.

In one of my current projects the customer wants to see a generated html documentation in a separate view which should automatically update when the user changes elements which are part of this documentation.

To achieve this we decided to use a template engine like Freemarker which makes life much easier (than using StringBuffer). As we are using a model which supports PropertyChangeEvent (even for lists), it is easy to listen to changes on the model an the regenerate the html document and update the view.

But in this case the PropertyChangeListener needs to know which properties are actually displayed using the html template to update in the correct cases. This is even more difficult when you have a more complex model with list of lists of things. So the idea was: “Why is there no extension for freemarker which registers a PropertyChangeListener to all lists/properties which are used in the template?”

The freemarker JavaBeans Databinding

So I decided to see how hard it would be to add this feature to freemarker. First you need to decorate the BeansWrapper implementation so you can provide your own StringModel and CollectionModel implementations. The StringModel is used for entities and the method StringModel#get(String key) is called to access properties of the entity. The CollectionModel is used for lists and the method iterator() is called to access the lists items. So when the template accesses a property or a list, we want to register one propertychangelistener to it. So I created to decorator classes ListeningStringModel and ListeningCollectionModel. Finished.

freemarkerdatabinding

 

Here you can download the complete project: FreemarkerDataBinding
Feel free to take this as an example and use it in your own code.

DISCLAIMER: This is not production ready! There might be important things missing!

 

Leave a Reply

Your email address will not be published. Required fields are marked *