Download: Latest Version of Niggle (1.1 pre14) (If you are starting with Niggle, get this one.) Last Niggle 1.0.x release (1.06) Forum example (requires Niggle 1.1) Read More: Niggle Home Niggle Design Goals History and current status Generated Javadoc Configuring XML-based Metadata Subclassing ServletInteraction Other Links: Niggle Project Page on Sourceforge Subscribe to Niggle mailing lists |
PreambleUsing some kind of page template solution is really an absolute necessity in serious web application development, since outputting HTML via println() statements in your java code is really not a maintainable practice. I don't think I should launch into a sermon as to why this is so. If you've been there, done that, then you already know this, and if you haven't, then it is wise to believe those who have gone there before you! The Niggle framework currently gives you the choice of three popular open-source template engines: Freemarker, WebMacro, and Velocity. As you may know from reading the history of the Niggle project, Niggle began by leveraging Freemarker. Support for WebMacro and Velocity was introduced fairly recently. What Niggle offers above and beyond any of these template solutions alone is a prebuilt solution for modeling your application's persistent data externally, as well as exposing the data to a page template and reading data from an HTML form. By separating out the persistence layer as well as presentation, Niggle offers the skeletal basis for developing web applications that roughly follow the much-vaunted MVC (model-view-controller) pattern. (And if you don't know quite what that is, well, just think of it as a synonym for GOODtm) Configuring your Template EngineIn your deployment descriptor (that's a fancy term that means the WEB-INF/web.xml file) you can configure a servlet initialization parameter called PAGE_FACTORY_CLASS. If you intend to use Freemarker, this does not need to be set, since Freemarker is the default. If you intend to use WebMacro or Velocity, you do have to set this parameter. Within your servlet configuration, you would need something like: <init-param> <param-name>PAGE_FACTORY_CLASS</param-name> <param-value>webmacro</param-value> </init-param>
Note that "webmacro" above is a convenient shorthand that the code that
processes the parameters understands to mean
By default, it will be assumed that you wish to load templates relative to the classloader's CLASSPATH. This is the scheme that will allow you to put all of your .class files and associated resources in a .war archive. (This is also GOODTM) However, if you want your templates loaded relative to an absolute location on the file system, you can specify the init parameter RESOURCE_BASE, which specifies a location from which to load the templates. If this is an absolute path, this is assumed to be on the file system. If it is a relative path, then it is assumed to be relative to the classloader. For final deployment, it is far better not to specify an absolute path here, since a relative path (or nothing specified at all) means that your webapp will simply obtain the template files relative to the classloader. This is the most robust, portable solution. However, in a development stage, it may be useful to specify an absolute path here, which points to where your templates are on the file system. Differences between using Freemarker and WebMacro or VelocityUnder the hood, Freemarker and WebMacro/Velocity actually take very different approaches to exposing objects to a page template. The Freemarker library defines three basic interfaces for objects that will be exposed to a page. Any object exposed to a page must implement at least one of these three interfaces:
The freemarker engine parses your page template and compiles it into a tree. When it finally outputs the page, it traverses the tree and fills in the elements of the tree based on the variables in your data model. For example, if you have the variable ${foo.bar} in your page template, the template engine expects your root data model to contain a variable called "foo" and it requires that this variable be interpretable as a hash variable. From the engine's point of view, this means that the object implements the TemplateHashModel interface.
Of course, you may have noticed that the Niggle example code makes no reference
to TemplateHashModel or any of these interfaces. Also, you can expose a data
record onto a freemarker template directly and it gets interpreted as a hash,
even though the org.oreodata.Record interface does not inherit from
freemarker.template.TemplateHashModel. The reason this works is that Niggle
transparently creates a wrapper object that does implement the right
interface. In fact, the wrapper object that is used by default is
By contrast, both WebMacro and Velocity are much more based on java's introspection capabilities. If you have the webmacro variable $foo.bar in a page, WebMacro and Velocity (like Freemarker does) assume that you exposed a variable called "foo" to your root context. However, it takes the reflective lookup approach to deducing what the "bar" subvariable is. It will look for either a getBar() method (javabeans style) or a get(Object obj) method to which it can pass the string "bar" in that order. In fact, one thing that WebMacro and Velocity allow for that Freemarker simply does not, is arbitrary calls to public methods by name from a page template. I will not hide from you that I consider this to be rather dangerous. I am still not absolutely sure that this is evil by nature, or merely has the potential for evil. Still, it is possible that, ultimately, this capability is intrinsically evil, in the same way as the rings of power in the Tolkein books. Now, even given that, it is surely not as evil as the ability to embed arbitrary java code in a JSP template. But certainly, it does create the potential for people working on the page design layer to rely on the existence of arbitrary methods in your core java objects. This can create an undesirable coupling, where, whenever you want to refactor your java code, you have to verify whether a method that you wish to eliminate or rename is actually used somehow in a page template. And in fact, given the ability for variable aliasing that page templates provide, it could be fairly difficult to know for sure whether a method is being used. SummaryYou can use either Freemarker, WebMacro or Velocity in conjunction with Niggle. Freemarker is the default; it works well and the freemarker bridge code has been subject to much more usage and testing. Broadly speaking, you can use either one almost indistinctly as a java programmer, since they are wrapped up in a higher level API. The biggest difference will naturally be at the page template level, since the template languages differ significantly. Probably, the biggest practical consideration in choosing which one to use will be whether the people working at the page design level already have experience with one or the other, or have a stated preference. If there is no stated preference, typically because your designers have used neither one, you might as well go with the default, which is Freemarker. In the above, I point out a couple of basic differences. First of all, if you use the Freemarker bridge code, you have the possibility of implementing your own custom subclass of RecordWrapper. This can give you an extra degree of freedom when it comes to migrating your java code, without having to change any template code. On the other hand, the reflection-based approach of WebMacro or Velocity is appealing in certain ways, since it gives you access to arbitrary java methods from your page template. Though, you will note that I express my reservations about in that above. Since it is not terribly difficult to write the bridge code that allows Niggle to work with other page template solutions, I anticipate that Niggle will at some point offer a greater choice of presentation solutions than it does now. Probably something that uses XML/XSL as well as a solution that uses JSP taglibs. Since XSL and JSP are standard, "approved" ways of doing things, there will likely be a fair bit of third-party tool support coming on line. Additional NoteSince writing the text above, I have become the maintainer and lead developer of the FreeMarker project. I suppose that people would infer that, in terms of tight integration with Niggle, that FreeMarker will receive a kind of favoritism. The above inference is correct. There has now been a release of FreeMarker version 2.1. The 2.1 final is about a week away. I will make no bones about the fact that I consider this to be a far superior solution to both Velocity and WebMacro at this juncture. Also, one should take into account that, since FreeMarker is being maintained by me as well, in all likelihood, the integration of Niggle and FreeMarker will be superior to the integration with Velocity or WebMacro.I have deprecated Velocity support (though it still works and is present) because the current distribution includes a Velocity->FreeMarker template converter. |
|
This is a first draft of a document explaining Niggle's template engine support. If you note any inaccuracies in this document, or have any suggestions for improvement, please write me! I do not document the syntax of the template languages here. At some point soon, I anticipate including a quick-start crib sheet that explains the template language syntax of Freemarker, WebMacro and Velocity, and their usage with Niggle. Currently, for this information, please refer to the respective websites: freemarker.sourceforge.net, www.webmacro.org, and jakarta.apache.org/velocity.
Jonathan Revusky Last modified: 10 May 2002