| <?xml version="1.0" encoding="UTF-8"?> |
| |
| <document> |
| |
| <properties> |
| <title>Developer's Guide</title> |
| <author email="geirm@apache.org">Velocity Documentation Team</author> |
| </properties> |
| |
| <body> |
| |
| <section name="Developer Guide - Contents" href="DeveloperGuide-Contents"> |
| |
| <p> |
| <ol> |
| |
| <li> |
| <a href="#Introduction">Introduction and Getting Started</a> |
| </li> |
| |
| <li> |
| <a href="#Resources">Resources</a> |
| </li> |
| |
| <li> |
| <a href="#HowVelocityWorks">How Velocity Works</a> |
| <ul> |
| <li><a href="#TheFundamentalPattern">The Fundamental Pattern</a></li> |
| </ul> |
| </li> |
| |
| <li> |
| <a href="#ToSingletonOrNotToSingleton...">To Singleton Or Not To Singleton...</a> |
| <ul> |
| <li><a href="#Singleton">Singleton Model</a></li> |
| <li><a href="#Separate">Separate Instance</a></li> |
| </ul> |
| </li> |
| |
| <li> |
| <a href="#TheContext">The Context</a> |
| <ul> |
| <li><a href="#TheBasics">The Basics</a></li> |
| <li><a href="#SupportforIterativeObjectsfor#foreach()">Support for Iterative Objects for #foreach()</a></li> |
| <li><a href="#ContextChaining">Context Chaining</a></li> |
| <li><a href="#ObjectsCreatedintheTemplate">Objects Created by the Template</a></li> |
| <li><a href="#OtherContextIssues">Other Context Issues</a></li> |
| </ul> |
| </li> |
| |
| <li> |
| <a href="#UsingVelocity">Using Velocity in General Applications</a> |
| <ul> |
| <li><a href="#TheVelocityHelperClass">The Velocity Helper Class</a></li> |
| <li><a href="#Exceptions">Exceptions</a></li> |
| <li><a href="#MiscellaneousDetails">Miscellaneous Details</a></li> |
| </ul> |
| </li> |
| |
| <li> |
| <a href="#ApplicationAttributes">Application Attributes</a> |
| </li> |
| |
| <li> |
| <a href="#EventCartridgeandEventHandlers">EventCartridge and Event Handlers</a> |
| </li> |
| |
| <li> |
| <a href="#VelocityConfigurationKeysandValues">Velocity Configuration Keys and Values</a> |
| </li> |
| |
| <li> |
| <a href="#Configuring Logging">Configuring Logging</a> |
| <ul> |
| <li> |
| <a href="#UsingLog4jWithExistingCategory">Using Log4j With Existing Category</a> |
| </li> |
| <li> |
| <a href="#SimpleExampleofaCustomLogger">Simple Example of a Custom Logger</a> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <a href="#ConfiguringResourceLoaders">Configuring the Resource Loaders (template loaders)</a> |
| <ul> |
| <li> |
| <a href="#ResourceLoaders">Resource Loaders</a> |
| </li> |
| <li> |
| <a href="#ConfigurationExamples">Configuration Examples</a> |
| </li> |
| <li> |
| <a href="#ResourceManagerandCache">Pluggable Resource Manager and Resource Cache</a> |
| </li> |
| </ul> |
| </li> |
| |
| <li> |
| <a href="#TemplateEncodingforInternationalization">Template Encoding for Internationalization</a> |
| </li> |
| |
| <li> |
| <a href="#VelocityandXML">Velocity and XML</a> |
| </li> |
| |
| <li> |
| <a href="#Summary">Summary</a> |
| </li> |
| |
| </ol> |
| </p> |
| </section> |
| |
| <section name="Introduction" href="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. |
| |
| <p> |
| <strong>Building Web Applications with Velocity</strong> |
| </p> |
| Velocity is often used for building web applications |
| In order to use Velocity in a web app you'll need a servlet or servlet-based |
| framework. The easiest way to get started is with |
| <a href="http://jakarta.apache.org/velocity/tools/view/">VelocityViewServlet</a> in the |
| <a href="http://jakarta.apache.org/velocity/tools/">Velocity Tools</a> |
| subproject. You can also use any of a number of |
| <a href="http://wiki.apache.org/jakarta-velocity/PoweredByVelocity">third party frameworks</a> |
| or build your own servlet using the techniques described in this document. |
| </p> |
| |
| <p> |
| We suggest you read this article on |
| <a href="../webapps.html">getting started with web applications</a> for |
| more detail on the various options. |
| </p> |
| |
| <p> |
| <strong>Downloading Velocity</strong> |
| </p> |
| |
| <p> |
| You can download the latest release version of |
| <a href="http://jakarta.apache.org/site/downloads/downloads_velocity-engine.cgi">Velocity</a> |
| or <a href="http://jakarta.apache.org/site/downloads/downloads_velocity-tools.cgi">Velocity Tools</a> |
| from the main Jakarta download site. For Velocity itself, source is included with the binary download. |
| </p> |
| |
| <p> |
| If you want to download the latest source, you can do so via the Subversion (svn) |
| source control system, or download a complete |
| <a href="http://svn.apache.org/snapshots/jakarta-velocity/">nightly snapshot.</a> |
| </p> |
| |
| <p> |
| Instructions for building Velocity from source can be found in the |
| <a href="build.html">Build</a> document. |
| </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" href="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> |
| Wiki: |
| <a href="http://wiki.apache.org/jakarta-velocity/">http://wiki.apache.org/jakarta-velocity/</a> |
| The Velocity wiki contains articles, sample code, and other community-written content. |
| </li> |
| <li> |
| Frequently Asked Questions (FAQ): |
| <a href="http://wiki.apache.org/jakarta-velocity/VelocityFAQ">http://wiki.apache.org/jakarta-velocity/VelocityFAQ</a> |
| please visit this page to read the latest FAQ and to contribute your own answers. |
| </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> |
| 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> |
| 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" href="HowVelocityWorks"> |
| |
| <p> |
| <a name="TheFundamentalPattern"><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. However, no matter how to use Velocity the above sequence is what is happening |
| either explicitly, or behind the scenes. |
| </p> |
| |
| |
| </section> |
| |
| <section name="To Singleton Or Not To Singleton..." href="ToSingletonOrNotToSingleton..."> |
| |
| <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 its 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> |
| <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" href="TheContext"> |
| |
| <a name="TheBasics"><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="SupportforIterativeObjectsfor#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="ContextChaining"><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="ObjectsCreatedintheTemplate"><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>VTL Map references are unsurprisingly stored as <code>java.util.Map</code>.</li> |
| <li> |
| Decimal numbers will be Doubles or BigDecimals in the context, integer numbers will be |
| Integer, Long, or BigIntegers, 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="OtherContextIssues"><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="#ContextChaining">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" href="UsingVelocity"> |
| |
| <p>If you are using <a href="http://jakarta.apache.org/velocity/tools/view/">VelocityViewServlet</a> |
| or other web frameworks, you may never call Velocity directly. However, if you use |
| Velocity for non-web purposes, or create your own web framework you will need |
| to directly call the Velocity Engine similar to |
| <a href="#TheFundamentalPattern">the fundamental pattern</a> shown earlier. |
| One important additional thing to remember is to initialize the Velocity Engine before |
| using it to merge templates. |
| |
| </p> |
| |
| <a name="TheVelocityHelperClass"><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="MiscellaneousDetails"><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> |
| |
| <p> |
| If you need to place objects into the Velocity properties then you cannot use |
| the Velocity.init(Properties p) method. Instead you should create a new instance |
| of the <code>org.apache.commons.collections.ExtendedProperties</code> class, copy |
| all properties from an existing Properties object into the ExtendedProperties and |
| then add new properties with your objects to the ExtendedProperties object. |
| </p> |
| |
| <source><![CDATA[ |
| ... |
| |
| VelocityEngine velocityEngine = new VelocityEngine(); |
| ExtendedProperties eprops = new ExtendedProperties(); |
| |
| // if you already have a Properties object do this |
| eprops.putAll(props); |
| |
| // Now set the property with your object instance |
| eprops.setProperty("name", object); |
| |
| ... |
| velocityEngine.setExtendedProperties(eprops); |
| velocityEngine.init(); |
| ... |
| ]]> |
| </source> |
| |
| <p> |
| You may want to also consider using the Application Attributes feature described |
| in the following section. |
| </p> |
| |
| </section> |
| |
| <section name="Application Attributes" href="ApplicationAttributes"> |
| <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" href="EventCartridgeandEventHandlers"> |
| |
| <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() rejects an assignment due to the right hand side being an invalid |
| or null reference, 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" href="VelocityConfigurationKeysandValues"> |
| |
| <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 its configuration baseline. |
| This ensures that Velocity will always have a 'correct' value |
| for its 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="#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 its 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.LogChute</code>, which allows |
| the combination of Velocity log messages with your other application |
| log messages. Please see the section |
| <a href="#Configuring Logging">Configuring Logging</a> |
| for more information. |
| </p> |
| |
| <p> |
| <code>runtime.log.logsystem.class = |
| org.apache.velocity.runtime.log.AvalonLogChute</code><br/> |
| Class to be used for the Velocity-instantiated log system. |
| </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 off 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 LogChute interface. <b>Note:</b> |
| You must also specify |
| <code>runtime.log.logsystem.class = |
| org.apache.velocity.runtime.log.AvalonLogChute</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> |
| <code>directive.foreach.maxloops = -1</code><br/> |
| Maximum allowed number of loops for a #foreach() statement. |
| </p> |
| |
| <p> |
| <strong>#set() Directive</strong> |
| </p> |
| |
| <p> |
| <code>directive.set.null.allowed = false</code><br/> |
| If true, having a right hand side of a #set() statement with |
| an invalid reference or null value will set the left hand side to null. |
| If false, the left hand side will stay the same. |
| </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.max.depth = 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.manager.cache.class</code> Declares the class to be used |
| for resource caching. The current default is |
| <code>org.apache.velocity.runtime.resource.ResourceCacheImpl</code> |
| which uses a LRU Map to prevent data from being held forever. You can |
| set the size of the LRU Map using the parameter |
| <code>resource.manager.defaultcache.size</code>. The dafault value |
| of the default cache size is currently 89. |
| </p> |
| |
| <p> |
| <code>resource.manager.defaultcache.size</code> Sets the size of the |
| default implementation of the resource manager resource cache. |
| </p> |
| |
| <p> |
| <code>resource.loader = <name> (default = file)</code><br/> |
| <i>Multi-valued key. Will accept CSV for value.</i> Public 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 parser instances 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 overflow instances as needed. Note that these |
| extra parsers will not be added to the pool, and will be discarded |
| after use. This will result in very slow operation compared to the |
| normal usage of pooled parsers, but this is considered an exceptional |
| condition. A web application using Velocity as its view engine might |
| exhibit this behavior under extremely high concurrency (such as when |
| getting Slashdotted). If you see a corresponding message referencing |
| the <code>parser.pool.size</code> property in your log files, please |
| increment this property immediately to avoid performance degradation. |
| </p> |
| |
| <p> |
| <strong>Pluggable Introspection</strong> |
| </p> |
| |
| <p> |
| <code>runtime.introspector.uberspect = |
| org.apache.velocity.util.introspection.UberspectImpl</code> |
| <br/> |
| This property sets the 'Uberspector', the introspection package that |
| handles all introspection strategies for Velocity. The default works just |
| fine, so only replace if you have something really interesting and special |
| to do. |
| </p> |
| |
| </section> |
| |
| <section name="Configuring Logging" href="Configuring Logging"> |
| |
| <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 Logger/Category</b><br/> |
| Starting with version 1.3, Velocity will log its output to an existing |
| Log4j Category setup elsewhere in the application. With version 1.5, we have |
| switched to using the Logger class, as the Category class is now deprecated |
| in Log4j. 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> |
| a) If your environment uses the Logger class, |
| configure Velocity to use the <code>Log4JLogChute</code> class. |
| b) If your system still uses the deprecated Category, you can |
| configure Velocity to use the very deprecated |
| <code>SimpleLog4JLogSystem</code> class. |
| </li> |
| <li> |
| a) If using a Logger, specify the name of the existing Logger to use via the |
| 'runtime.log.logsystem.log4j.logger' property. |
| b) If using a Category, specify the name of the existing Category to use via the |
| 'runtime.log.logsystem.log4j.category' property. |
| </li> |
| </ol> |
| |
| Note that this support for Logger is in version 1.5 of Velocity. Further, |
| in version 1.5 we removed the now-ancient and very deprecated original |
| Log4JLogSystem class and replaced with the current Log4JLogChute class which |
| uses the Logger class. We apologize for the confusion, but we needed to move |
| on. |
| </li> |
| |
| <li> |
| <b>Custom Standalone Logger</b><br/> |
| You can create a custom logging class - you just need to implement the |
| interface <code>org.apache.velocity.runtime.log.LogChute</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="#UsingVelocityInGeneralApplications"> |
| Velocity helper class</a> as well as the |
| <a href="#VelocityConfigurationKeysandValues"> |
| configuration keys and values.</a> |
| Please note that the old <code>org.apache.velocity.runtime.log.LogSystem</code> |
| interface has been deprecated for v1.5 in favor of the new LogChute interface. |
| This is due to significant upgrades to our logging code that could not be |
| supported by the LogSystem interface. But don't worry, if you specify a |
| custom class that implements the LogSystem interface, it will still work. |
| However, it will generate deprecation warnings. You should upgrade your |
| custom logger to implement LogChute as soon as possible. |
| </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.LogChute</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 application's logger. |
| See the information on the |
| <a href="#UsingVelocityInGeneralApplications">Velocity helper class</a> |
| as well as the |
| <a href="#VelocityConfigurationKeysandValues">configuration keys and values.</a> |
| </li> |
| |
| </ul> |
| |
| <a name="UsingLog4jWithExistingCategory"><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("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("follows initialization output from velocity"); |
| } |
| } |
| ]]></source> |
| |
| <p> |
| Note that the above example can be found in <code>examples/logger_example</code>. |
| </p> |
| |
| <a name="SimpleExampleofaCustomLogger"><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>LogChute</code> interface. |
| |
| </p> |
| |
| <source><![CDATA[ |
| import org.apache.velocity.runtime.log.LogChute; |
| import org.apache.velocity.runtime.RuntimeServices; |
| ... |
| |
| public class MyClass implements LogChute |
| { |
| |
| ... |
| |
| public MyClass() |
| { |
| ... |
| |
| try |
| { |
| /* |
| * register this class as a logger with the Velocity singleton |
| * (NOTE: this would not work for the non-singleton method.) |
| */ |
| 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 the 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 log(int level, String message) |
| { |
| /* do something useful */ |
| } |
| |
| /** |
| * This is the method that you implement for Velocity to |
| * call with log messages. |
| */ |
| public void log(int level, String message, Throwable t) |
| { |
| /* do something useful */ |
| } |
| |
| /** |
| * This is the method that you implement for Velocity to |
| * check whether a specified log level is enabled. |
| */ |
| public boolean isLevelEnabled(int level) |
| { |
| /* do something useful */ |
| return someBooleanValue; |
| } |
| ... |
| } |
| ]]></source> |
| |
| </section> |
| |
| <section name="Configuring Resource Loaders" href="ConfiguringResourceLoaders"> |
| |
| <a name="ResourceLoaders"><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="#VelocityConfigurationKeysandValues">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. Its |
| 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. See the documentation for your servlet or web framework (for example |
| <a href="http://jakarta.apache.org/velocity/tools/view/">VelocityViewServlet</a>) for more |
| info on how to configure the location of the Velocity templates. |
| </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="ConfigurationExamples"><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="#ConfiguringResourceLoaders">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="ResourceManagerandCache"></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> |
| |
| <p> |
| A resource cache implementation may want to limit the cache size |
| (rather than providing an unbounded cache which could consume all |
| available memory). To configure Velocity to set the size for your |
| cache, use the configuration key: |
| </p> |
| |
| <source><![CDATA[ |
| resource.manager.cache.size |
| ]]></source> |
| |
| <p> |
| This key is also defined as a contstant |
| <code>RuntimeConstants.RESOURCE_MANAGER_CACHE_SIZE</code> |
| </p> |
| |
| </section> |
| |
| <section name="Template Encoding for Internationalization" href="TemplateEncodingforInternationalization"> |
| |
| <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.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" href="VelocityandXML"> |
| |
| <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 Doc 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.getRootElement()); |
| |
| |
| ... |
| ]]></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. |
| </p> |
| |
| </section> |
| |
| <section name="Summary" href="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> |
| |
| </body> |
| </document> |