| <?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><list list1 as list2> |
| <list list2 as list3> |
| <list list3 as element> |
| ${element}<br> |
| </list> |
| </list> |
| </list> |
| </pre> |
| <p>You could make nested <tt>SimpleList</tt>s like this: </p> |
| <pre>SimpleList list1 = new SimpleList(); |
| for (int i = 0; i < 3; i++) { |
| SimpleList list2 = new SimpleList(); |
| for (int j = 0; j < 3; j++) { |
| SimpleList list3 = new SimpleList(); |
| for (int k = 0; k < 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> |
| <servlet> |
| <servlet-name>freemarker</servlet-name> |
| <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class> |
| <init-param> |
| <param-name>TemplatePath</param-name> |
| <param-value>/templates</param-value> |
| </init-param> |
| <init-param> |
| <param-name>TemplateDelay</param-name> |
| <param-value>0</param-value> |
| </init-param> |
| <init-param> |
| <param-name>NoCache</param-name> |
| <param-value>true</param-value> |
| </init-param> |
| <load-on-startup>1</load-on-startup> |
| </servlet> |
| |
| <servlet-mapping> |
| <servlet-name>freemarker</servlet-name> |
| <url-pattern>/templates/*</url-pattern> |
| </servlet-mapping> |
| </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> |