| <?xml version="1.0"?>
|
|
|
| <document>
|
|
|
| <properties>
|
| <title>Developer's Guide</title>
|
| <author email="geirm@apache.org">Velocity Documentation Team</author>
|
| </properties>
|
|
|
| <body>
|
|
|
| <section name="Contents">
|
|
|
| <p>
|
| <ol>
|
|
|
| <li>
|
| <a href="developer-guide.html#Introduction">Introduction and Getting Started</a>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#Resources">Resources</a>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#How Velocity Works">How Velocity Works</a>
|
| <ul>
|
| <li><a href="developer-guide.html#The Fundamental Pattern">The Fundamental Pattern</a></li>
|
| </ul>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#To Singleton Or Not To Singleton...">To Singleton Or Not To Singleton...</a>
|
| <ul>
|
| <li><a href="developer-guide.html#Singleton">Singleton Model</a></li>
|
| <li><a href="developer-guide.html#Separate">Separate Instance</a></li>
|
| </ul>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#The Context">The Context</a>
|
| <ul>
|
| <li><a href="developer-guide.html#The Basics">The Basics</a></li>
|
| <li><a href="developer-guide.html#Support for Iterative Objects for #foreach()">Support for Iterative Objects for #foreach()</a></li>
|
| <li><a href="developer-guide.html#Context Chaining">Context Chaining</a></li>
|
| <li><a href="developer-guide.html#Objects Created in the Template">Objects Created by the Template</a></li>
|
| <li><a href="developer-guide.html#Other Context Issues">Other Context Issues</a></li>
|
| </ul>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#Using Velocity In Servlets">Using Velocity in Servlets</a>
|
| <ul>
|
| <li><a href="developer-guide.html#Servlet Programming">Servlet Programming</a></li>
|
| <li><a href="developer-guide.html#Deployment">Deployment</a></li>
|
| </ul>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#Using Velocity In General Applications">Using Velocity in General Applications</a>
|
| <ul>
|
| <li><a href="developer-guide.html#The Velocity Helper Class">The Velocity Helper Class</a></li>
|
| <li><a href="developer-guide.html#Exceptions">Exceptions</a></li>
|
| <li><a href="developer-guide.html#Miscellaneous Details">Miscellaneous Details</a></li>
|
| </ul>
|
| </li> |
| |
| <li> |
| <a href="developer-guide.html#Application Attributes">Application Attributes</a> |
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#EventCartridge and Event Handlers">EventCartridge and Event Handlers</a>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#Velocity Configuration Keys and Values">Velocity Configuration Keys and Values</a>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#Configuring the Log System">Configuring the Log System</a>
|
| <ul> |
| <li> |
| <a href="developer-guide.html#Using Log4j With Existing Category">Using Log4j With Existing Category</a> |
| </li>
|
| <li>
|
| <a href="developer-guide.html#Simple Example of a Custom Logger">Simple Example of a Custom Logger</a>
|
| </li>
|
| </ul>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#Configuring Resource Loaders">Configuring the Resource Loaders (template loaders)</a>
|
| <ul>
|
| <li> |
| <a href="developer-guide.html#Resource Loaders">Resource Loaders</a> |
| </li> |
| <li>
|
| <a href="developer-guide.html#Configuration Examples">Configuration Examples</a>
|
| </li>
|
| <li> |
| <a href="developer-guide.html#Resource Manager and Cache">Pluggable Resource Manager and Resource Cache</a> |
| </li> |
| </ul>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#Template Encoding for Internationalization">Template Encoding for Internationalization</a>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#Velocity and XML">Velocity and XML</a>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#FAQ (Frequently Asked Questions)">FAQ (Frequently Asked Questions)</a>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#Summary">Summary</a>
|
| </li>
|
|
|
| <li>
|
| <a href="developer-guide.html#Appendix 1 : Deploying the Example Servlet">Appendix 1 : Deploying the Example Servlet</a>
|
| <ul>
|
| <li>
|
| <a href="developer-guide.html#TomcatExample">Jakarta Tomcat</a>
|
| </li>
|
| <li>
|
| <a href="developer-guide.html#ResinExample">Caucho Technology's Resin</a>
|
| </li>
|
| <li>
|
| <a href="developer-guide.html#WebLogic">BEA WebLogic</a>
|
| </li>
|
| </ul>
|
| </li>
|
|
|
| </ol>
|
| </p>
|
| </section>
|
|
|
| <section name="Introduction">
|
| <p>
|
| Velocity is a Java-based template engine, a simple and powerful development tool
|
| that allows you to easily create and render documents that format and present
|
| your data. In this guide, we hope to give an overview of the basics of
|
| development using Velocity, focusing on the two main areas for Velocity usage :
|
| </p>
|
|
|
| <ul>
|
| <li>servlet-based WWW development</li>
|
| <li>general application use</li>
|
| </ul>
|
|
|
| <p>
|
| You will see that there is no real difference between these, other than we make
|
| servlet development with Velocity very easy if you use our provided class
|
| VelocityServlet as a base class for your servlet, and offer a utility class to
|
| help with application development.
|
| </p>
|
|
|
| <p>
|
| <strong>Getting Started</strong>
|
| </p>
|
|
|
| <p>
|
| While this information is found elsewhere on the Velocity site and in the
|
| documentation, it is included here for completeness. Getting Velocity running on
|
| your computer is very easy. Note that all directory references are relative the
|
| root of the Velocity distribution tree.
|
| <ol>
|
| <li>
|
| Get the Velocity distribution. This is available as a release, nightly snapshot or
|
| directly from the CVS code repository. Any are fine, although for the latest
|
| features, the nightly snapshot is most likely the best way. For more
|
| information, go <a href="index.html">here</a>.
|
| </li>
|
| <li>
|
| If you don't have <a href="http://jakarta.apache.org/ant/">Jakarta Ant</a>,
|
| the Java build tool already installed, please do so. It is required for
|
| building Velocity, although not required for <i>using</i> Velocity.
|
| </li>
|
| <li>
|
| Go to the <code>build</code> directory in the distribution.
|
| </li>
|
| <li>
|
| Type <code>ant <build target></code> where <build target>
|
| is one of:
|
| <ul>
|
| <li>
|
| <b><code>jar</code></b> builds the complete Velocity jar in the
|
| <code>bin</code> directory. This jar will be called 'velocity-X.jar',
|
| where 'X' is the current version number. This jar does not include
|
| necessary dependencies for Velocity. If you use this
|
| target, you must get the Collections component jar from Jakarta Commons and add
|
| to your CLASSPATH (or WEB-INF/lib).
|
| If you wish to use the built-in logging or template conversion,
|
| you must include the appropriate jars in your CLASSPATH or
|
| webapp's WEB-INF/lib.
|
| For convenience, you can use the <code>jar-dep</code> target to build
|
| a jar with ORO, Logkit and Commons Collections included.
|
| </li>
|
| <li>
|
| <b><code>jar-dep</code></b> builds the complete Velocity jar in
|
| the <code>bin</code> directory, including necessary
|
| support for logging from the
|
| <a href="http://jakarta.apache.org/avalon/logkit/index.html">Jakarta
|
| Avalon Logkit</a> package, critical configuration support from the
|
| <a href="http://jakarta.apache.org/commons/">Jakarta Commons</a>
|
| and the necesary support for WebMacro
|
| template conversion using the
|
| <a href="http://jakarta.apache.org/oro/index.html">Jakarta ORO</a>
|
| package.
|
| </li>
|
| <li>
|
| <b><code>jar-core</code></b> builds a slimmer Velocity jar in the
|
| <code>bin</code> directory, called 'velocity-core-X.jar'. This jar
|
| contains the core Velocity functionality, and doesn't include example
|
| and utility things like Anakia, Texen or the VelocityServlet support
|
| baseclass. It has the same external dependency requirements as the
|
| regular <code>jar</code> target.
|
| </li>
|
| <li>
|
| <b><code>jar-util</code></b> builds a utility Velocity jar in the
|
| <code>bin</code> directory, called 'velocity-util-X.jar'. This jar
|
| contains utility code, specifically Anakia, Texen, and the WebMacro
|
| template conversion utility. It has the same external dependency requirements as the
|
| regular <code>jar</code> target.
|
| </li>
|
| <li>
|
| <b><code>jar-servlet</code></b> builds a utility Velocity jar in the
|
| <code>bin</code> directory, called 'velocity-servlet-X.jar'. This jar
|
| contains utility code for servlet programmers. It has the same external dependency requirements as the
|
| regular <code>jar</code> target.
|
| </li>
|
| <li>
|
| <b><code>jar-J2EE</code></b> builds a complete jar, like the 'jar' target,
|
| that includes any components that require J2EE support. Currently, this
|
| includes only org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader.
|
| As usual, it is placed in the <code>bin</code> directory, called
|
| 'velocity-j2ee-X.jar'. NOTE : if you wish to use this build target, you
|
| must place (or link) a copy of j2ee.jar into the build/lib directory.
|
| We do not provide it as part of the distribution. A good source is
|
| http://java.sun.com/. It has the same external dependency requirements as the
|
| regular <code>jar</code> target.
|
| </li>
|
| <li>
|
| <b><code>jar-J2EE-dep</code></b> build a complete jar with J2EE support
|
| and includes logging support from the Jakarta Avalon Logkit and
|
| regexp support fromt the Jakarta ORO package. See the notes on the
|
| <code>jar-dep</code> target, above.
|
| </li>
|
| <li>
|
| <b><code>examples</code></b> builds the example code in the example programs
|
| found in the <code>examples</code> directory. This build target will
|
| also build the forumdemo example project.
|
| </li>
|
| <li>
|
| <b><code>forumdemo</code></b> builds the example webapplication in the
|
| <code>examples/forumdemo</code> directory.
|
| </li>
|
| <li>
|
| <b><code>docs</code></b> builds these docs in the <code>docs</code> directory
|
| using Velocity's <a href="anakia.html">Anakia</a> XML transformation tool.
|
| Allowing you to use
|
| Velocity templates in place of stylesheets
|
| - give it a try! <i>Note: This target requires that the jakarta-site2 project
|
| is located as a peer directory to the jakarta-velocity distribution directory.
|
| Please see the note in the build.xml file for this target for further information.</i>
|
| </li>
|
| <li>
|
| <b><code>jar-src</code></b> bundles all the Velocity source code into a single
|
| jar, placed in the <code>bin</code> directory.
|
| </li>
|
| <li>
|
| <b><code>javadocs</code></b> builds the Javadoc class documentation in the
|
| <code>docs/api</code> directory
|
| </li>
|
| <li>
|
| <b><code>test</code></b> (after jar) will test Velocity against it's testbed
|
| suite of test routines
|
| </li>
|
| <li>
|
| <b><code>help</code></b> lists the build targets that are available.
|
| </li>
|
| </ul>
|
| </li>
|
| <li>
|
| While not required, testing the build is a good idea. Use the
|
| <code>test</code> target mentioned above.
|
| </li>
|
| <li>
|
| That's it! Velocity is ready to be used. Put the jar into your classpath, or
|
| into other appropriate places (such as the lib directory of your webapp if
|
| using with servlets)
|
| </li>
|
| <li>
|
| If you want to play with the examples, which is highly recommended when
|
| getting started, use build the examples via
|
| <code>ant examples</code>.
|
| </li>
|
| </ol>
|
| </p>
|
|
|
| <strong>Dependencies</strong>
|
|
|
| <p>
|
| Velocity uses elements of the Java 2 API such as collections, and therefore
|
| building requires the Java 2 Standard Edition SDK (Software Development Kit).
|
| To run Velocity, the Java 2 Standard Edition RTE (Run Time Environment)
|
| is required (or you can use the SDK, of course).
|
| </p>
|
| <p>
|
| Velocity also is dependent upon a few packages for general functionality. They
|
| are included in the <code>build/lib</code> directory for convenience, but
|
| the default build target (see above) does not include them. If you use the
|
| default build target, you must add the dependencies to your classpath.
|
| </p>
|
|
|
| <ul>
|
| <li>
|
| <a href="http://jakarta.apache.org/commons/">
|
| <b>Jakarta Commons Collections</b></a> - required.
|
| </li>
|
| <li>
|
| <a href="http://jakarta.apache.org/avalon/logkit/index.html">
|
| <b>Jakarta Avalon Logkit</b></a> - optional, but very common.
|
| Needed if using the default file-based logging in Velocity.
|
| </li>
|
| <li>
|
| <a href="http://jakarta.apache.org/oro/index.html"><b>Jakarta ORO</b></a>
|
| - optional. Needed when using the
|
| <code>org.apache.velocity.convert.WebMacro</code> template conversion
|
| utility.
|
| </li>
|
| </ul>
|
|
|
|
|
| </section>
|
|
|
| <section name="Resources">
|
| <p>
|
| There are quite a few resources and examples available to the programmer, and we
|
| recommend that you look at our examples, documentation and even the source code.
|
| Some great sources are :
|
| </p>
|
|
|
| <ul>
|
| <li>
|
| The user and developer community : join us via the
|
| <a href="http://jakarta.apache.org/getinvolved/mail.html">mail-lists</a>.
|
| </li>
|
| <li>
|
| Mail-list archives : <a href="http://www.mail-archive.com">
|
| http://www.mail-archive.com</a> is a good one. Type 'velocity' into the search
|
| box to see both our -user and -dev archives.
|
| </li>
|
| <li>
|
| source code : <code>src/java/...</code> : all the source code to the
|
| Velocity project
|
| </li>
|
| <li>
|
| application example 1 : <code>examples/app_example1</code> : a simple
|
| example showing how to use Velocity in an application program.
|
| </li>
|
| <li>
|
| application example 2 : <code>examples/app_example2</code> : a simple
|
| example showing how to use Velocity in an application program using the
|
| Velocity application utility class.
|
| </li>
|
| <li>
|
| servlet example : <code>examples/servlet_example1</code> : a simple example
|
| showing how to use Velocity in a servlet.
|
| </li>
|
| <li>
|
| logger example : <code>examples/logger_example</code> : a simple example
|
| showing how to create a custom logging class and register it with
|
| Velocity to receive all log messages.
|
| </li>
|
| <li>
|
| XML example : <code>examples/xmlapp_example</code> : a simple example
|
| showing how to use JDOM to read and access XML document data from
|
| within a Velocity template. It also includes a demonstration of
|
| a recursive Velocimacro that walks the document tree.
|
| </li>
|
| <li>
|
| event example : <code>examples/event_example</code> : An example that
|
| demonstrates the use of the event handling API in Velocity 1.1
|
| </li>
|
| <li>
|
| Anakia application : <code>examples/anakia</code> : example application
|
| showing how to use Velocity for creating stylesheet renderings of xml data
|
| </li>
|
| <li>
|
| Forumdemo web app : <code>examples/forumdemo</code> : working example of a
|
| simple servlet-based forum application
|
| </li>
|
| <li>
|
| documentation : <code>docs</code> : all the generated documentation for the
|
| Velocity project in html
|
| </li>
|
| <li>
|
| API documentation : <code>docs/api</code> : the generated Javadoc
|
| documentation for the Velocity project
|
| </li>
|
| <li>
|
| templates : <code>test/templates</code> : a large collection of template
|
| examples in our testbed directory, these are a great source of useage
|
| examples of VTL, the Velocity Template Language
|
| </li>
|
| <li>
|
| context example : <code>examples/context_example</code> : two examples
|
| showing how the Velocity context can be extended. For advanced users.
|
| </li>
|
| </ul>
|
|
|
| <p>
|
| All directory references above are relative to the distribution root directory.
|
| </p>
|
| </section>
|
|
|
| <section name="How Velocity Works">
|
|
|
| <p>
|
| <a name="The Fundamental Pattern"><strong>'The Fundamental Pattern'</strong></a>
|
| </p>
|
|
|
| <p>
|
| When using Velocity in an application program or in a servlet
|
| (or anywhere, actually), you will generally do the following :
|
| </p>
|
|
|
| <ol>
|
| <li>Initialize Velocity. This applies to both usage patterns for Velocity,
|
| the Singleton as well as the 'separate runtime instance' (see more on this
|
| below), and you only do this once.</li>
|
| <li>Create a Context object (more on what that is later).</li>
|
| <li>Add your data objects to the Context.</li>
|
| <li>Choose a template.</li>
|
| <li>'Merge' the template and your data to produce the ouput.</li>
|
| </ol>
|
|
|
| <p>
|
| In code, using the singleton pattern via the
|
| <code>org.apache.velocity.app.Velocity</code> class,
|
| this looks like
|
| </p>
|
|
|
| <source><![CDATA[
|
| import java.io.StringWriter;
|
| import org.apache.velocity.VelocityContext;
|
| import org.apache.velocity.Template;
|
| import org.apache.velocity.app.Velocity;
|
| import org.apache.velocity.exception.ResourceNotFoundException;
|
| import org.apache.velocity.exception.ParseErrorException;
|
| import org.apache.velocity.exception.MethodInvocationException;
|
|
|
| Velocity.init();
|
|
|
| VelocityContext context = new VelocityContext();
|
|
|
| context.put( "name", new String("Velocity") );
|
|
|
| Template template = null;
|
|
|
| try
|
| {
|
| template = Velocity.getTemplate("mytemplate.vm");
|
| }
|
| catch( ResourceNotFoundException rnfe )
|
| {
|
| // couldn't find the template
|
| }
|
| catch( ParseErrorException pee )
|
| {
|
| // syntax error : problem parsing the template
|
| }
|
| catch( MethodInvocationException mie )
|
| {
|
| // something invoked in the template
|
| // threw an exception
|
| }
|
| catch( Exception e )
|
| {}
|
|
|
| StringWriter sw = new StringWriter();
|
|
|
| template.merge( context, sw );
|
|
|
| ]]></source>
|
|
|
| <p>
|
| That's the basic pattern. It is very simple, isn't it? This is generally what
|
| happens when you use Velocity to render a template. You probably won't be
|
| writing code exactly like this - we provide a few tools to help make it even
|
| easier than this for both servlet and application programmers.
|
| Later on in this guide, we will talk about using Velocity in both servlets
|
| as well as general applications, and we discuss the tools we provide to make
|
| things easier. In each case, though, the above sequence is what is happening
|
| either explicitly, or behind the scenes.
|
| </p>
|
|
|
|
|
| </section>
|
|
|
| <section name="To Singleton Or Not To Singleton...">
|
|
|
| <p>
|
| As of Velocity 1.2 and later, developers now have two options
|
| for using the Velocity engine, the singleton model and the separate instance
|
| model. The same core Velocity code is used for both approaches, which are
|
| provided to make Velocity easier to integrate into your Java application.
|
| </p>
|
|
|
| <p>
|
| <a name="Singleton"><strong>Singleton Model</strong></a>
|
| </p>
|
|
|
| <p>
|
| This is the legacy pattern, where there is only one instance of the Velocity
|
| engine in the JVM (or web application, depending) that is shared by all.
|
| This is very convenient as it
|
| allows localized configuration and sharing of resources. For example, this
|
| is a very appropriate model for use in a Servlet 2.2+ compliant web application
|
| as each web application can have it's own instance of Velocity, allowing
|
| that web application's servlet to share resources like templates, a logger, etc.
|
| The singleton is accessable via the <code>org.apache.velocity.app.Velocity</code>
|
| class, and and example of use :
|
| </p>
|
| <source><![CDATA[
|
|
|
| import org.apache.velocity.app.Velocity;
|
| import org.apache.velocity.Template;
|
|
|
| ...
|
|
|
| /*
|
| * Configure the engine - as an example, we are using
|
| * ourselves as the logger - see logging examples
|
| */
|
|
|
| Velocity.setProperty( Velocity.RUNTIME_LOG_LOGSYSTEM, this);
|
|
|
| /*
|
| * now initialize the engine
|
| */
|
|
|
| Velocity.init();
|
|
|
| ...
|
|
|
| Template t = Velocity.getTemplate("foo.vm");
|
| ]]></source>
|
|
|
| <p>
|
| Please note that the Singleton model is used in the
|
| <code>org.apache.velocity.servlet.VelocityServlet</code> base class,
|
| a utility class provided with the distribution to make writing servlets
|
| easier. While extending this class is the most common and convenient
|
| way to write servlets using Velocity, you are free to not use this
|
| class if you needs require something different.
|
| </p>
|
|
|
| <p>
|
| <a name="Separate"><strong>Separate Instance</strong></a>
|
| </p>
|
|
|
| <p>
|
| New in version 1.2, the separate instance allows you to create, configure
|
| and use as many instances of Velocity as you wish in the same JVM
|
| (or web application.) This
|
| is useful when you wish to support separate configurations, such as template
|
| directories, loggers, etc in the same application. To use separate
|
| instances, use the <code>org.apache.velocity.app.VelocityEngine</code>
|
| class. An example, which parallels the above singleton example, looks
|
| like :
|
| </p>
|
|
|
| <source><![CDATA[
|
|
|
| import org.apache.velocity.app.VelocityEngine;
|
| import org.apache.velocity.Template;
|
|
|
| ...
|
|
|
| /*
|
| * create a new instance of the engine
|
| */
|
|
|
| VelocityEngine ve = new VelocityEngine();
|
|
|
| /*
|
| * configure the engine. In this case, we are using
|
| * ourselves as a logger (see logging examples..)
|
| */
|
|
|
| ve.setProperty( VelocityEngine.RUNTIME_LOG_LOGSYSTEM, this);
|
|
|
| /*
|
| * initialize the engine
|
| */
|
|
|
| ve.init();
|
|
|
| ...
|
|
|
| Template t = ve.getTemplate("foo.vm");
|
| ]]></source>
|
|
|
| <p>
|
| As you can see, this is very simple and straightforward. Except for some simple
|
| syntax changes, using Velocity as a singleton or as separate instances requires
|
| no changes to the high-level structure of your application or templates.
|
| </p>
|
|
|
| <p>
|
| As a programmer, the classes you should use to interact with the Velocity
|
| internals are the <code>org.apache.velocity.app.Velocity</code> class if
|
| using the singleton model, or <code>org.apache.velocity.app.VelocityEngine</code>
|
| if using the non-singleton model ('separate instance').
|
| </p>
|
| <p>
|
| At no time should an application use the internal <code>Runtime, RuntimeConstants,
|
| RuntimeSingleton or RuntimeInstance</code> classes in the
|
| <code>org.apache.velocity.runtime</code> package, as these are intended for
|
| internal use only and may change over time. As mentioned above,
|
| the classes you should use
|
| are located in the <code>org.apache.velocity.app</code> package, and are the
|
| <code>Velocity</code> and <code>VelocityEngine</code> classes. If anything is
|
| missing or needed from those classes, do not hesitate to suggest changes - these
|
| classes are intended for the application developer.
|
| </p>
|
| </section>
|
|
|
| <section name="The Context">
|
|
|
| <a name="The Basics"><strong>The Basics</strong></a>
|
| <p>
|
| The concept of the 'context' is central to Velocity, and is a common technique
|
| for moving a container of data around between parts of a system. The idea is
|
| that the context is a 'carrier' of data between the Java layer (or you the
|
| programmer) and the template layer ( or the designer ). You as the programmer
|
| will gather objects of various types, whatever your application calls for, and
|
| place them in the context. To the designer, these objects, and their methods
|
| and properties, will become accessable via template elements called
|
| <a href="vtl-reference-guide.html"> references</a>. Generally, you will work
|
| with the designer to determine the data needs for the application. In a sense,
|
| this will become an 'API' as you produce a data set for the designer to access
|
| in the template. Therefore, in this phase of the development process it is
|
| worth devoting some time and careful analysis.
|
| </p>
|
|
|
| <p>
|
| While Velocity allows you to create your own context classes to support special
|
| needs and techniques (like a context that accesses an LDAP server directly, for
|
| example), a good basic implementation class called VelocityContext is provided
|
| for you as part of the distribution.
|
| </p>
|
| <p>
|
| VelocityContext is suitable for all general purpose needs, and we strongly
|
| recommended that you use it. Only in exceptional and advanced cases will you
|
| need to extend or create your own context implementation.
|
| </p>
|
| <p>
|
| Using VelocityContext is as simple as using a normal Java Hashtable class.
|
| While the interface contains other useful methods, the two main methods you
|
| will use are
|
| </p>
|
|
|
| <source><![CDATA[
|
| public Object put(String key, Object value);
|
| public Object get(String key);
|
| ]]></source>
|
|
|
| <p>
|
| Please note that like a Hashtable, the value must be derived from
|
| java.lang.Object, and must not be null. Fundamental types like int or float must
|
| be wrapped in the appropriate wrapper classes.
|
| </p>
|
| <p>
|
| That's really all there is to basic context operations. For more information,
|
| see the API documentation included in the distribution.
|
| </p>
|
|
|
| <p>
|
| <a name="Support for Iterative Objects for #foreach()"><strong>Support for Iterative Objects for
|
| #foreach()</strong></a>
|
| </p>
|
|
|
| <p>
|
| As a programmer, you have great freedom in the objects that you put into the
|
| context. But as with most freedoms, this one comes with a little bit of
|
| responsibility, so understand what Velocity supports, and any issues that may
|
| arise. Velocity supports serveral types of collection types suitable for use
|
| in the VTL <code>#foreach()</code> directive.
|
| </p>
|
|
|
| <ul>
|
|
|
| <li> <code>Object [] </code> Regular object array, not much needs to be said
|
| here. Velocity will internally wrap your array in a class that provides an
|
| Iterator interface, but that shouldn't concern you as the programmer, or the
|
| template author.
|
| </li>
|
|
|
| <li> <code>java.util.Collection</code> Velocity will use the
|
| <code>iterator()</code> method to get an Iterator to use in the loop,
|
| so if you are implementing a Collection interface on your object, please
|
| ensure that <code>iterator()</code> returns a working Iterator.
|
| </li>
|
|
|
| <li> <code>java.util.Map </code> Here, Velocity depends upon the
|
| <code>values()</code> method of the interface to get a <code>Collection</code>
|
| interface, on which <code>iterator()</code> is called to retrieve an Iterator
|
| for the loop.
|
| </li>
|
|
|
| <li> <code>java.util.Iterator</code> USE WITH CAUTION : This is currently
|
| supported only provisionally - the issue of concern is the
|
| 'non-resettablity' of the Iterator. If a 'naked' Iterator is placed into
|
| the context, and used in more than one #foreach(), subsequent #foreach()
|
| blocks after the first will fail, as the Iterator doesn't reset.
|
| </li>
|
|
|
| <li> <code>java.util.Enumeration</code> USE WITH CAUTION : Like
|
| <code>java.util.Iterator</code>, this is currently
|
| supported only provisionally - the issue of concern is the
|
| 'non-resettablity' of the Enumeration. If a 'naked' Enumeration
|
| is placed into the context, and used in more than one #foreach(),
|
| subsequent #foreach() blocks after the first will fail,
|
| as the Enumeration doesn't reset.
|
| </li>
|
|
|
| </ul>
|
|
|
| <p>
|
| In the case of the <code>Iterator</code> and <code>Enumeration</code>, it is
|
| recommended that they are placed in the context only when it cannot be avoided,
|
| and you should let Velocity find the appropriate reusable iterative interface when
|
| that is sufficient and possible.
|
| </p>
|
|
|
| <p>
|
| There are good reasons to use the <code>java.util.Iterator</code> interface
|
| directly (large data sets via JDBC, for example), but if it can be
|
| avoided, it might be better to use something else. By 'directly' , we meant
|
| doing something like:
|
| </p>
|
|
|
| <source><![CDATA[
|
| Vector v = new Vector();
|
| v.addElement("Hello");
|
| v.addElement("There");
|
|
|
| context.put("words", v.iterator() );
|
| ]]></source>
|
|
|
| <p>
|
| where the Iterator itself is placed into the context. Instead, if you
|
| simply did:
|
| </p>
|
|
|
| <source><![CDATA[
|
| context.put("words", v );
|
| ]]></source>
|
|
|
| <p>
|
| then all would be fine: Velocity would figure out that Vector implement
|
| Collection (via List), and therefore will find the <code>iterator()</code>
|
| method, and use that to get a 'fresh' Iterator for its use each time
|
| it needs to. With just a plain Iterator (the first snippet above...),
|
| once velocity has used it in a <code>#foreach()</code>, Velocity has
|
| no way of getting a new one to use for the next <code>#foreach()</code>
|
| it is used in. The result is no output from any subsequent
|
| <code>#foreach()</code> blocks using that reference.
|
| </p>
|
|
|
| <p>
|
| This above isn't meant to give the impression that iterating over
|
| collections in Velocity is something that requires great care and
|
| thought. Rather, the opposite is true, in general. Just be
|
| careful when you place an Iterator into the context.
|
| </p>
|
|
|
| <a name="Context Chaining"><strong>Context Chaining</strong></a>
|
|
|
| <p>
|
| An innovative feature of Velocity's context design is the concept
|
| of <i>context chaining</i>. Also sometimes referred to as
|
| <i>context wrapping</i>, this advanced feature allows you to connect
|
| separate contexts together in a manner that makes it appear as one
|
| 'contiguous' context to the template.
|
| </p>
|
| <p>
|
| This is best illustrated by an example :
|
| </p>
|
| <source><![CDATA[
|
| VelocityContext context1 = new VelocityContext();
|
|
|
| context1.put("name","Velocity");
|
| context1.put("project", "Jakarta");
|
| context1.put("duplicate", "I am in context1");
|
|
|
| VelocityContext context2 = new VelocityContext( context1 );
|
|
|
| context2.put("lang", "Java" );
|
| context2.put("duplicate", "I am in context2");
|
|
|
| template.merge( context2, writer );
|
| ]]></source>
|
|
|
| <p>
|
| In the code above, we have set up context2 such that it <i>chains</i>
|
| context1. This means that in the template, you can access any of
|
| the items that were put into either of the two VelocityContext objects,
|
| as long as there is no duplication of the keys used to add objects.
|
| If that is the case, as it is above for the key 'duplicate', the object
|
| stored in the nearest context in the chain will be available. In this
|
| example above, the object returned would
|
| be the string "I am in context2".
|
| </p>
|
| <p>
|
| Note that this duplication, or 'covering', of a context item does not in
|
| any way harm or alter the covered object. So in the example above, the
|
| string "I am in context1" is alive and well, still accessable via
|
| context1.get("duplicate"). But in the example above, the value of the
|
| reference '$duplicate' in the template would be 'I am in context2',
|
| and the template has no access to the covered string 'I am in context1'.
|
| </p>
|
| <p>
|
| Note also that you have to be careful when you are relying on the template
|
| to add information to a context that you will examine later after the
|
| rendering. The changes to the context via <code>#set()</code> statements
|
| in a template will affect only the outer context. So make sure that you
|
| don't discard the outer context, expecting the data from the template to
|
| have been placed onto the inner one.
|
| </p>
|
| <p>
|
| This feature has many uses, the most common so far is providing layered
|
| data access and toolsets.
|
| </p>
|
| <p>
|
| As mentioned before, the Velocity context mechanism is also extendable,
|
| but beyond the current scope of this guide. If you are interested,
|
| please see the classes in the package <code>org.apache.velocity.context</code>
|
| to see how the provided contexts are put together. Futher, there are a few
|
| examples in the <code>examples/context_example</code> directory in the
|
| distribution which show alternate implementations, including [a goofy] one
|
| that uses a database as the backing storage.
|
| </p>
|
| <p>
|
| Please note that these examples are unsupported and are there for
|
| demonstration/educational purposes only.
|
| </p>
|
|
|
| <a name="Objects Created in the Template"><strong>Objects Created in the
|
| Template</strong></a>
|
|
|
| <p>
|
| There are two common situations where the Java code must deal with objects
|
| created at runtime in the template :
|
| </p>
|
|
|
| <p>
|
| When a template author calls a method of an object placed into
|
| the context by Java code.
|
| </p>
|
|
|
| <source><![CDATA[
|
| #set($myarr = ["a","b","c"] )
|
| $foo.bar( $myarr )
|
| ]]></source>
|
|
|
| <p>
|
| When a template adds objects to the context, the Java code can access
|
| those objects after the merge process is complete.
|
| </p>
|
|
|
| <source><![CDATA[
|
| #set($myarr = ["a","b","c"] )
|
| #set( $foo = 1 )
|
| #set( $bar = "bar")
|
| ]]></source>
|
|
|
| <p>
|
| Dealing with these cases if very straighforward, as there are just a few
|
| things to know:
|
| </p>
|
|
|
| <ul>
|
| <li>
|
| The VTL RangeOperator [ 1..10 ] and ObjectArray ["a","b"] are
|
| <code>java.util.ArrayList</code> objects when placed in the context
|
| or passed to methods. Therefore, your methods that are designed to
|
| accept arrays created in the template should be written with this
|
| in mind.
|
| </li>
|
| <li>
|
| Numbers will be Integers in the context, and strings will be, of course, Strings.
|
| </li>
|
| <li>
|
| Velocity will properly 'narrow' args to method calls, so calling
|
| <code>setFoo( int i )</code> with an int placed into the
|
| context via <code>#set()</code> will work fine.
|
| </li>
|
| </ul>
|
|
|
| <a name="Other Context Issues"><strong>Other Context Issues</strong></a>
|
|
|
| <p>
|
| One of the features provided by the VelocityContext
|
| (or any Context derived from AbstractContext) is
|
| node specific introspection caching. Generally, you as a the developer
|
| don't need to worry about this when using the VelocityContext
|
| as your context. However, there is currently one
|
| known usage pattern where you must be aware of this feature.
|
| </p>
|
|
|
| <p>
|
| The VelocityContext will accumulate intropection information about the
|
| syntax nodes in a template as it visits those nodes. So, in the following
|
| situation:
|
| </p>
|
|
|
| <ul>
|
| <li>
|
| You are iterating over the same template using the same VelocityContext
|
| object.
|
| </li>
|
| <li>
|
| Template caching is off.
|
| </li>
|
| <li>
|
| You request the Template from getTemplate() on each iteration.
|
| </li>
|
| </ul>
|
|
|
| <p>
|
| It is possible that your VelocityContext will appear to 'leak' memory
|
| (it is really just gathering more introspection information.) What
|
| happens is that it accumulates template node introspection information
|
| for each template it visits, and as template caching is off, it appears
|
| to the VelocityContext that it is visiting a new template each time.
|
| Hence it gathers more introspection information and grows. It is highly
|
| recommended that you do one or more of the following :
|
| </p>
|
|
|
| <ul>
|
| <li>Create a new VelocityContext for each excursion
|
| down through the template render process. This will prevent the accumulation
|
| of introspection cache data. For the case where you want to reuse the
|
| VelocityContext because it's populated with data or objects,
|
| you can simply wrap the populated
|
| VelocityContext in another, and the 'outer' one will accumulate the
|
| introspection information, which you will just discard. Ex.
|
| <code>VelocityContext useThis = new VelocityContext( populatedVC );</code>
|
| This works because the outer context will store the introspection
|
| cache data, and get any requested data from the inner context (as it is empty.)
|
| Be careful though - if your template places data into the context and it's
|
| expected that it will be used in the subsequent iterations, you will need to do
|
| one of the other fixes, as any template #set() statements will be stored in
|
| the outermost context. See the discussion in
|
| <a href="developer-guide.html#Context Chaining">Context chaining</a> for more
|
| information.
|
| </li>
|
|
|
| <li>
|
| Turn on template caching. This will prevent the template from being re-parsed
|
| on each iteration, resulting the the VelocityContext being able to not only
|
| avoid adding to the introspection cache information, but be able to use it
|
| resulting in a performance improvement.
|
| </li>
|
|
|
| <li>
|
| Reuse the Template object for the duration of the loop iterations.
|
| Then you won't be forcing Velocity, if the cache is turned off, to
|
| reread and reparse the same template over and over, so the VelocityContext
|
| won't gather new introspection information each time.
|
| </li>
|
| </ul>
|
|
|
| </section>
|
|
|
| <section name="Using Velocity In Servlets">
|
|
|
| <a name="Servlet Programming"><strong>Servlet Programming</strong></a>
|
|
|
| <p>
|
| The most common use of Velocity is in the area of Java Servlet programming
|
| for the WWW. There are many reasons why Velocity is well suited for this
|
| task, one of the primary ones is Velocity's enforcement of the
|
| separation of the presentation (or view) layer from the
|
| code layer. There are many resources on this subject, including
|
| <a href="http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html">
|
| this</a>.
|
| </p>
|
| <p>
|
| The basic technique of using Velocity in a servlet environment is very simple.
|
| In a nutshell, all you must do is extend the provided VelocityServlet base class
|
| and implement a single method, <code>handleRequest()</code>. That's really all that is
|
| required to use Velocity in your servlet development.
|
| </p>
|
|
|
| <p>
|
| As of Velocity 1.1, there are two <code>handleRequest()</code> methods :
|
|
|
| <br/>
|
| <br/>
|
|
|
| <i><code>public Template handleRequest( Context )</code></i>
|
|
|
| <blockquote>
|
| This is the older of the two methods. This method requires that you
|
| return a valid Template object. If not valid, or <code>null</code>,
|
| this is considered an error condition, and will result in the <a
|
| href="developer-guide.html#error()"><code>error()</code></a> error
|
| handling method being called. You may override the
|
| <code>error()</code> if you wish. If returning a <code>null</code> is
|
| something you expect to do (for example, you will want to redirect
|
| requests) it is recommended that you use the newer method, listed
|
| next.
|
| </blockquote>
|
| <br/>
|
|
|
| <i><code>public Template handleRequest( HttpServletRequest, HttpServletResponse, Context )</code></i>
|
|
|
| <blockquote>
|
| This is the newer of the two <code>handleRequest()</code> methods,
|
| implemented in version 1.1. The difference with this method is that
|
| the <code>HttpServletRequest</code> and
|
| <code>HttpServletResponse</code> objects are passed to you as
|
| arguments to the method, as well as in the <code>Context</code>. The
|
| other difference is that this method can return <code>null</code> to
|
| indicate that all processing has been handled by the method, and that
|
| Velocity should do nothing further than call
|
| <a href="developer-guide.html#requestCleanup()"><code>requestCleanup()</code></a>.
|
| This is extremely useful is you wish to redirect the request, for
|
| example.
|
| </blockquote>
|
|
|
| As always, please refer to the Javadoc API documentation for the definitive and
|
| latest notes.
|
| </p>
|
|
|
| <p>
|
| The following code is similar to the SampleServlet.java class included
|
| in the distribution in the examples directory.
|
| </p>
|
|
|
| <source><![CDATA[
|
| public class SampleServlet extends VelocityServlet
|
| {
|
| public Template handleRequest( HttpServletRequest request,
|
| HttpServletResponse response,
|
| Context context )
|
| {
|
|
|
| String p1 = "Jakarta";
|
| String p2 = "Velocity";
|
|
|
| Vector vec = new Vector();
|
| vec.addElement( p1 );
|
| vec.addElement( p2 );
|
|
|
| context.put("list", vec );
|
|
|
| Template template = null;
|
|
|
| try
|
| {
|
| template = getTemplate("sample.vm");
|
| }
|
| catch( ResourceNotFoundException rnfe )
|
| {
|
| // couldn't find the template
|
| }
|
| catch( ParseErrorException pee )
|
| {
|
| // syntax error : problem parsing the template
|
| }
|
| catch( Exception e )
|
| {}
|
|
|
| return template;
|
| }
|
| }
|
| ]]></source>
|
|
|
| <p>
|
| Look familiar? With the exception of creating the context object, which is
|
| done for you by the VelocityServlet base class, and the merge() step
|
| which is also done for you by the VelocityServlet base class, it's identical
|
| to the basic code pattern we mentioned at the beginning of this guide.
|
| We take the context, add our application data, and return a template.
|
| </p>
|
|
|
| <p>
|
| The default <code>Context</code> object that is passed into the
|
| <code>handleRequest()</code> methods contains both the current
|
| <code>HttpServletRequest</code> and <code>HttpServletResponse</code>
|
| objects. They are placed in the context using the the constants
|
| <code>VelocityServlet.REQUEST</code> (value = 'req') and
|
| <code>VelocityServlet.RESPONSE</code> (value = 'res')
|
| respectively. To access and use these objects in your Java code :
|
| </p>
|
| <source><![CDATA[
|
| public Template handleRequest( Context context )
|
| {
|
| HttpServletRequest request = (HttpServletRequest) context.get( REQUEST );
|
| HttpServletResponse response = (HttpServletResponse) context.get( RESPONSE );
|
|
|
| ...
|
| ]]></source>
|
|
|
| <p>
|
| and in your templates:
|
| </p>
|
|
|
| <source><![CDATA[
|
| #set($name = $req.getParameter('name') )
|
| ]]></source>
|
|
|
| <p>
|
| For more advanced uses, the VelocityServlet base class allows you to override
|
| parts of the handling of the request processing. The following methods may
|
| be overridden :
|
| <br/>
|
| <br/>
|
|
|
| <i><code> Properties loadConfiguration( ServletConfig )</code></i>
|
| <blockquote>
|
| Allows you to override the normal configuration mechanism and add or
|
| alter the configuation properties. This is useful for overriding or
|
| augmenting template and log paths, to set the absolute path into the
|
| webapp root at runtime.
|
| </blockquote>
|
|
|
| <i><a name="createContext()">
|
| <code>Context createContext(HttpServletRequest, HttpServletResponse )</code></a></i>
|
| <blockquote>
|
| Allows you to create the Context object yourself. This allows more advanced
|
| techniques, such as chaining or pre-loading with tools or data. The default
|
| implementation simply returns a VelocityContext object with the request
|
| and response objects placed inside. The request and response objects are
|
| wrapped in simple wrapper classes to avoid introspection problems that may
|
| occurr in some servlet container implementations. You can use the request
|
| and repsponse objects normally, accessing methods of either from the
|
| template. Just note that they aren't specifically javax.servlet.XXXX
|
| classes, if that is important to you.
|
| </blockquote>
|
|
|
| <i><code>void setContentType( HttpServletRequest,HttpServletResponse )</code></i>
|
| <blockquote>
|
| Allows you to examine the request and set the content type yourself,
|
| depending on the request or client. The default implementation sets
|
| the content type to be that either specified in the
|
| velocity.properties, if any, or the default, "text/html" if not
|
| specified in the properties.
|
| </blockquote>
|
|
|
| <i><code>void mergeTemplate( Template, Context, HttpServletResponse )</code></i>
|
| <blockquote>
|
| Allows you to produce the output stream. The VelocityServlet uses a
|
| pool of very efficient Writer classes, so this would usually be
|
| overridden in special situations.
|
| </blockquote>
|
|
|
| <i><a name="requestCleanup()"><code>void requestCleanup( HttpServletRequest,
|
| HttpServletResponse , Context )</code></a></i>
|
| <blockquote>
|
| Allows you to do any cleanup or resource reclamation at the end of the
|
| request processing. The default does nothing.
|
| </blockquote>
|
|
|
| <i><a name="error()"><code>protected void error( HttpServletRequest,
|
| HttpServletResponse, Exception )</code></a></i>
|
| <blockquote>
|
| Error handler that is called an exception occurrs in request
|
| processing. Default implementation will send a simple HTML message
|
| with stacktrace and exception information back to the user. Override
|
| for custom client messages and more advanced problem handling.
|
| </blockquote>
|
|
|
| For further information, please see the Javadoc
|
| <a href="apidocs/index.html">API documentation</a>.
|
| </p>
|
|
|
| <a name="Deployment"><strong>Deployment</strong></a>
|
|
|
| <p>
|
| When you deploy your Velocity-based servlets, you will certainly want to
|
| ensure that your properties file is used to configure the Velocity runtime.
|
| Under Tomcat, one way to accomplish this is by placing your velocity.properties
|
| file into the root directory of your web app (webapps/appname ) and then
|
| add the following to your WEB-INF/web.xml file :
|
| </p>
|
|
|
| <source><![CDATA[
|
| <servlet>
|
| <servlet-name>MyServlet</servlet-name>
|
| <servlet-class>com.foo.bar.MyServlet</servlet-class>
|
| <init-param>
|
| <param-name>properties</param-name>
|
| <param-value>/velocity.properties</param-value>
|
| </init-param>
|
| </servlet>
|
| ]]></source>
|
|
|
| <p>
|
| Assuming all is right, this will ensure that when MyServlet is loaded,
|
| it will use the velocity.properties file to initialize itself
|
| rather than relying on it's internal defaults.
|
| </p>
|
| <p>
|
| Note that Velocity uses a singleton model for it's central core Runtime
|
| class, so it is a very good idea to put the velocity-XX.jar
|
| into the WEB-INF/lib directory in all web applications that use
|
| Velocity to ensure that the web app classloader is
|
| managing your Runtime instance, rather than putting it in the CLASSPATH
|
| or the top level lib directory of the servlet runner.
|
| </p>
|
| <p>
|
| This deployment method will ensure that different web applications will
|
| not be subject to Velocity configuration conflicts.
|
| </p>
|
| </section>
|
|
|
| <section name="Using Velocity In General Applications">
|
|
|
| <p>
|
| As Velocity was designed to be a general-use tool, it is just as useful in
|
| general application programs as it is servlets. In general, you can use the
|
| same programming pattern discussed at the beginning of this guide, but there
|
| are a few utility methods provided for application use, just like we provide
|
| the VelocityServlet base class for ease of use in servlet programming.
|
| The only new responsibility you have as the application programmer is to
|
| initialize the Velocity runtime engine, but that is easy.
|
| </p>
|
|
|
| <a name="The Velocity Helper Class"><strong>The Velocity Helper Class</strong></a>
|
|
|
| <p>
|
| Velocity contains an application utility class called Velocity
|
| ( <code>org.apache.velocity.app.Velocity</code> ). The purpose of this class
|
| is to provide the necessary methods required to initialize Velocity, as well as
|
| useful utility routines to make life easier in using Velocity. This class is
|
| documented in the project's javadoc, so please look there for definitive
|
| details. This documentation is intended to be of a tutorial nature; therefore
|
| for compete API information, the Javadoc is the definitive source.
|
| </p>
|
| <p>
|
| The Velocity runtime engine is a singleton instance that provides resource,
|
| logging and other services to all Velocity users running in the same JVM.
|
| Therefore, the runtime engine is initialized only once. You can attempt to
|
| initialize Velocity more than once, but only the first initialization will
|
| apply. The rest of the attempts will be ignored. The Velocity utility
|
| class currently provides five methods used in configuration of the runtime engine.
|
| </p>
|
|
|
| <p>
|
| The five configuration methods are :
|
| </p>
|
|
|
| <ul>
|
|
|
| <li><code>setProperty( String key, Object o )</code><br/>
|
| Sets the property <code>key</code> with the value <code>o</code>. The value
|
| is typically a String, but in special cases can also be a comma-separated
|
| list of values (in a single String, ex."foo, bar, woogie") as well as other
|
| things that will arise.
|
| </li>
|
|
|
| <li><code>Object getProperty( String key )</code><br/>
|
| Returns the value of the property key. Note that you must be aware of the
|
| type of the return value, as they can be things other than Strings.
|
| </li>
|
|
|
| <li><code>init()</code><br/>
|
| Initializes the runtime with the default properties provided in the
|
| distribution.(These are listed below in the section pertaining to
|
| properties.)
|
| </li>
|
|
|
| <li><code>init( Properties p )</code><br/> Initialize the runtime with the
|
| properties contained in the <code>java.util.Properties</code> object passed
|
| as an argument.
|
| </li>
|
|
|
| <li><code>init( String filename )</code><br/> initilizes the runtime
|
| using the properties found in the properties file filename
|
| </li>
|
|
|
| </ul>
|
|
|
| <p>
|
| Note that in each case, the default properties will be used as a base
|
| configuration, and any additional properties specified by the application
|
| will replace individual defaults. Any default properties not overwritten
|
| will remain in effect. This has the benefit that only the properties
|
| you are interested in changing need to be specified, rather
|
| than a complete set.
|
| </p>
|
|
|
| <p>
|
| Another thing to note is that the <code>init()</code> calls may be called
|
| more than once without harm in an application. However, the first call to any
|
| of the <code>init()</code> functions will configure the engine with the
|
| configuration properties set at that point, and any further configuration
|
| changes or <code>init()</code> calls will be ignored.
|
| </p>
|
|
|
| <p>
|
| The most common approaches to initializing Velocity will be something like :
|
| </p>
|
|
|
| <ol>
|
| <li> Setup the configuration values you wish to set in a file in the same
|
| format as org/apache/velocity/runtime/defaults/velocity.properties
|
| (the default set), or in a <code>java.util.Properties</code>, and then
|
| call either <code>init( filename )</code> or <code>init( Properties )</code>
|
| </li>
|
|
|
| <li> Set the configuration values individually using <code>setProperty()</code>
|
| and then call <code>init()</code>. This method is generally used by more advanced
|
| applications that already have their own configuration management system -
|
| this allows the application so configure Velocity based upon values it generates
|
| at runtime, for example.
|
| </li>
|
| </ol>
|
|
|
| <p>
|
| Once the runtime is initialized, you can do with it what you wish.. This mostly
|
| revolves around rendering templates into an output stream, and the Velocity
|
| utility class allows you to do this easily. Currently, here are the methods
|
| and a brief description of what they do :
|
| </p>
|
|
|
| <ul>
|
| <li>
|
| <code> evaluate( Context context, Writer out, String logTag,
|
| String instring )</code><br/>
|
| <code>evaluate( Context context, Writer writer, String logTag,
|
| InputStream instream )</code><br/>
|
| These methods will render the input, in either the form of String or
|
| InputStream to an output Writer, using a Context that you provide.
|
| This is a very convenienient method to use for token replacement of
|
| strings, or if you keep 'templates' of VTL-containing content in a
|
| place like a database or other non-file storage, or simply generate such
|
| dynamically.
|
| </li>
|
|
|
| <li>
|
| <code>invokeVelocimacro( String vmName, String namespace, String params[],
|
| Context context, Writer writer )</code><br/>
|
| Allows direct access to Velocimacros. This can also be accomplished
|
| via the <code>evaluate()</code> method above if you wish. Here you
|
| simply name the vm you wish to be called, create an array of args to the VM,
|
| a Context of data, and Writer for the output. Note that the VM args
|
| must be the 'keys' of the data objects in the Context, rather than
|
| literal data to be used as the arg. This will probably change.
|
| </li>
|
|
|
| <li>
|
| <code>mergeTemplate( String templateName, Context context, Writer writer )
|
| </code><br/>
|
| Convenient access to the normal template handling and rendering services
|
| of Velocity. This method will take care of getting and rendering the
|
| template. It will take advantage of loading the template according
|
| to the properties setting for the file resource loader, and therefore
|
| provides the advantage of file and parsed template caching that Velocity
|
| offers. This is the most efficient way to access templates,
|
| and is recommended unless you have special needs.
|
| </li>
|
|
|
| <li>
|
| <code> boolean templateExists( String name ) </code><br/>
|
| Determines if a template <code>name</code> is able to be found by
|
| the currently configured resource loaders.
|
| </li>
|
| </ul>
|
|
|
| <p>
|
| Once we know about these basic helpers, it is easy to write Java program
|
| that uses Velocity. Here it is:
|
| </p>
|
|
|
| <source><![CDATA[
|
| import java.io.StringWriter;
|
| import org.apache.velocity.app.Velocity;
|
| import org.apache.velocity.VelocityContext;
|
|
|
| public class Example2
|
| {
|
| public static void main( String args[] )
|
| {
|
| /* first, we init the runtime engine. Defaults are fine. */
|
|
|
| Velocity.init();
|
|
|
| /* lets make a Context and put data into it */
|
|
|
| VelocityContext context = new VelocityContext();
|
|
|
| context.put("name", "Velocity");
|
| context.put("project", "Jakarta");
|
|
|
| /* lets render a template */
|
|
|
| StringWriter w = new StringWriter();
|
|
|
| Velocity.mergeTemplate("testtemplate.vm", context, w );
|
| System.out.println(" template : " + w );
|
|
|
| /* lets make our own string to render */
|
|
|
| String s = "We are using $project $name to render this.";
|
| w = new StringWriter();
|
| Velocity.evaluate( context, w, "mystring", s );
|
| System.out.println(" string : " + w );
|
| }
|
| }
|
| ]]></source>
|
|
|
| <p>
|
| When we run this program, and have the template <code> testtemplate.vm</code>
|
| in the same directory as our program (because we used the default
|
| configuration properties, and the defaul place to load templates
|
| from is the current directory...), our output should be :
|
| </p>
|
|
|
| <source><![CDATA[
|
| template : Hi! This Velocity from the Jakarta project.
|
|
|
| string : We are using Jakarta Velocity to render this.
|
| ]]></source>
|
|
|
| <p>
|
| where the template we used, testtemplate.vm, is
|
| </p>
|
|
|
| <source><![CDATA[
|
| Hi! This $name from the $project project.
|
| ]]></source>
|
|
|
| <p>
|
| That's all there is to it! Note that we didn't have to use both
|
| <code>mergeTemplate()</code> and <code>evaluate()</code> in our
|
| program. They are both included there for demonstration purposes.
|
| You will probably use only one of the methods, but depending
|
| on you application requirements, you are free to do what you wish.
|
| </p>
|
|
|
| <p>
|
| This appears to be a little different from the 'fundamental pattern'
|
| that was mentioned at the beginning of this guide, but it really is the
|
| same thing. First, you are making a context and filling it with
|
| the data needed. Where this examples differs is that in the part of
|
| the above example where <code>mergeTemplate()</code> is used,
|
| <code>mergeTemplate()</code> is doing the work of getting the template
|
| and merging it for you, using the lower-level calls in the Runtime class.
|
| In the second example, you are making your template dynamically via the
|
| String, so that is analgous to the 'choose template' part of the process,
|
| and the <code>evaluate()</code> method does the merging for you using
|
| lower level calls.
|
| </p>
|
|
|
| <p>
|
| So the example above sticks to the same simply pattern of using the Velocity
|
| template engine, but the utility functions do some of
|
| the repeated drudge work, or allow you other options for your
|
| template content other than template files.
|
| </p>
|
|
|
| <a name="Exceptions"><strong>Exceptions</strong></a>
|
|
|
| <p>
|
| There are three exceptions that Velocity will throw during the parse / merge cycle.
|
| This are additional to the exceptions that will come from IO problems, etc.
|
| They are found in the package <code>org.apache.velocity.exception</code> and are:
|
| </p>
|
|
|
| <ol>
|
| <li>
|
| <code>ResourceNotFoundException</code><br/>
|
| Thrown when the resource managment system cannot find a resource (template) that
|
| was requested.
|
| </li>
|
|
|
| <li>
|
| <code>ParseErrorException</code><br/>
|
| Thrown when a VTL syntax error is found when parsing a resource (template).
|
| </li>
|
|
|
| <li>
|
| <code>MethodInvocationException</code><br/>
|
| Thrown when a method of object in the context thrown an exception during
|
| render time. This exception wraps the thrown exception and propogates it
|
| to the application. This allows you to handle problems in your own objects
|
| at runtime.
|
| </li>
|
| </ol>
|
|
|
| <p>
|
| In each case, a message is put into the runtime log. For more information,
|
| see the Javadoc API documentation.
|
| </p>
|
|
|
| <a name="Miscellaneous Details"><strong>Miscellaneous Details</strong></a>
|
|
|
| <p>
|
| While the above example used the default properties, setting your own
|
| properties is very simple. All you have to do is make a properties file
|
| somewhere and pass the name of that file to the <code>init(String)</code>
|
| method of the Velocity utility class, or make a
|
| <code>java.util.Properties</code> object, add the desired properties and
|
| values, and pass that to the <code>init(Properties)</code> method.
|
| The latter method is convenient, because you can either fill it directly
|
| from a separate properties file via the <code>load()</code> method, or even
|
| better, you can fill it dynamically from your own application / framework's
|
| property set at runtime. This gives you the freedom to combine all of the
|
| properties for your app into one properties file.
|
| </p>
|
| <p>
|
| If we wanted to use a different directory than the current directory to
|
| load our template from, we could do something like this :
|
| </p>
|
|
|
| <source><![CDATA[
|
| ...
|
|
|
| import java.util.Properties;
|
| ...
|
|
|
| public static void main( String args[] )
|
| {
|
| /* first, we init the runtime engine. */
|
|
|
| Properties p = new Properties();
|
| p.setProperty("file.resource.loader.path", "/opt/templates");
|
| Velocity.init( p );
|
|
|
| /* lets make a Context and put data into it */
|
|
|
| ...
|
| ]]></source>
|
|
|
| <p>
|
| And, assuming you have a directory <code>/opt/templates</code> and the template
|
| <code>testtemplate.vm</code> is in there, then things would work just fine.
|
| If you try this and have a problem, be sure to look at the velocity.log for
|
| information - the error messages are pretty good for figuring out what is wrong.
|
| </p>
|
| </section>
|
| |
| <section name="Application Attributes"> |
| <p> |
| <i>Application Attributes</i> are name-value pairs that can be associated with |
| a RuntimeInstance (either via the <code>VelocityEngine</code> or |
| the <code>Velocity</code> singleton) and accessed from any part of the Velocity |
| engine that has access to the RuntimeInstance. |
| </p> |
| |
| <p> |
| This feature was designed for applications that need to communicate between |
| the application layer and custom parts of the Velocity engine, such as |
| loggers, resource loaders, resource managers, etc. |
| </p> |
| |
| <p> |
| The Application Attribute API is very simple. From the application layer, there |
| is a method of the <code>VelocityEngine</code> and the <code>Velocity</code> |
| classes : |
| </p> |
| |
| <source> |
| <![CDATA[ |
| public void setApplicationAttribute( Object key, Object value ); |
| ]]> |
| </source> |
| |
| <p> |
| through which an application can store on Object under an application (or |
| internal component) specified key. There are no restrictions on the key |
| or the value. The value for a key may be set at any time - it is not required |
| that this be set before init() is called. |
| </p> |
| |
| <p> |
| Internal components can access the key-value pairs if they have access to the |
| object via the <code>RuntimeServices</code> interface, using the method |
| </p> |
| |
| <source> |
| <![CDATA[ |
| public Object getApplicationAttribute( Object key ); |
| ]]> |
| </source> |
| |
| <p> |
| Note that internal components cannot set the value of the key, just get it. |
| if the internal component must communicate information to the application layer, |
| it must do so via the Object passed as the value. |
| </p> |
| </section> |
|
|
| <section name="EventCartridge and Event Handlers">
|
|
|
| <p>
|
| Starting in version 1.1, a fine-grain event handling system was added to Velocity.
|
| The EventCartridge is a class in which you register your event handlers, and then the
|
| EventCartridge acts as the delivery agent from which the Velocity engine will
|
| access the event handlers at merge time if needed.
|
| Currently, there are 3 events that can be handled, and all are found in the
|
| <code>org.apache.velocity.app.event</code> package.
|
| </p>
|
|
|
| <p>
|
| <i><code>org.apache.velocity.app.event.NullSetEventHandler</code></i>
|
|
|
| <blockquote>
|
| When a #set() results in a null assignment, this is normally
|
| logged. The <code>NullSetEventHandler</code> allows you to 'veto' the
|
| logging of this condition.
|
| <br/>
|
| <pre>
|
| public interface NullSetEventHandler extends EventHandler
|
| {
|
| public boolean shouldLogOnNullSet( String lhs, String rhs );
|
| }
|
| </pre>
|
| </blockquote>
|
|
|
| <i><code>org.apache.velocity.app.event.ReferenceInsertionEventHandler</code></i>
|
| <blockquote>
|
| A <code>ReferenceInsertionEventHandler</code> allows the
|
| developer to intercept each write of a reference ($foo) value to the output
|
| stream and modify that output.
|
| <pre>
|
| public interface ReferenceInsertionEventHandler extends EventHandler
|
| {
|
| public Object referenceInsert( String reference, Object value );
|
| }
|
| </pre>
|
| </blockquote>
|
|
|
| <i><code>org.apache.velocity.app.event.MethodExceptionEventHandler</code></i>
|
| <blockquote>
|
| When a user-supplied method throws an exception, the
|
| <code>MethodExceptionEventHandler</code> is invoked with the Class, method name
|
| and thrown Exception. The handler can either return a valid Object to be used
|
| as the return value of the method call, or throw the passed-in or new Exception,
|
| which will be wrapped and propogated to the user as a
|
| <code>MethodInvocationException</code>
|
| <pre>
|
| public interface MethodExceptionEventHandler extends EventHandler
|
| {
|
| public Object methodException( Class claz, String method, Exception e )
|
| throws Exception;
|
| }
|
| </pre>
|
| </blockquote>
|
| </p>
|
|
|
| <p>
|
| <strong>Using the EventCartridge</strong>
|
| </p>
|
|
|
| <p>
|
| Using the EventCartridge is fairly straightforward. The following abbreviated
|
| example was taken from <code>org.apache.velocity.test.misc.Test</code>.
|
| </p>
|
|
|
| <source><![CDATA[
|
| ...
|
|
|
| import org.apache.velocity.app.event.EventCartridge;
|
| import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
|
| import org.apache.velocity.app.event.MethodExceptionEventHandler;
|
| import org.apache.velocity.app.event.NullSetEventHandler;
|
|
|
| ...
|
|
|
| public class Test implements ReferenceInsertionEventHandler,
|
| NullSetEventHandler,
|
| MethodExceptionEventHandler
|
| {
|
| public void myTest()
|
| {
|
| ....
|
|
|
| /*
|
| * now, it's assumed that Test implements the correct methods to
|
| * support the event handler interfaces. So to use them, first
|
| * make a new cartridge
|
| */
|
| EventCartridge ec = new EventCartridge();
|
|
|
| /*
|
| * then register this class as it contains the handlers
|
| */
|
| ec.addEventHandler(this);
|
|
|
| /*
|
| * and then finally let it attach itself to the context
|
| */
|
| ec.attachToContext( context );
|
|
|
| /*
|
| * now merge your template with the context as you normally
|
| * do
|
| */
|
|
|
| ....
|
| }
|
|
|
| /*
|
| * and now the implementations of the event handlers
|
| */
|
| public Object referenceInsert( String reference, Object value )
|
| {
|
| /* do something with it */
|
| return value;
|
| }
|
|
|
| public boolean shouldLogOnNullSet( String lhs, String rhs )
|
| {
|
| if ( /* whatever rule */ )
|
| return false;
|
|
|
| return true;
|
| }
|
|
|
| public Object methodException( Class claz, String method, Exception e )
|
| throws Exception
|
| {
|
| if ( /* whatever rule */ )
|
| return "I should have thrown";
|
|
|
| throw e;
|
| }
|
| }
|
| ]]></source>
|
|
|
| </section>
|
|
|
| <section name="Velocity Configuration Keys and Values">
|
|
|
| <p>
|
| Velocity's runtime configuration is controlled by a set of configuration keys
|
| listed below. Generally, these keys will have values that consist of either a
|
| String, or a comma-separated list of Strings, referred to as a CSV for
|
| comma-separated values.
|
| </p>
|
|
|
| <p>
|
| There is a set of default values contained in Velocity's jar, found in
|
| /src/java/org/apache/velocity/runtime/defaults/velocity.defaults, that
|
| Velocity uses as it's configuration baseline.
|
| This ensures that Velocity will always have a 'correct' value
|
| for it's configuration keys at startup, although it may not be what you want.
|
| </p>
|
|
|
| <p>
|
| Any values specified before init() time will replace the default values.
|
| Therefore, you only have toconfigure velocity with the values for the keys
|
| that you need to change, and not worry about the rest. Further, as we add more
|
| features and configuration capability, you don't have to change your
|
| configuration files to suit - the Velocity engine will always have default
|
| values.
|
| </p>
|
|
|
| <p>
|
| Please sees the section above <a href="developer-guide.html#Using
|
| Velocity In General Applications"><b>Using Velocity In General
|
| Applications</b></a> for discussion on the configuration API.
|
| </p>
|
|
|
| <p>
|
| Below are listed the configuration keys that control Velocity's behavior.
|
| Organized by category, each key is listed with it's current default value
|
| to the right of the '=' sign.
|
| </p>
|
|
|
| <p>
|
| <strong>Runtime Log</strong>
|
| </p>
|
|
|
| <p>
|
| <code>runtime.log = velocity.log</code><br/>
|
| Full path and name of log file for error, warning,
|
| and informational messages. The location, if not absolute, is
|
| relative to the 'current directory'.
|
| </p>
|
|
|
| <p>
|
| <code>runtime.log.logsystem</code><br/>
|
| This property has no default value. It is used to give Velocity an
|
| instantiated instance of a logging class that supports the interface
|
| <code>org.apache.velocity.runtime.log.LogSystem.</code>, which allows
|
| the combination of Velocity log messages with your other application
|
| log messages. Please see the section
|
| <a href="developer-guide.html#Configuring the Log System">Configuring the Log System</a>
|
| for more information.
|
| </p>
|
|
|
| <p>
|
| <code>runtime.log.logsystem.class =
|
| org.apache.velocity.runtime.log.AvalonLogSystem</code><br/>
|
| Class to be used for the Velocity-instantiated log system.
|
| </p>
|
|
|
|
|
| <p>
|
| <code>runtime.log.error.stacktrace = false</code><br/>
|
| <code>runtime.log.warn.stacktrace = false</code><br/>
|
| <code>runtime.log.info.stacktrace = false</code><br/>
|
| Turns on stacktracing for the three error categories.
|
| These produce a large amount of log output.
|
| </p>
|
|
|
| <p>
|
| <code>runtime.log.invalid.references = true </code><br/>
|
| Property to turn off the log output when a reference isn't valid.
|
| Good thing to turn of in production, but very valuable
|
| for debugging.
|
| </p>
|
|
|
| <p>
|
| <code>runtime.log.logsystem.avalon.logger = <i>name</i> </code><br/>
|
| Allows user to specify an existing logger <i>name</i>
|
| in the Avalon hierarchy
|
| without having to wrap with a LogSystem interface. <b>Note:</b>
|
| You must also specify
|
| <code>runtime.log.logsystem.class =
|
| org.apache.velocity.runtime.log.AvalonLogSystem</code> as the default
|
| logsystem may change. There is <b>no</b> guarantee that the Avalon
|
| log system will remain the default log system.
|
| </p>
|
|
|
| <p>
|
| <strong>Character Encoding</strong>
|
| </p>
|
|
|
| <p>
|
| <code>input.encoding = ISO-8859-1</code><br/>
|
| Character encoding for input (templates). Using this, you can use
|
| alternative encoding for your templates, such as UTF-8.
|
| </p>
|
|
|
| <p>
|
| <code>output.encoding = ISO-8859-1</code><br/>
|
| Character encoding for output streams from the VelocityServlet and Anakia.
|
| </p>
|
|
|
| <p>
|
| <strong>#foreach() Directive</strong>
|
| </p>
|
|
|
| <p>
|
| <code>directive.foreach.counter.name = velocityCount</code><br/>
|
| Used in the #foreach() directive, defines the string to be used as the
|
| context key for the loop count. A template would access
|
| the loop count as $velocityCount.
|
| </p>
|
|
|
| <p>
|
| <code>directive.foreach.counter.initial.value = 1</code><br/>
|
| Default starting value for the loop counter reference in a #foreach() loop.
|
| </p>
|
|
|
| <p>
|
| <strong>#include() and #parse() Directive</strong>
|
| </p>
|
|
|
| <p>
|
| <code>directive.include.output.errormsg.start
|
| = <![CDATA[ <!-- include error : ]]> </code><br/>
|
| <code>directive.include.output.errormsg.end
|
| = <![CDATA[ see error log --> ]]></code><br/>
|
| Defines the beginning and ending tags for an in-stream error message in the
|
| case of a problem with the #include() directive. If both the .start and .end
|
| tags are defined, an error message will be output to the stream, of the
|
| form '.start msg .end' where .start and .end refer to the property values.
|
| Output to the render stream will only occur if both the .start and .end
|
| (next) tag are defined.
|
| </p>
|
| <p>
|
| <code>directive.parse.maxdepth = 10</code><br/>
|
| Defines the allowable parse depth for a template. A template may #parse()
|
| another template which itself may have a #parse() directive. This value
|
| prevents runaway #parse() recursion.
|
| </p>
|
|
|
| <p>
|
| <strong>Resource Management</strong>
|
| </p>
|
|
|
| <p>
|
| <code>resource.manager.logwhenfound = true</code><br/>
|
| Switch to control logging of 'found' messages from resource manager.
|
| When a resource is found for the first time, the resource name
|
| and classname of the loader that found it will be noted in the
|
| runtime log.
|
| </p>
|
|
|
| <p>
|
| <code>resource.loader = <name> (default = File)</code><br/>
|
| <i>Multi-valued key. Will accept CSV for value.</i> Pulic name of a
|
| resource loader to be used. This public name will then be used
|
| in the specification of the specific properties for that resource loader.
|
| Note that as a multi-valued key, it's possible to pass
|
| a value like "file, class" (sans quotes), indicating that following
|
| will be configuration values for two loaders.
|
| </p>
|
|
|
| <p>
|
| <code><name>.loader.description
|
| = Velocity File Resource Loader</code><br/>
|
| Description string for the given loader.
|
| </p>
|
|
|
| <p>
|
| <code><name>.resource.loader.class
|
| = org.apache.velocity.runtime.resource.loader.FileResourceLoader</code><br/>
|
| Name of implementation class for the loader. The default loader
|
| is the file loader.
|
| </p>
|
|
|
| <p>
|
| <code><name>.resource.loader.path = .</code><br/>
|
| <i>Multi-valued key. Will accept CSV for value.</i> Root(s) from which the
|
| loader loads templates. Templates may live in subdirectories of this root.
|
| ex. homesite/index.vm This configuration key applies currently to the
|
| FileResourceLoader and JarResourceLoader.
|
| </p>
|
|
|
| <p>
|
| <code><name>.resource.loader.cache = false</code><br/>
|
| Controls caching of the templates in the loader. Default is false, to make
|
| life easy for development and debugging. This should be set to true for
|
| production deployment. When 'true', the <code>modificationCheckInterval</code>
|
| property applies. This allows for the efficiency of caching, with the
|
| convenience of controlled reloads - useful in a hosted or ISP environment
|
| where templates can be modifed frequently and bouncing the application or
|
| servlet engine is not desired or permitted.
|
| </p>
|
|
|
| <p>
|
| <code><name>.resource.loader.modificationCheckInterval = 2</code><br/>
|
| This is the number of seconds between modification checks when caching is
|
| turned on. When this is an integer > 0, this represents the number of
|
| seconds between checks to see if the template was modified. If the
|
| template has been modified since last check, then it is reloaded and
|
| reparsed. Otherwise nothing is done. When <= 0, no modification
|
| checks will take place, and assuming that the property <code>cache</code>
|
| (above) is true, once a template is loaded and parsed the first time it is used,
|
| it will not be checked or reloaded after that until the application or
|
| servlet engine is restarted.
|
| </p>
|
|
|
|
|
| <p> To illustrate, here is an example taken right from the default Velocity
|
| properties, showing how setting up the FileResourceLoader is managed
|
| </p>
|
|
|
| <source><![CDATA[
|
| resource.loader = file
|
|
|
| file.resource.loader.description = Velocity File Resource Loader
|
| file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
|
| file.resource.loader.path = .
|
| file.resource.loader.cache = false
|
| file.resource.loader.modificationCheckInterval = 2
|
| ]]></source>
|
|
|
| <p>
|
| <strong>Velocimacro</strong>
|
| </p>
|
|
|
| <p>
|
| <code>velocimacro.library = VM_global_library.vm </code><br/>
|
| <i>Multi-valued key. Will accept CSV for value.</i>
|
| Filename(s) of Velocimacro library to be loaded when the Velocity
|
| Runtime engine starts. These Velocimacros are accessable to all
|
| templates. The file is assumed to be relative to the root of the
|
| file loader resource path.
|
| </p>
|
|
|
| <p>
|
| <code>velocimacro.permissions.allow.inline = true</code><br/>
|
| Determines of the definition of new Velocimacros via the #macro() directive
|
| in templates is allowed. The default value is true, meaning any template
|
| can define and use new Velocimacros. Note that depending on other properties,
|
| those #macro() statements can replace global definitions.
|
| </p>
|
|
|
| <p>
|
| <code>velocimacro.permissions.allow.inline.to.replace.global = false </code><br/>
|
| Controls if a Velocimacro defind 'inline' in a template can replace
|
| a Velocimacro defined in a library loaded at startup.
|
| </p>
|
|
|
| <p>
|
| <code>velocimacro.permissions.allow.inline.local.scope = false</code><br/>
|
| Controls 'private' templates namespaces for Velocimacros. When true, a #macro()
|
| directive in a template creates a Velocimacro that is accessable only from the
|
| defining template. This means that Velocimacros cannot be shared unless they
|
| are in the global or local library loaded at startup. (See above.) It also means
|
| that templates cannot interfere with each other. This property also allows a technique
|
| where there is a 'default' Velocimacro definition in the global or local library,
|
| and a template can 'override' the implementation for use within that template.
|
| This occurrs because when this property is true, the template's namespace is
|
| searched for a Velocimacro before the global namespace, therefore allowing
|
| the override mechanism.
|
| </p>
|
| <p>
|
| <code>velocimacro.context.localscope = false</code><br/>
|
| Controls whether reference access (set/get) within a Velocimacro will change
|
| the context, or be of local scope in that
|
| Velocimacro.
|
| </p>
|
|
|
| <p>
|
| <code>velocimacro.library.autoreload = false</code><br/>
|
| Controls Velocimacro library autoloading. When set to <code>true</code>
|
| the source Velocimacro library for an invoked Velocimacro will be checked
|
| for changes, and reloaded if necessary. This allows you to change and
|
| test Velocimacro libraries without having to restart your application or
|
| servlet container, just like you can with regular templates.
|
| This mode only works when caching is <i>off</i>
|
| in the resource loaders (e.g. <code>file.resource.loader.cache = false</code> ).
|
| This feature is intended for development, not for production.
|
| </p>
|
|
|
| <p>
|
| <strong>String Interpolation</strong>
|
| </p>
|
|
|
| <p>
|
| <code>runtime.interpolate.string.literals = true</code><br/>
|
| Controls interpolation mechanism of VTL String Literals. Note that a VTL
|
| StringLiteral is specifically a string using double quotes that is used
|
| in a #set() statement, a method call of a reference, a parameter to a VM,
|
| or as an argument to a VTL directive in general. See the VTL reference for
|
| further information.
|
| </p>
|
|
|
| <p>
|
| <strong>Runtime Configuration</strong>
|
| </p>
|
|
|
| <p>
|
| <code>parser.pool.size = 20</code><br/>
|
| This property sets the number of parsers that Velocity will
|
| create at startup and keep in a pool. The default of 20 parsers
|
| should be more than enough for most uses. In the event
|
| that Velocity does run out of parsers, it will indicate
|
| so in the log, and
|
| dynamically create them as needed. Note that they will not
|
| be added to the pool. This is a slow operation compared to
|
| the normal parser pooling, but this is considered an
|
| exceptional condition. If you see a log message, please
|
| increment this property.
|
| </p>
|
|
|
| </section>
|
|
|
| <section name="Configuring the Log System">
|
|
|
| <p>
|
| Velocity has a few nice logging features to allow both simplicity and
|
| flexibility. Without any extra configuration, Velocity will setup a
|
| file-based logger that will output all logging messages to a file
|
| called <code>velocity.log</code> in the 'current directory' where
|
| Velocity was initialized. For more advanced users, you may integrate
|
| your current logging facilities with Velocity to have all log messages
|
| sent to your logger.
|
| </p>
|
|
|
| <p>
|
| Starting with version 1.3, Velocity will automatically use either the
|
| <a href="http://jakarta.apache.org/avalon/logkit/index.html">
|
| Jakarta Avalon Logkit</a> logger, or the
|
| <a href="http://jakarta.apache.org/log4j/">Jakarta Log4j</a> logger.
|
| It will do so by using whatever it finds in the current classpath, starting
|
| first with Logkit. If Logkit isn't found, it tries Log4j.
|
| </p>
|
|
|
| <p>
|
| To utilize this feature, simply use the 'non-dependency' Velocity jar
|
| (because Logkit is baked into the jar with dependencies) and place
|
| either the logkit or log4j jar in your classpath.
|
| </p>
|
|
|
| <p>
|
| In general, you have the following logging options :
|
| </p>
|
|
|
| <ul>
|
|
|
| <li>
|
| <b>Default Configuration</b><br/>
|
| By default, Velocity will create a file-based logger in the current
|
| directory. See the note above regarding automatic detection of
|
| Logkit or Log4j to use as the default logging system.
|
| </li>
|
| |
| <li> |
| <b>Existing Log4j Category</b><br/> |
| Starting with version 1.3, Velocity will log it's output to an existing |
| Log4j Category setup elsewhere in the application. To use this feature |
| you must |
| <ol> |
| <li> |
| Make sure that the Log4j jar is in your classpath. (You would do this |
| anyway since you are using Log4j in the application using Velocity.) |
| </li> |
| <li> |
| Configure Velocity to use the <code>SimpleLog4jLogSystem</code> class. |
| </li> |
| <li> |
| Specify the name of the existing Category to use via the |
| 'runtime.log.logsystem.log4j.category' property. |
| </li> |
| </ol> |
| |
| This approach replaces and deprecates the older <code>Log4JLogSystem</code> |
| class. To see how this is done in code, see the example below. |
| </li> |
|
|
| <li>
|
| <b>Custom Standalone Logger</b><br/>
|
| You can create a custom logging class - you simply must implement the
|
| interface <code>org.apache.velocity.runtime.log.LogSystem</code> and
|
| then simply set the configuration property
|
| <code>runtime.log.logsystem.class</code> with the
|
| classname, and Velocity will create an instance of that class at init time.
|
| You may specify the classname as you specify any other properties. See
|
| the information on the
|
| <a href="developer-guide.html#Using Velocity In General Applications">
|
| Velocity helper class</a> as well as the
|
| <a href="developer-guide.html#Velocity Configuration Keys and Values">
|
| configuration keys and values.</a>
|
| Please note that through oversight, the interface to
|
| <code>org.apache.velocity.runtime.log.LogSystem</code>
|
| was changed in v1.2 to support the separable instances of the Velocity
|
| runtime. If you have an exisiting pre v1.2 custom logger that is going
|
| to be instantiated by the Velocity LogManager, you must add the
|
| <code>init( RuntimeServices )</code> method.
|
| </li>
|
|
|
| <li>
|
| <b>Integrated Logging</b><br/>
|
| You can integrate Velocity's logging capabilities with your applications
|
| existing logging system, simply by implementing the
|
| <code>org.apache.velocity.runtime.log.LogSystem</code> interface. Then,
|
| pass an instance of your logging class to Velocity via the
|
| <code>runtime.log.logsystem</code> configuration key before
|
| initializing the Velocity engine,
|
| and Velocity will log messages to your applications logger.
|
| See the information on the
|
| <a href="developer-guide.html#Using Velocity In General Applications">Velocity helper class</a>
|
| as well as the
|
| <a href="developer-guide.html#Velocity Configuration Keys and Values">configuration keys and values.</a>
|
| </li>
|
|
|
| </ul>
|
|
|
| <a name="Using Log4j With Existing Category"><strong>Using Log4j With Existing Category</strong></a> |
| |
| <p> |
| Here is an example of how to configure Velocity to log to an existing Log4j |
| Category. |
| </p> |
| |
| <source><![CDATA[ |
| import org.apache.velocity.app.VelocityEngine; |
| import org.apache.velocity.runtime.RuntimeConstants; |
| |
| import org.apache.log4j.Category; |
| import org.apache.log4j.BasicConfigurator; |
| |
| public class Log4jCategoryExample |
| { |
| public static String CATEGORY_NAME = "velexample"; |
| |
| public static void main( String args[] ) |
| throws Exception |
| { |
| /* |
| * configure log4j to log to console |
| */ |
| |
| BasicConfigurator.configure(); |
| |
| Category log = Category.getInstance( CATEGORY_NAME ); |
| |
| log.info("Hello from Log4jCategoryExample - ready to start velocity"); |
| |
| /* |
| * now create a new VelocityEngine instance, and |
| * configure it to use the category |
| */ |
| |
| VelocityEngine ve = new VelocityEngine(); |
| |
| ve.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, |
| "org.apache.velocity.runtime.log.SimpleLog4JLogSystem" ); |
| |
| ve.setProperty("runtime.log.logsystem.log4j.category", CATEGORY_NAME); |
| |
| ve.init(); |
| |
| log.info("this should follow the initialization output from velocity"); |
| } |
| } |
| ]]></source> |
| |
| <p> |
| Note that the above example can be found in <code>examples/logger_example</code>. |
| </p> |
| |
| <a name="Simple Example of a Custom Logger"><strong>Simple Example of a Custom Logger</strong></a>
|
|
|
| <p>
|
| Here is an example of how to use an instantiation of your class that implements |
| Velocity's logging system as the logger. Note that we are not passing the name |
| of the class to use, but rather a living, existing instantiation of the class |
| to be used. All that is required is that it support the |
| <code>LogSystem</code> interface. |
|
|
| </p>
|
|
|
| <source><![CDATA[
|
| import org.apache.velocity.runtime.log.LogSystem;
|
| import org.apache.velocity.runtime.RuntimeServices;
|
| ...
|
|
|
| public class MyClass implements LogSystem
|
| {
|
|
|
| ...
|
|
|
| public MyClass()
|
| {
|
| ...
|
|
|
| try
|
| {
|
| /*
|
| * register this class as a logger
|
| */
|
| Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, this );
|
| Velocity.init();
|
| }
|
| catch (Exception e)
|
| {
|
| /*
|
| * do something
|
| */
|
| }
|
| }
|
|
|
| /**
|
| * This init() will be invoked once by the LogManager
|
| * to give you current RuntimeServices intance
|
| */
|
| public void init( RuntimeServices rsvc )
|
| {
|
| // do nothing
|
| }
|
|
|
| /**
|
| * This is the method that you implement for Velocity to call
|
| * with log messages.
|
| */
|
| public void logVelocityMessage(int level, String message)
|
| {
|
| /* do something useful */
|
| }
|
| ...
|
| }
|
| ]]></source>
|
|
|
| </section>
|
|
|
| <section name="Configuring Resource Loaders">
|
| |
| <a name="Resource Loaders"><strong>Resource Loaders</strong></a> |
|
|
| <p>
|
| One of the fundamental and important parts about Velocity is the resource
|
| management system and the resource loaders. They are referred to as 'resources'
|
| here rather than 'templates' because the resource management system will also
|
| handle non-template reasources, specifically things that are loaded via the
|
| #include() directive.
|
| </p>
|
|
|
| <p>
|
| The resource loader system if very flexible, allowing one or more resource
|
| loaders to be in operation at the same time. This allows tremendous
|
| flexibility in configuration and resource managment, and futher allows you
|
| to write your own resource loaders for your special needs.
|
| </p>
|
|
|
| <p>
|
| There are currently four kinds of resource loaders that are included with Velocity,
|
| each described below. Note that in the example configuration properties given,
|
| a common name for the loader is shown
|
| (ex.'file' in <code>file.resource.loader.path</code>). This 'common name'
|
| may not work for your configuration. Please read the section on
|
| <a href="developer-guide.html#Velocity Configuration Keys and Values">resource configuration properties</a>
|
| to understand how this system works. Also, each of these loaders is
|
| located in the package <code>org.apache.velocity.runtime.resource.loader</code>.
|
| </p>
|
|
|
| <ul>
|
| <li>
|
| <b>FileResourceLoader :</b> This loader gets resources from the filesystem. It's
|
| configuration properties include :
|
| <ul>
|
| <li>
|
| <code>file.resource.loader.path</code> = <path to root of templates>
|
| </li>
|
| <li>
|
| <code>file.resource.loader.cache</code> = true/false
|
| </li>
|
| <li>
|
| <code>file.resource.loader.modificationCheckInterval</code> = <seconds between checks>
|
| </li>
|
| </ul>
|
| This is the default loader, and is configured, by default to get templates from the
|
| 'current directory'. In the case of using Velocity with servlets, this can be a problem
|
| as you don't want to have to keep your templates in the directory from which you start
|
| your servlet engine. Please see the section on
|
| <a href="developer-guide.html#Using Velocity In Servlets"> developing servlets with Velocity</a>
|
| for more information.
|
| </li>
|
| <li>
|
| <b>JarResourceLoader :</b> This loader gets resource from specific jar files. It is very
|
| similar to the FileResourceLoader, except that you have the convenience of bundling
|
| your templates into jars. The properties are identical, except for
|
| <code>jar.resource.loader.path</code>, where you provide the full location of
|
| the jar(s) you wish to load resources from. To specify a jar for the loader.path
|
| you use the standard JAR URL syntax of <code>java.net.JarURLConnection</code>.
|
| </li>
|
| <li>
|
| <b>ClasspathResourceLoader :</b> This loader gets resources from the classloader.
|
| In general, this means that the ClasspathResourceLoader will load
|
| templates placed in the classpath (in jars, for example)
|
| While the
|
| classpath is a source of great pain and suffering in general, it is a very useful
|
| mechanism when working on a Servlet Spec 2.2 (or newer) compliant servlet runner.
|
| <a href="http://jakarta.apache.org/tomcat/">Tomcat</a>
|
| is an example of such. To use this loader effectively, all you must do is
|
| jar your templates, and put that jar into the WEB-INF/lib directory of your
|
| webapp. There are no configuration options to worry about, nor is the absolute vs.
|
| relative path an issue, as it is with Jar and File resource loaders.
|
| Again, please note that the ClasspathResourceLoader is not only for use with a
|
| servlet container, but can be used in any application context.
|
| </li>
|
|
|
| <li>
|
| <b>DataSourceResourceLoader :</b> This loader will load resources from a DataSource
|
| such as a database. This loader is not built as part of the standard build
|
| as it requires J2EE support. To build this loader, please download the J2EE
|
| distribution, move the j2ee.jar into the <code>build/lib</code> directory,
|
| and then build the new velocity jar with the <code>jar-j2ee</code> build target.
|
| For more information on this loader, please see the javadoc for the class
|
| <code>org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader</code>.
|
| </li>
|
|
|
| </ul>
|
|
|
| <a name="Configuration Examples"><strong>Configuration Examples</strong></a>
|
|
|
| <p>
|
| Configuring the resource loaders for Velocity is straightforward.
|
| The properties that control the are listed in the
|
| <a href="developer-guide.html#Configuring Resource Loaders">resource configuration</a>
|
| section, for further reference.
|
| </p>
|
|
|
| <p>
|
| The first step in configuring one or more resource loaders is do
|
| 'declare' them by name to Velocity. Use the property
|
| <code>resource.loader</code> and list one or more loader names.
|
| You can use anything you want - these names are used to associate
|
| configuration properties with a given loader.
|
| </p>
|
|
|
| <source><![CDATA[
|
| resource.loader = file
|
| ]]></source>
|
|
|
| <p>
|
| That entry declares that we will have a resource loader known as 'file'.
|
| The next thing to do is to set the important properties. The most critical
|
| is to declare the class to use as the loader :
|
| </p>
|
|
|
| <source><![CDATA[
|
| file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
|
| ]]></source>
|
|
|
| <p>
|
| In this case, we are telling velocity that we are setting up
|
| a resource loadercalled 'file', and are using the class
|
| <code>
|
| org.apache.velocity.runtime.resource.loader.FileResourceLoader
|
| </code>
|
| to be the class to use.
|
| The next thing we do is set the properties important
|
| to this loader.
|
| </p>
|
|
|
| <source><![CDATA[
|
| file.resource.loader.path = /opt/templates
|
| file.resource.loader.cache = true
|
| file.resource.loader.modificationCheckInterval = 2
|
| ]]></source>
|
|
|
| <p>
|
| Here, we set a few things. First, we set the path to find
|
| the templates to be <code>/opt/templates</code>. Second, we
|
| turned caching on, so that after a template or static file
|
| is read in, it is cached in memory. And finally, we set
|
| the modification check interval to 2 seconds, allowing Velocity
|
| to check for new templates.
|
| </p>
|
|
|
| <p>
|
| Those are the basics. What follows are a few examples of different configuraitons.
|
| </p>
|
|
|
| <p>
|
| <b>Do-nothing Default Configuration : </b> As the name says, there is nothing
|
| you have to do or configure to get the default configuration. This configuration
|
| uses the FileResourceLoader with the current directory as the default resource
|
| path, and caching is off. As a properties set, this is expressed as :
|
| </p>
|
|
|
| <source><![CDATA[
|
| resource.loader = file
|
|
|
| file.resource.loader.description = Velocity File Resource Loader
|
| file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
|
| file.resource.loader.path = .
|
| file.resource.loader.cache = false
|
| file.resource.loader.modificationCheckInterval = 0
|
| ]]></source>
|
|
|
| <p>
|
| <b>Multiple Template Path Configuration : </b> This configuration
|
| uses the FileResourceLoader with several directories as 'nodes' on the
|
| template search path. We also want to use caching, and have the templates
|
| checked for changes in 10 second intervals. As a properties set, this is expressed as :
|
| </p>
|
|
|
| <source><![CDATA[
|
| resource.loader = file
|
|
|
| file.resource.loader.description = Velocity File Resource Loader
|
| file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
|
| file.resource.loader.path = /opt/directory1, /opt/directory2
|
| file.resource.loader.cache = true
|
| file.resource.loader.modificationCheckInterval = 10
|
| ]]></source>
|
|
|
| <p>
|
| <b>Multiple Loader Configuration :</b> This configuration sets up
|
| three loaders at the same time, the FileResourceLoader,
|
| the ClasspathResourceLoader, and the JarResourceLoader.
|
| The loaders are set-up such that the
|
| FileResourceLoader is consulted first, then the
|
| ClasspathResourceLoader, and finally the JarResourceLoader.
|
| This would allow you to qickly
|
| drop a template into the file template area to replace on of the
|
| templates found in the classpath (usually via a jar) without
|
| having to rebuild the jar.
|
| </p>
|
|
|
| <source><![CDATA[
|
| #
|
| # specify three resource loaders to use
|
| #
|
| resource.loader = file, class, jar
|
|
|
| #
|
| # for the loader we call 'file', set the FileResourceLoader as the
|
| # class to use, turn off caching, and use 3 directories for templates
|
| #
|
| file.resource.loader.description = Velocity File Resource Loader
|
| file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
|
| file.resource.loader.path = templatedirectory1, anotherdirectory, foo/bar
|
| file.resource.loader.cache = false
|
| file.resource.loader.modificationCheckInterval = 0
|
|
|
| #
|
| # for the loader we call 'class', use the ClasspathResourceLoader
|
| #
|
| class.resource.loader.description = Velocity Classpath Resource Loader
|
| class.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
|
|
|
| #
|
| # and finally, for the loader we call 'jar', use the JarResourceLoader
|
| # and specify two jars to load from
|
| #
|
| jar.resource.loader.description = Velocity Jar Resource Loader
|
| jar.resource.loader.class = org.apache.velocity.runtime.resource.loader.JarResourceLoader
|
| jar.resource.loader.path = jar:file:/myjarplace/myjar.jar, jar:file:/myjarplace/myjar2.jar
|
| ]]></source>
|
|
|
| <p>
|
| Node that the three names 'file', 'class', and 'jar' are merely for your convenience and
|
| sanity. They can be anything you want - they are just used to associate a set of
|
| properties together. However, it is recommended that you use names that give some hint
|
| of the function.
|
| </p>
|
|
|
| <p>
|
| Note that while all three require very little configuration information
|
| for proper operation, the ClasspathResourceLoader is the simplest.
|
| </p>
|
| |
| |
| <a name="Resource Manager and Cache"></a> |
| <strong>Pluggable Resource Manager and Resource Cache</strong> |
| |
| <p> |
| The Resource Manager is the main part of the resource (template and static content) |
| management system, and is responsible for taking application requests for |
| templates, finding them in the available resource loaders, and then optionally |
| caching the parsed template. The Resource Cache is the mechanism that the |
| Resource Manager uses to cache templates for quick reuse. While the default |
| versions of these two facilities are suitable for most |
| applications, for advanced users it now is possible |
| to replace the default resource manager |
| and resource cache with custom implementations. |
| </p> |
| |
| <p> |
| A resource manager implementation must implement the |
| <code>org.apache.velocity.runtime.resource.ResourceManager</code> interface. |
| A description of the requirements of a resource manager is out of scope for |
| this document. Implementors are encouraged to review the default implementation. |
| To configure Velocity to load the replacement implementation, use the |
| configuration key : |
| </p> |
| |
| <source><![CDATA[ |
| resource.manager.class |
| ]]></source> |
| |
| <p> |
| This key is also defined as a contstant |
| <code>RuntimeConstants.RESOURCE_MANAGER_CLASS</code> |
| </p> |
| |
| <p> |
| A resource cache implementation must implement the |
| <code>org.apache.velocity.runtime.resource.ResourceCache</code> interface |
| As with the resource manager, a description of the requirements of a |
| resource manager is out of scope for |
| this document. Implementors are encouraged to review the default implementation. |
| To configure Velocity to load the replacement implementation, use the |
| configuration key : |
| </p> |
| |
| <source><![CDATA[ |
| resource.manager.cache.class |
| ]]></source> |
| |
| <p> |
| This key is also defined as a contstant |
| <code>RuntimeConstants.RESOURCE_MANAGER_CACHE_CLASS</code> |
| </p> |
| |
| </section>
|
|
|
| <section name="Template Encoding for Internationalization">
|
|
|
| <p>
|
| As of version 1.1, Velocity allows you to specify the character encoding of your
|
| template resources on a template by template basis. The normal resource
|
| API's have been extended to take the encoding as an argument :
|
| </p>
|
|
|
| <p>
|
| <code>org.apache.velocity.servlet.VelocityServlet</code> : <br/>
|
| <blockquote>
|
| <i><code> public Template getTemplate( String template, String encoding )</code></i>
|
| </blockquote>
|
| </p>
|
|
|
| <p>
|
| <code>org.apache.velocity.app.Velocity</code> : <br/>
|
| <blockquote>
|
| <i><code>public static Template getTemplate(String name, String encoding)</code></i>
|
| <br/>
|
| <br/>
|
| <i><code>public static boolean mergeTemplate( String templateName, String encoding, Context context, Writer writer )</code></i>
|
| <br/>
|
| <i><code> </code></i>
|
| </blockquote>
|
| </p>
|
|
|
| <p>
|
| The value for the <i>encoding</i> argument is the conventional encoding specification
|
| supported by your JVM, for example "UTF-8" or "ISO-8859-1". For the official names
|
| for character sets, see <a href="http://www.iana.org/assignments/character-sets">here</a>.
|
| </p>
|
|
|
| <p>
|
| Note that this applies only to the encoding of the template itself - the output
|
| encoding is an application specific issue.
|
| </p>
|
|
|
| </section>
|
|
|
| <section name="Velocity and XML">
|
|
|
| <p>
|
| Velocity's flexibility and simple template language makes it an ideal environment
|
| for working with XML data. <a href="anakia.html">Anakia</a> is an example of how
|
| Velocity is used to replace XSL for rendering output from XML. The Velocity site,
|
| including this documentation, is generated from XML source using Anakia.
|
| The Jakarta site is also rendered using Anakia.
|
| </p>
|
|
|
| <p>
|
| Generally, the pattern for dealing with XML in Velocity is to use something like
|
| <a href="http://www.jdom.org/">JDOM</a> to process your XML into a data structure with
|
| convenient Java access. Then, you produce templates that access data directly
|
| out of the XML document - directly though the JDOM tree. For example, start
|
| with an XML document such as :
|
| </p>
|
|
|
| <source><![CDATA[
|
| <?xml version="1.0"?>
|
|
|
| <document>
|
| <properties>
|
| <title>Developer's Guide</title>
|
| <author email="geirm@apache.org">Velocity Documentation Team</author>
|
| </properties>
|
| </document>
|
| ]]></source>
|
|
|
| <p>
|
| Now make a little Java program that includes code similar to:
|
| </p>
|
|
|
| <source><![CDATA[
|
| ...
|
|
|
| SAXBuilder builder;
|
| Document root = null;
|
|
|
| try
|
| {
|
| builder = new SAXBuilder( "org.apache.xerces.parsers.SAXParser" );
|
| root = builder.build("test.xml");
|
| }
|
| catch( Exception ee)
|
| {}
|
|
|
| VelocityContext vc = new VelocityContext();
|
| vc.put("root", root );
|
|
|
| ...
|
| ]]></source>
|
|
|
| <p>
|
| (See the Anakia source for details on how to do this, or the Anakia
|
| example in the <code>examples</code> directory in the distribution.)
|
| Now, make a regular Velocity template :
|
| </p>
|
|
|
| <source><![CDATA[
|
| <html>
|
| <body>
|
| The document title is
|
| $root.getChild("document").getChild("properties").getChild("title").getText()
|
| </body>
|
| </html>
|
| ]]></source>
|
|
|
| <p>
|
| and render that template as you normally would, using the Context
|
| containing the JDOM tree. Of course, this isn't the prettiest of
|
| examples, but it shows the basics - that you can easily access XML data
|
| directly from a Velocity template.
|
| </p>
|
|
|
| <p>
|
| One real advantage of styling XML data in Velocity is that you have
|
| access to any other object or data that the application provides. You
|
| aren't limited to just using the data present in the XML document.
|
| You may add anything you want to the context to provide additional
|
| information for your output, or provide tools to help make working
|
| with the XML data easier. Bob McWhirter's
|
| <a href="http://sourceforge.net/projects/werken-xpath/"> Werken Xpath</a>
|
| is one such useful tool - an example of how it is used in Anakia can be
|
| found in <code>org.apache.velocity.anakia.XPathTool</code>.
|
| </p>
|
|
|
| <p>
|
| One issue that arises with XML and Velocity is how to deal with XML
|
| entities. One technique is to combine the use of Velocimacros
|
| when you need to render an entity into the output stream :
|
| </p>
|
|
|
| <source><![CDATA[
|
| ## first, define the Velocimacro somewhere
|
|
|
| #macro( xenc $sometext )$tools.escapeEntities($sometext)#end
|
|
|
| ## and use it as
|
|
|
| #set( $sometext = " < " )
|
| <text>#xenc($sometext)</text>
|
| ]]></source>
|
|
|
| <p>
|
| where the escapeEntities() is a method that does the escaping
|
| for you. Another trick would be to create an encoding utility that takes the
|
| context as a constructor parameter and only implements a method:
|
| </p>
|
|
|
| <source><![CDATA[
|
| public String get(String key)
|
| {
|
| Object obj = context.get(key)
|
| return (obj != null) ? Escape.getText( obj.toString() ) : "";
|
| }
|
| ]]></source>
|
|
|
| <p>
|
| Put it into the context as "xenc". Then you can use it as :
|
| </p>
|
|
|
| <source><![CDATA[
|
| <text>$xenc.sometext</text>
|
| ]]></source>
|
|
|
| <p>
|
| This takes advantage of Velocity's introspection process - it will try
|
| to call get("sometext") on the $xenc object in the Context - then the
|
| xenc object can then get the value from the Context, encode it, and
|
| return it.
|
| </p>
|
|
|
| <p>
|
| Alternatively, since Velocity makes it easy to implement custom Context
|
| objects, you could implement your own context which always applies the
|
| encoding to any string returned. Be careful to avoid rendering the
|
| output of method calls directly, as they could return objects or strings
|
| (which might need encoding). Place them first into the context with a
|
| #set() directive and the use that, for example :
|
| </p>
|
|
|
| <source><![CDATA[
|
| #set( $sometext = $jdomElement.getText() )
|
| <text>$sometext</text>
|
| ]]></source>
|
|
|
| <p>
|
| The previous suggestions for dealing with XML entities came from
|
| Christoph Reck, an active participant in the Velocity community. We are
|
| very grateful for his [unknowing] contribution to this document, and
|
| hope his ideas weren't mangled too badly :)
|
| </p>
|
|
|
| </section>
|
|
|
| <section name="FAQ (Frequently Asked Questions)">
|
|
|
| <p>
|
| In no apparent order, here are questions and answers that repeatedly arise
|
| by developers using Velocity. As we get more, we will move this out to
|
| a separate document.
|
| </p>
|
|
|
| <strong>Why Can't I Access Class Members and Constants from VTL?</strong>
|
|
|
| <p>
|
| The short answer is because we don't introspect for fields. We don't do that
|
| because we wish to promote the idea that you hide your raw data in your
|
| data objects. There are two solutions to this issue. The first is
|
| that you should be writing accessors for data elements you wish to be
|
| publicly exposed. That of course won't work for instances where you don't
|
| have the source, or simply are too lazy. There is a class for the latter
|
| group, <code>org.apache.velocity.app.FieldMethodizer</code> which introspects
|
| your class, and exposes the public static fields in a way that allows easy
|
| access from a template. Suppose you have a class :
|
| </p>
|
|
|
| <source><![CDATA[
|
| public class Foo
|
| {
|
| public static String PATH_ROOT = "/foo/bar";
|
|
|
| ....
|
| }
|
| ]]></source>
|
|
|
| <p>
|
| Then, in your code, you would put a <code>Foo</code> into the context like this
|
| </p>
|
|
|
| <source><![CDATA[
|
| context.put("myfoo", new FieldMethodizer( new Foo() ) );
|
| ]]></source>
|
|
|
| <p>
|
| Then to access this field in your template, you would simply access in
|
| a manner similar to Java :
|
| </p>
|
|
|
| <source><![CDATA[
|
| $myfoo.PATH_ROOT
|
| ]]></source>
|
|
|
| <p>
|
| If you have a crushing need to access public non-static members (or even private
|
| if you are so driven), then you would have to exend / modify the
|
| <code>FieldMethodizer</code> yourself. (And we still recommend you provide accessors....)
|
| </p>
|
|
|
| <strong>Where does Velocity look for Templates?</strong>
|
|
|
| <p>
|
| By default, without any configuration on your part, Velocity will look
|
| for templates in files, and look for them in the current directory
|
| (or relative to the current directory, if you prepend a path to your
|
| template, like 'foo/bar.vm').
|
| </p>
|
|
|
| <p>
|
| Velocity does this to make it as easy as possible to use out of the box.
|
| It has been argued that Velocity should do it from the 'root' directory, but
|
| it's never clear what that is on filesystems where there are multiple roots
|
| (like - "C:\", "D:\", etc).
|
| </p>
|
|
|
| <p>
|
| For more information, see the section on
|
| <a href="developer-guide.html#Configuring Resource Loaders">
|
| resource loaders</a> as well as the section on
|
| <a href="developer-guide.html#Velocity Configuration Keys and Values">
|
| configuration keys, values and defaults</a>.
|
| </p>
|
|
|
| </section>
|
|
|
| <section name="Summary">
|
|
|
| <p>
|
| We hope this brief guide was a helpful introduction to using Velocity in
|
| your Java projects, and thank you for you interest in Velocity. We
|
| welcome any and all comments you may have about this documentation and
|
| the Velocity template engine itself.
|
| </p>
|
| <p>
|
| Please submit all detailed, thoughtful and constructive feedback through our
|
| <a href="http://jakarta.apache.org/getinvolved/mail.html">mail lists</a>.
|
| </p>
|
| </section>
|
|
|
| <section name="Appendix 1 : Deploying the Example Servlet">
|
|
|
| <p>
|
| A continuing source of frustration for beginning servlet users is getting
|
| all the pieces into place and working. Using a servlet engine like Tomcat or Resin
|
| is far from obvious for the first time user (and even for more experienced users...).
|
| The following are the basic instructions, to the best of our knowledge, for getting
|
| the SampleServlet example working. Note that the sample template <code>sample.vm</code>
|
| and the servlet code itself, <code>SampleServlet.java</code> are
|
| found in the <code>examples/servlet_example</code> directory. Although some servlet
|
| engines (Resin, for example) will compile the servlet for you, it would be best if
|
| you compiled the examples first. To do this, see the section on building Velocity, and
|
| use the <code>examples</code> target.
|
| </p>
|
|
|
| <p>
|
| <a name="TomcatExample"><strong>Jakarta Tomcat</strong></a>
|
| </p>
|
|
|
| <p>
|
| Setting up under <a href="http://jakarta.apache.org/tomcat/">Jakarta Tomcat</a> is fairly
|
| straightforward. The 'webapp' directory is where Tomcat automatically
|
| looks for it's 'web applications', so
|
| this is where we will set things up.
|
| </p>
|
|
|
| <ol>
|
| <li> First, make a new 'webapp' by creating a directory called <i>velexample</i>
|
| in Tomcat's webapps directory, and make
|
| a new directory structure as follows :
|
| <blockquote>
|
| velexample<br/>
|
| velexample/WEB-INF<br/>
|
| velexample/WEB-INF/lib<br/>
|
| velexample/WEB-INF/classes<br/>
|
| </blockquote>
|
| </li>
|
| <li>
|
| Put the Velocity jar into the velexample/WEB-INF/lib directory. Note that with v1.2
|
| and newer, you either have to either use the jar from the distribution (or that you
|
| build yourself) that contains all the dependencies ( ex. velocity-dep-1.2.jar) or
|
| you must add the dependency jars yourself to the WEB-INF/lib directory. Please see
|
| the section "Getting Started" and "Dependencies", above.
|
| </li>
|
| <li>
|
| Put the SampleServlet.class into the velexample/WEB-INF/classes directory
|
| </li>
|
| <li>
|
| Put the sample.vm template into the velexample directory. The SampleServlet is
|
| written to use the root of the webapp as the source of the templates, so
|
| no configuration is needed.
|
| </li>
|
| <li>
|
| At this point, you should be able to start (or restart) Tomcat and access the servlet.
|
| </li>
|
| <li>
|
| To access the servlet, point your web browser at :
|
|
|
| <blockquote>
|
| http://localhost:8080/velexample/servlet/SampleServlet
|
| </blockquote>
|
|
|
| or if that doesn't work :
|
|
|
| <blockquote>
|
| http://<your computer's ip address>:8080/velexample/servlet/SampleServlet
|
| </blockquote>
|
| </li>
|
| <li>
|
| You should see the sample output.
|
| </li>
|
| </ol>
|
|
|
| <p>
|
| <a name="ResinExample"><strong>Caucho Technology's Resin</strong></a>
|
| </p>
|
|
|
| <p>
|
| Setting up the example servlet under <a href="http://www.caucho.com">Caucho Technology's Resin</a>
|
| servlet engine is also very simple. The following instructions were tested with the version 1.2.5
|
| release. The following assume that you have unzip-ed or untar-ed the distribution, know how to start
|
| the servlet engine (something like bin/httpd.sh under unix...), and know where the doc directory is
|
| (in the root of the distribution).
|
| </p>
|
|
|
| <ol>
|
| <li>
|
| Copy the SampleServlet.class file into the doc/WEB-INF/classes directory.
|
| </li>
|
| <li>
|
| Copy the sample.vm template file into the doc/ directory
|
| </li>
|
| <li>
|
| Copy the Velocity jar (and any required dependencies - see note above in
|
| Tomcat setup section) into the doc/WEB-INF/lib directory.
|
| </li>
|
| <li>
|
| Start resin.
|
| </li>
|
| <li>
|
| To access the servlet, point your web browser at :
|
|
|
| <blockquote>
|
| http://localhost:8080/servlet/SampleServlet
|
| </blockquote>
|
|
|
| or if that doesn't work :
|
|
|
| <blockquote>
|
| http://<your computer's ip address>:8080/servlet/SampleServlet
|
| </blockquote>
|
|
|
| and you should see the output.
|
| </li>
|
| </ol>
|
|
|
| <p>
|
| Note that this appeared to be a simpler configuration - with the Tomcat example,
|
| you set up a complete, new, separate webapp, whereas the Resin instructions
|
| don't, although both should provide a sufficient setup to let you play with
|
| Velocity.
|
| </p>
|
|
|
| <p>Note that while we wish we could, we can't answer questions about the servlet
|
| engines. Please use the resources provided by the servlet engine provider.
|
| </p>
|
|
|
| <p>
|
| <a name="WebLogic"><strong>BEA WebLogic</strong></a>
|
| </p>
|
|
|
| <p>
|
| Paw Dybdahl <pdy@csg.csc.dk> contributed <a href="velocity_and_weblogic.html">this</a>
|
| description of using Velocity with WebLogic, as well as some good general suggestions and
|
| examples for working with servlets.
|
| </p>
|
| </section>
|
|
|
| </body>
|
| </document>
|