Using decorators to transform data

ID Email Status Date Money
35641 voluptua-dolor@rebum.com DIAM 10/29/09 $ 999.00
47898 aliquyam-erat@invidunt.com SEA 08/25/10 $ 2,863.00
47006 accusam-tempor@clita.com LOREM 11/19/09 $ 2,961.00
97968 no-sanctus@et.com EIRMOD 02/13/09 $ 2,420.00
497 sadipscing-accusam@nonumy.com DOLOR 11/06/09 $ 6,142.00
3187 elitr-At@nonumy.com ACCUSAM 06/30/10 $ 6,452.00
74501 Stet-Stet@eos.com DIAM 01/15/10 $ 3,998.00
32216 eos-tempor@eirmod.com INVIDUNT 06/24/09 $ 4,604.00
69320 Lorem-est@nonumy.com DIAM 08/20/09 $ 7,688.00
16701 Lorem-dolor@sed.com DOLORES 07/16/10 $ 1,851.00

A "decorator" is a design pattern where one object provides a layer of functionality by wrapping or "decorating" another object.

Let's assume you have list of business objects that you want to display, and the objects contain properties that don't return native Strings, and you want control over how they get displayed in the list (for example, Dates, money, numbers, etc...). It would be bad form to put this type of formatting code inside your business objects, so instead create a Decorator that formats the data according to your needs.

Notice the following 4 key things (and refer to the TableDecorator javadoc for some of the other details).

  • The Wrapper class must be a subclass of TableDecorator. There is various bootstrapping and API methods that are called inside the TableDecorator class and your class must subclass it for things to work properly (you will get a JspException if your class does not subclass it).
  • Be smart and create your formatters just once in the constructor method - performance will be a lot better...
  • Notice how the getDate() and getMoney() methods overload the return value of your business object contained in the List. They use the TableDecorator.getCurrentRowObject() method to get a handle to the underlying business object, and then format it accordingly.
  • We do not have to overload each of the other business object properties (like getID, getEmail, etc...). The decorator class is called first, but if it doesn't implement the method for the property called, then the underlying business class is called.

The way this works is that a single decorator object is created right before the table tag starts iterating through your List, before it starts processing a particular row, it gives the object for that row to the decorator, then as the various properties getXXX() methods - the decorator will be called first and if the decorator doesn't implement the given property, the method will be called on the original object in your List.

Column Decorators

You can specify decorators that work on individual columns, this would allow you to come up with data specific formatters, and just reuse them rather then coming up with a custom decorator for each table that you want to show a formatted date for. This kind of decorator must implement the ColumnDecorator interface.

ID Email Status Date
35641 voluptua-dolor@rebum.com DIAM 10/29/2009 21:15:06
47898 aliquyam-erat@invidunt.com SEA 08/25/2010 21:15:06
47006 accusam-tempor@clita.com LOREM 11/19/2009 21:15:06
97968 no-sanctus@et.com EIRMOD 02/13/2009 21:15:06
497 sadipscing-accusam@nonumy.com DOLOR 11/06/2009 21:15:06
3187 elitr-At@nonumy.com ACCUSAM 06/30/2010 21:15:06
74501 Stet-Stet@eos.com DIAM 01/15/2010 21:15:06
32216 eos-tempor@eirmod.com INVIDUNT 06/24/2009 21:15:06
69320 Lorem-est@nonumy.com DIAM 08/20/2009 21:15:06
16701 Lorem-dolor@sed.com DOLORES 07/16/2010 21:15:06