You have seen how to build a data-model in the Getting Started using the standard
Java classes (Map
, String
,
etc.). Internally, the variables available in the template are Java
objects that implement the
freemarker.template.TemplateModel
interface. But
you could use standard Java collections as variables in your
data-model, because these were replaced with the appropriate
TemplateModel
instances behind the scenes. This
facility is called object wrapping.
The object wrapping facility can convert any kind
of object transparently to the instances of classes that implement
TemplateModel
interface. This makes it possible,
for example, to access java.sql.ResultSet
as
sequence variable in templates, or to access
javax.servlet.ServletRequest
objects as a hash
variable that contains the request attributes, or even to traverse XML
documents as FTL variables (see here). To
wrap (convert) these objects, however, you need to plug the proper
ObjectWrapper
implementation (possibly your custom
implementation); this will be discussed later. The point for now
is that any object that you want to access from the templates, sooner
or later must be converted to an object that implements
TemplateModel
interface. So first you should
familiarize yourself with writing of TemplateModel
implementations.
There is roughly one
freemarker.template.TemplateModel
descendant
interface corresponding to each basic type of variable
(TemplateHashModel
for hashes,
TemplateSequenceModel
sequences,
TemplateNumberModel
for numbers, etc.). For
example, if you want to expose a java.sql.ResultSet
as a sequence for the templates, then you have to write a
TemplateSequenceModel
implementation that can read
java.sql.ResultSet
-s. We used to say on this, that
you wrap the
java.sql.ResultSet
with your
TemplateModel
implementation, as basically you just
encapsulate the java.sql.ResultSet
to provide
access to it with the common TemplateSequenceModel
interface. Note that a class can implement multiple
TemplateModel
interfaces; this is why FTL variables
can have multiple types (see: Template Author's Guide/Values, Types/Basics)
Note that a trivial implementation of these interfaces is
provided with the freemarker.template
package. For
example, to convert a String
to FTL string
variable, you can use SimpleScalar
, to convert a
java.util.Map
to FTL hash variable, you can use
SimpleHash
, etc.
An easy way to try your own TemplateModel
implementation, is to create an instance of that, and drop it directly
into the data-model (as put
it into the root hash).
The object wrapper will expose it untouched for the template, as it
already implements TemplateModel
, so no conversion
(wrapping) needed. (This trick is also useful in cases when you do not
want the object wrapper to try to wrap (convert) a certain
object.)