FreeMarkerBean Release 2

The FreeMarkerBean provides a JavaBean(TM) interface to the powerful FreeMarker 2.2.4 template engine.

The main goal of this implementation was to allow DigiSlice AppComposer, a component-assembly tool, to easily access FreeMarker. Packaging the FreeMarker technology as a JavaBean allows AppComposer users to easily build FreeMarker data models and process them against FreeMarker templates to create dynamic output. AppComposer can access arbitrary classes, so FreeMarker classes could be invoked directly to achieve the same ends, but the JavaBean packaging makes the user interface much clearer.

Already Familiar With FreeMarker?

If you're already using FreeMarker, you'll see that the interface to the FreeMarkerBean is a simple combination of commonly accessed Template and Configuration methods. Using it should be fairly intuitive once you read the Short Version below.

Note that this is an initial implementation. We've verified that templates can be successfully processed, but we aren't FreeMarker power-users, so there may be common FreeMarker operations which aren't supported either because they don't work, or just because we haven't provided a rich enough API to access them. We understand that there are probably some "things that are missing," but we won't know what they are until you tell us.

Note also that our primary interest is in using FreeMarker in a servlet environment -- that is, we're assuming that the templates being processed are going to be written out as a web page. We're interested in supporting other uses, but processing web page templates is the main goal.

As background for those not familiar with AppComposer, it includes a JSPTemplate JavaBean. It also includes a suite of components that allow web pages to be built tag-by-tag, but the "best practices" recommendation is to use JSP's as templates, and use the AppComposer JSP Tag Library tags in conjunction with the JSPTemplate component to create dynamic web pages. We'd like the FreeMarkerBean to eventually provide an alternate template technology of equivalent power and flexibility.

What Is FreeMarker?

If you've never seen FreeMarker, it's a template engine with a straight-forward syntax which is designed to combine a template file with a data model to produce dynamic output. See the FreeMarker web site for more details.

How To Use The FreeMarkerBean (in AppComposer), Short Version

  1. Create a new servlet capsule
  2. Add a FreeMarkerBean to the capsule
  3. Add the ServletGet saved group to the capsule as a child of the FreeMarkerBean  
  4. Set the TemplatePath property of the FreeMarkerBean to the name of the appropriate template file

     
  5. If the page is to have any dynamic data, call addData(), addDataMap(), or setDataRoot() on the FreeMarkerBean to provide appropriately named key/data pairs for the template. (This also must execute before the sendDocument Action.) Here is the SimpleFMExample adding a data item with the "time" key:

     
  6. That's it! The sendDocument Action in the ServletGet saved group calls the print() method of the FreeMarkerBean, and directs the output to the writer from the ServletResponse.
    Of course, exception handling should be added.

Data Model

The FreeMarkerBean offers two options for building up the data model for the template:

  1. Manipulate the bean's default (empty) data model using addData(String key, Object data) and addDataMap(Map data) (and, possibly removeData(String key), clearData(), and getData(String key)), or;
  2. Create your own data model and call setDataRoot(Map map) to replace the bean's default data model.

Configuration

The FreeMarkerBean assumes that you will want to use the default FreeMarker Configuration accessed via Configuration.getDefaultConfiguration().

However, if you need more control over Configuration settings, you can create your own Configuration, or modify the default one. If you create your own Configuration, and you don't set it as the default Configuration, you can tell the FreeMarkerBean to use it by calling useConfiguration(Configuration useConfig).

Templates

The FreeMarkerBean has a TemplatePath property. This property, in conjunction with the Configuration, is used to find the template file. By default (using the default configuration), the template location path is relative to the web application, and should not begin with a slash. If you use one of the other mechanisms mentioned above to manipulate the Configuration to specify a location from which templates will be loaded, the template path will be relative to that location instead.

The path specified in the TemplatePath property is relative to the location specified as the template location in the Configuration. The path should not begin with a slash, and the directory separator character is forward-slash ('/'), regardless of the platform. In AppComposer, you need to make sure to add your templates or the directory containing your templates to the project so that capsules in the project can access the templates.

FreeMarker templates are often saved with .ftl extensions, but there is no requirement for that. You can save them with .html if your HTML editor is happier with that, or with any or no extension at all.

Other Details

The FreeMarkerBean.jar contains the entire FreeMarker 2.2.4 jar, and the FreeMarkerBean class. This packaging was chosen because the typical AppComposer user will not already have the FreeMarker classes on their class path.

Examples

Some example AppComposer servlets that use the FreeMarkerBean are included, since examining an example can be worth a thousand words of documentation.

SimpleFMExample.zac

This capsule is in the FMexamples.zap project, and it uses the simple.ftl file in the templates directory.

This servlet displays the current time using the FreeMarker grammar: The time is: ${time}

The servlet gets the time from a Clock bean and puts the time string into the data model for the template with the "time" key.

To run this example in AppComposer, open the examples/FreeMarkerExamples/simpleexamples/FMexamples.zap project file, double-click the SimpleFMExample.zac capsule in the project to open it, then click the Run button.

SillyHouse.zac

This capsule is also in the FMexamples.zap project, and it uses five template files in the templates/silly directory.

This servlet allows the user to play a silly game where they travel from room to room in a house until they get hungry. When they get hungry, they are supposed to visit the kitchen and make a sandwich.

The data model for the templates in this game is still very simple. The only things in the model are the current turn number and a list of message strings. The servlet capsule is a bit more complex. It keeps track of the turn number and hunger status using session data, and it has a bunch of behaviors to test for hunger and add messages, handle sandwich eating, etc. This is a bit more realistic example, although all the logic resides in the capsule -- there is no JavaBean that tracks turns, hunger, and sandwich eating.

To run this example in AppComposer, open the examples/FreeMarkerExamples/simpleexamples/FMexamples.zap project file, double-click the SillyHouse.zac capsule in the project to open it, then click the Run button.

FMWebAppEx2.zap

This is a web application which provides a guestbook that visitors to a web site can "sign" by leaving messages. It is implemented with three servlet capsules:

This example is based on the FreeMarker Example Web Application 2. The template files (add.ftl, form.ftl, etc.) are unchanged. However, the logic in this example is implemented using three AppComposer servlet capsules, where the original example included a single controller servlet implemented in Java code. Also, GuestbookEntry and GuestbookMgr JavaBeans have been created to handle the logic of maintaining and persisting the guestbook in the HSQL database that is included with AppComposer.

To run this example in AppComposer, open the examples/FreeMarkerExamples/webappexample2/FMWebAppEx2.zap project file, double-click the GuestbookMain.zac capsule in the project to open it, then click the Run button.