Freemarker 1 (Classic) was originally written by Benjamin Geer and Mike Bayer. They defined the basic syntax -- and more importantly, the philosophy -- of the tool that is carried on in Freemarker 2. Significant contributions to Freemarker Classic were made by Nicholas Cull, Holger Arendt and others.
Though Freemarker 2 (Lazarus) is virtually a complete rewrite, it is almost entirely backward compatible with Freemarker Classic. The core (parser/compiler) of Freemarker was rewritten by Jonathan Revusky using a popular parser generator tool, JavaCC. Major contributions were made by Attila Szegedi, who, besides refactoring some of the core API's for this release, is the author of the freemarker.ext.* code (a.k.a. the expose package) which previously lived in the contrib directory. Many ideas and feedback were provided by the various participants on the freemarker-devel mailing list. People who are interested in influencing (and even participating in) further Freemarker development are strongly encouraged to subscribe to the freemarker-devel mailing list.
By community consensus, the Lazarus release is under the more liberal BSD-style license. (Freemarker Classic was released under the LGPL.) Benjamin Geer, the main author of Freemarker 1, remains the copyright holder. It was decided that, since we do not currently have a juridical entity (such as the Apache Foundation) to play this role, that Benjamin Geer would continue to be the sole copyright holder. Though various people have contributed to Freemarker development, to have one individual be copyright holder makes future license changes or clarifications simpler.
Freemarker is an ongoing open source project with an active developer community. Check back for updates at http://freemarker.sourceforge.net.
Click here for the manual.
Click here for
javadoc
-generated documentation.
Note: the classes in freemarker.jar
have been compiled with
javac
with full debug information and no optimization.
This is because we want a complete stack trace on any bug reports.
You do have the option of rebuilding with optimization="on" and debug="off"
by changing the appropriate line in the ant build script.
If you are interested in an application framework that is well integrated with Freemarker, you might want to look into the Niggle Web Application Framework. Niggle leverages Freemarker for the presentation layer but gives you a lot more besides, such as easy integration with SQL/JDBC data sources as well as transparent data validation. By using Niggle, you can get your servlet development off to a running start, since you start in essence with a skeletal web application based on the model-view-controller (MVC) paradigm. Niggle-based web applications tend to be extremely robust and maintainable. (Disclosure note: Niggle was written and is maintained by the author of this document, Jonathan Revusky.)
This library is free software; you can redistribute it and/or modify it under the terms of the BSD-style license that should be included with the Freemarker distribution.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the accompanying license for more details.
This is version 2.03, released on 12 June 2002. The main reason for this release is that the last release did full page buffering of output if you set debug mode to false. It really turns out that this was not desirable and had some very bad performance implications, particularly on Windows systems. Also, some API changes were made that will be present in 2.1.x.
Since these API's are changing in 2.1, it was considered that people might as well adjust to them now.
The various
Template.process()
methods take a
java.io.Writer
rather than a
java.io.PrintWriter
. Cpnsequently, they also
throw java.io.IOException
in addition to freemarker.template.TemplateException
.
So, some java code code will definitely
have to be tweaked a bit to compile against
this release. It is fairly trivial though. Note that, also, the
transform()
method in the TemplateTransformModel
interface was changed to take a Writer rather than a PrintWriter
and also, the transform() method throws
IOException as well as TemplateException..
Aside from the potential performance problem caused by full-page-buffering in 2.02, there are no bug-fixes to speak of in this release. Nor have there been any changes in the template language syntax.
Version 2.02 was released on 3 June 2002. This was a bug-fix maintenance release in the 2.0x series. New development on FreeMarker is for the 2.1 release. The main bug-fix was an interaction between the newly introduced <break> and <return> instructions and the <compress> and <transform> instructions. Since the latter two instructions buffered output, if you broke out of a loop or returned early from a function, and the block was nested within a compress or a transformation block, the buffered output would be lost. This has been fixed.
There was a glitch where methods in a numerical context were called more than once. This would only be a significant issue if the method call, instead of just returning the value, had side effects in the application. This glitch has been fixed in 2.02
Other than a couple of extra convenience methods in the
freemarker.template.Template
class, there are no
API changes between 2.01 and 2.02.
By popular appeal, you can now write the \lt
,
\gt
operators without the initial backslash.
Thus, lt
, gt
, lte
and gte
cannot be used as top-level variable names.
Note that true
and false
cannot be
used as top-level variable names either. No use is made of these
names in this release, but these are reserved words in
the 2.1 branch, used to represent boolean true and false
respectively.
Version 2.01 was released on May Day, 2002. This version contains no changes to the template language or bugfixes, since no bugs had been reported against 2.0 final. The main improvement is in error reporting. Now exceptions are much more informative since they come with complete line number and column information.
The only API change between 2.0 and 2.01 was the elimination of the CacheListener/CacheEvent API. Now, if the updating of a template file fails, the exception is thrown back to the caller to handle. If you want logging to occur when a template file is updated successfully, you can override the logFileUpdate() method in FileTemplateCache.
FreeMarker 2.0 final was released on 18 April 2002. The changes with respect to the previous release, 2.0 RC3 are fairly minor.
myString?web_safe
to convert a string to its "web-safe" equivalent, where problematic
characters such as '<' are converted to <.getAsString()
method in the
TemplateScalarModel
interface now
takes a java.util.Locale
as a parameter.
For the most part, this is a hook for later use. In the
default implementation, SimpleScalar
, this
parameter is unused. If you are implementing this interface
yourself, your implementation may ignore the parameter.
However, it will be appealing for certain implementations.
FileTemplateCache
have
changed. If you are using an absolute directory on the file system
as the location of your templates, you need to pass in an
instance of java.io.File
to indicate the location.
If you use the constructors that take a string, this is taken
to mean relative to the classloader classpath.The ant build script build.xml now contains a target that builds a .war file containing the Hello, World example and the guestbook. It builds a fmexamples.war. For example, if you are using Tomcat in its out-of-the-box configuration, you would place this under <TOMCAT_HOME>/webapps and then you would use http://localhost:8080/fmexamples/servlet/hello and http://localhost:8080/fmexamples/servlet/guestbook for the Hello, World and Guestbook examples respectively.
FreeMarker 2.0 RC3 was released on 11 April 2002. This release was primarily devoted to fixing bugs that were reported in RC2.
<include "included.html" ; parsed="n" >You can also indicate the encoding of the included file this way:
<include "included.html" ; encoding="ISO-8859-5">
FreeMarker 2.0 RC 2 was released on 4 April 2002. Here is a summary of changes wrt to the first release.
myList?size
provides the number of elements
in a list. Similarly, myString?length
provides the
length of a string, myString?upper_case
puts
the string all in capital letters, and myHash?keys
provides a
sequence containing the keys in the hash. All of the available built-ins
are documented here.
foreach
or
a list
block -- the current count in the loop
is available as the special variable index_count
.
where index is the name of the variable in the iteration.
A boolean variable called index_has_next
is also defined that indicates whether there are any more items in the iteration
after this one. Note that the index starts at zero,
so you will often be adding one to it in practice.
<break>
directive can now be used to break out
of a <foreach...>
or a <list...>
loop. (Prior to this version, it only worked within a switch-case block.)
There is a new directive called <stop>
that, when
encountered, simply halts processing of the template. This can be
useful for debugging purposes.
myMethod(1?int)
or myMethod(1?long)
. This is unnecessary if
there is only one method of the given name.
myList[0..3]
will return items 0 through 3 of the list in
question. Or, for example, you could get all the elements of the list
except for the first and last ones via:
myList[1..(myList?size-2)]
myString[0..5]
TemplateSequenceModel
interface now has
a size()
method for getting the number
of elements in the sequence in question.TemplateModelIterator
interface now has
a hasNext()
method.freemarker.template.SimpleSequence
and
freemarker.template.SimpleHash
are now unsynchronized.
If you need the methods to be synchronized, you can get a synchronized
wrapper via the synchronizedWrapper()
in either class.
freemarker.utility.ExtendedList
and freemarker.utility.ExtendedHash
classes were
removed, since all of the extra keys that it defined are now
available using the appropriate '?' built-in operation, i.e. myHash?keys
or myList?size
or myList?last
.
Template.setClassicCompatibility(true)
.
What this does is that it allows scalars to be treated as a single-item list
in a list directive. Also, it allows somewhat more looseness about types.
In FreeMarker 1.x, <if x=="1">
and <if x==1>
were in fact equivalent. This meant that legacy templates might tend to be slack about this. If
classic compatibility is not set, an attempt to compare the string "1" with
the number 1 will result in an exception being thrown. (Note that
it is preferable to get your templates working without the backward compatibility flag,
since it usually will require only minor changes. However, for people with a lot of
templates and no time to check over them, this flag may be of use.)
The first public release of Freemarker 2.0 was on 18 March 2002. Here is a summary of the changes in the Lazarus release, with respect to the last stable release of Freemarker Classic.
lhs + rhs
is non-numerical,
we revert to interpreting this as string concatenation.
Thus, in Freemarker 2, 2+2 evaluates to the number 4,
while any of "2"+2 or 2+"2" or "2"+"2" evaluate to the string "22".
In Freemarker Classic, rather embarassingly, all of the above,
including 2+2, evaluated to the string "22". An attempt
to use any other arithmetic operator besides the + with non-numerical
operands will cause an exception to be thrown.
#{....}
syntax. If the expression
within the curly parentheses does not evaluate to a numerical value, an
exception is thrown. The older ${....} syntax can evaluate to either
a number or a string. In general, if, for logical reasons, the output
must be numerical, it is preferable to use the #{...} syntax,
since it adds an extra sanity check. Note that if, by some miracle,
the character sequence "#{" occurs in your template, you will have
to use a workaround to prevent problems. (The
<noparse> directive is one possibility.)
#{foo + bar ; m3M6}(Note that the above is something of a stopgap measure. Future releases will move towards supporting fully internationalization and localization of number and currency formatting.
<foreach year in 1990..2001> blah blah in the year ${year} blah </foreach>The left hand and right hand sides of the .. operator must be numerical, or an exception is thrown. They also need not be literal numbers, but can be more complex expressions that evaluate to a numerical scalar value. Note that it is also possible to write a range that descends in value:
<foreach year in 2001..1990> blah blah in the year ${year} blah blah </foreach>
TemplateNumberModel
interface and the
SimpleNumber
implementation were added
to support exposing numerical values.TemplateListModel
API in Freemarker Classic
had some design problems -- particularly in terms of supporting
thread-safe code. It has been deprecated in favor of the following
API's: TemplateCollectionModel
and TemplateSequenceModel
.
The SimpleList
class was refactored to implement the
above interfaces (and paradoxically, does not implement the TemplateListModel
interface.) Code that uses the deprecated TemplateListModel
should be refactored.freemarker.template.utility.Addition
etcetera that
existed as workarounds for the lack of numerical operations
in Freemarker. Those have been removed and will probably
not be missed.
SimpleScalar
object
was mutable, it had a setValue
method. This was
fairly obviously a design mistake. Any code that relied
on this must be refactored. Note that in this release,
both SimpleScalar
and the newly
introduced SimpleNumber
are both immutable and final.
<assign x = 1, y = price*items, message="foo">
<assign y=[x]> and then... <list y as item>...</list>
NOTA BENE:
Despite the changes delineated above, the Lazarus release
is almost entirely backward-compatible with Freemarker Classic.
We believe that most existing code and templates that work
under Freemarker Classic will continue working under Lazarus, with
at most minimal changes. In practice, the most common cases where legacy
template code is broken will be where assumptions
were made about numbers and strings being equivalent. Note that in Freemarker 2,
2 + 2 does not result in "22". The String "1" and the number 1 are entirely
different animals and thus, any code will be broken if it
relies on the boolean expression ("1"==1) being true.
There is a "classic compatibility mode" that can be set via:
Template.setClassCompatibility()
that can be set
so that Lazarus emulates some of the quirky behavior of FreeMarker Classic.
However, any code that relied on the above "features" of Freemarker
classic really should be reworked. You are less likely
to run into the other incompatibilities that are listed above.
If you come across any other anomalies, please do
tell us about them.
Document last updated 12 June 2002 by Jonathan Revusky