blob: d201a7fadfd0e37be8f0f85e0eb9b6d23146b902 [file] [log] [blame]
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<faq title="The Old FreeMarker FAQ" adminMailTo="run2000@users.sourceforge.net" adminName="Nicholas Cull">
<preface/>
<topicgroup name="Assembling template data models">
<topic id="basic" name="Can you give me some examples showing how to assemble a template data model?">
<p>The easiest way is to use <tt>SimpleHash</tt>, <tt>SimpleList</tt>, and
<tt>SimpleScalar</tt>. For example, suppose you want to be able to use a
variable called <tt>foo.bar.baz.bing</tt> in your template. You could make a
structure of nested <tt>SimpleHash</tt> objects like this: </p>
<pre>SimpleHash foo = new SimpleHash();
SimpleHash bar = new SimpleHash();
SimpleHash baz = new SimpleHash();
SimpleScalar bing = new SimpleScalar("value of bing");
baz.put("bing", bing);
bar.put("baz", baz);
foo.put("bar", bar);
modelRoot.put("foo", foo);
</pre>
<p>What about nested lists? Suppose you wanted to write something like this in a
template: </p>
<pre>&lt;list list1 as list2&gt;
&lt;list list2 as list3&gt;
&lt;list list3 as element&gt;
${element}&lt;br&gt;
&lt;/list&gt;
&lt;/list&gt;
&lt;/list&gt;
</pre>
<p>You could make nested <tt>SimpleList</tt>s like this: </p>
<pre>SimpleList list1 = new SimpleList();
for (int i = 0; i &lt; 3; i++) {
SimpleList list2 = new SimpleList();
for (int j = 0; j &lt; 3; j++) {
SimpleList list3 = new SimpleList();
for (int k = 0; k &lt; 3; k++) {
list3.add(new SimpleScalar("test " +
String.valueOf(i) +
" " +
String.valueOf(j) +
" " +
String.valueOf(k)));
}
list2.add(list3);
}
list1.add(list2);
}
modelRoot.put("list1", list1);
</pre>
<p>The template code above would then produce this output: </p>
<p>test 0 0 0<br />test 0 0 1<br />test 0 0 2<br />test 0 1 0<br />test 0 1 1<br />test 0
1 2<br />test 0 2 0<br />test 0 2 1<br />test 0 2 2<br />test 1 0 0<br />test 1 0
1<br />test 1 0 2<br />test 1 1 0<br /></p>
<p>etc.</p>
</topic>
<topic id="xml" name="Can I use XML documents as data models?">
<p>Yes, you can. In particular, you have to first build a <a href="http://www.jdom.org/" target="_top">JDOM</a> tree
from your XML document, and afterwards you can use JDOM tree nodes as data models.
The extensions library has a class that can wrap a JDOM nodes to expose them to FreeMarker as
a template model. In order to wrap your JDOM document tree in a freemarker TemplateModel, it is
sufficient to do the following:</p>
<pre>
...
org.jdom.Document document = getMyDocumentSomehow(...);
TemplateModel model = new freemarker.ext.jdom.NodeListModel(document);
...
</pre>
<p>In the example below, the templates will be able to access the XML document through the
"document" variable. The adapter supports all kinds of tree traversals and filterings,
allows use of a node list as a TemplateListModel, and outputs XML fragments of contained nodes
when used as a string literal. It also features full XPath support.</p>
<p>This FAQ page itself is created by applying a FreeMarker template to an XML document. Table
of contents with links, topic grouping, and "Back to top" are all generated by the template.
See the <tt>examples/jdom</tt> and <tt>examples/ant</tt>
directories in FreeMarker distribution for example on using the XML support.</p>
</topic>
<topic id="reflect" name="What's a good way to wrap an existing object so that a template can call its methods?">
<p>The extensions library has classes to wrap arbitrary Java objects
as data models. In general, all you need to do to wrap your object <tt>obj</tt> into
a TemplateModel is to call a single static factory method:</p>
<pre>
...
TemplateModel model = freemarker.ext.beans.ReflectionUtilities.wrap(obj);
...
</pre>
<p>After this, you can write arbitrary method calls on the wrapped object, i.e. you
can write <tt>${obj.getFoo()}</tt> in a template to execute method foo and place its
result in the template output. Extensions library uses the JavaBeans introspector to discover available
methods, so you can use bean property-style invocations as well: in previous example you could
have written <tt>${obj.foo}</tt> as well. If any property or method call returns an object,
it is automatically wrapped for you, so you can chain invocations: <tt>{$obj.bar.baz.bing}</tt>
would translate to what in Java would be <tt>obj.getBar().getBaz().getBing()</tt>.
The framework automatically recognizes arrays as well as iterators, maps and collections
from <tt>java.util</tt> package and provides them with additional capabilities (arrays,
iterators, and collections act as list models and maps act as both lists of their entries
and allow lookup when used as a method model). There is even a facility for invoking
static methods (in case you ever needed <tt>System.currentTimeMillis()</tt> in a template).</p>
<p>It is worth noting that the framework caches the results of introspection, so that
the negative performance impact resulting from reflected method lookup is minimized.</p>
<p>For example on using the reflection wrapper, see the <tt>examples/webapp</tt>
directory in the FreeMarker distribution.</p>
</topic>
</topicgroup>
<topicgroup name="Integration">
<topic id="servlet" name="Is there a HTTP servlet for FreeMarker I can use out-of-the-box?">
<p>Yes, there is. The extensions library has the class <tt>freemarker.ext.servlet.FreemarkerServlet</tt>
that you can use to provide template processing capabilities to your webapp. There is even a sample
webapp under the <tt>examples/webapp</tt> directory of the distribution that should get you started.</p>
<p>In general, you should only place the following inside your <tt>web.xml</tt> file:</p>
<pre>
&lt;servlet&gt;
&lt;servlet-name&gt;freemarker&lt;/servlet-name&gt;
&lt;servlet-class&gt;freemarker.ext.servlet.FreemarkerServlet&lt;/servlet-class&gt;
&lt;init-param&gt;
&lt;param-name&gt;TemplatePath&lt;/param-name&gt;
&lt;param-value&gt;/templates&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;TemplateDelay&lt;/param-name&gt;
&lt;param-value&gt;0&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;NoCache&lt;/param-name&gt;
&lt;param-value&gt;true&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;freemarker&lt;/servlet-name&gt;
&lt;url-pattern&gt;/templates/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
</pre>
<p>This will map all URLs beginning with /templates/ to templates in your <tt>webapp/templates</tt> directory.
The servlet readily provides access to ServletContext, HttpSession, HttpServletRequest and HttpServletRequest
parameters in the template data model. If you need to have additional variables available in your data model,
just subclass the servlet and override the <tt>preTemplateProcess()</tt> method to shove any additional data
you need into the model before the template gets processed.</p>
</topic>
<topic id="ant" name="Can I use FreeMarker template processing in Ant?">
<p>Yes, you can. In particular, there is a FreeMarker task for Ant that will get a set of XML
files, run them through a FreeMarker template, and output the resulting files in a target
directory. This method is ideal for generating documentation, SQL scripts, or any other
transformation requried during your build process. It is a viable alternative to Ant's
<tt>xslt</tt> task. The Ant task is part of the extensions library. See the <tt>examples/ant</tt>
directory in FreeMarker distribution for a sample <tt>build.xml</tt> file that employs FreeMarker.</p>
</topic>
</topicgroup>
<topicgroup name="Features">
<topic id="arithmetic" name="Is it possible to do integer arithmetic in templates?">
<p>Yes. As of 2.0, FreeMarker supports numerics without casting in and
out of TemplateScalarModel. The new TemplateNumberModel intrace means
that numbers of any given precision are supported, not just integers.
</p>
<p>The basic arithmetic operators are supported,
and meaningful comparison can be made between numbers. Internally,
FreeMarker uses BigDecimals to ensure that no precision is lost when
performing arithmetic operations. See the <a href="docs/manual/index.html" target="_top">manual</a> for further details.</p>
</topic>
<topic id="editorMangle" name="I'm using a visual HTML editor that mangles template tags. Will you change the template language syntax to accomodate my editor?">
<p>I won't change the standard version, because a lot of templates depend on it.
However, FreeMarker is designed to make it easy for you to change the syntax to
suit your needs. Changing the tag delimiters, making tags case-insensitive, and
representing operators differently would be simple changes to make. Take a look
at <tt>freemarker.template.compiler.FMParser.jj</tt>, for more details.
Let me know if you need further explanation of anything in the source code.</p>
<p>My view is that the editors that break template code are themselves broken;
you'll probably have the same problem if you try to use them with other template
systems. A good editor should ignore, not mangle, what it doesn't understand. </p>
</topic>
<topic id="structureInfo" name="How can my Java classes ask a template for information about its structure (e.g. a list of all the variables)?">
<p>This isn't possible, because variable names can be dynamically generated from
data (see the <a
href="docs/manual/expressions.html">manual</a>).
However, there's a more important reason why FreeMarker doesn't support this.
The design of FreeMarker is based on the idea of a separation between business
objects and presentation objects. This separation takes two forms: </p>
<ol>
<li>The templates know what data to expect, but they don't know how it's
generated. </li>
<li>The business objects know what data to produce, but they don't know how
it's going to be displayed. Therefore, they don't know anything about
templates. </li>
</ol>
<p>Since the business objects don't rely on the templates, if you need to use
them with some other presentation system, you won't have to rewrite your
application. </p>
</topic>
</topicgroup>
<topicgroup name="Legal issues">
<topic id="license" name="If we distribute FreeMarker with our product, do we have to release the source code for our product?">
<p>No. As of 2.0, FreeMarker is released under the BSD license. This
means that source or binary distributions may be made freely, and
can be included in other products, whether commercial or open source.</p>
<p>The only restrictions apply to the copyright of FreeMarker itself,
and the use of FreeMarker or its contributors as endorsements of
your own product. See the <a href="LICENSE.txt">LICENSE</a> for
further details.</p>
<p>If you use FreeMarker, I hope you'll send me a link to some information about
your product, but that's optional as well.</p>
</topic>
</topicgroup>
</faq>