Modified: click/trunk/tools/eclipse/org.apache.click.eclipse/documentation/velocity/developer-guide.html URL: http://svn.apache.org/viewvc/click/trunk/tools/eclipse/org.apache.click.eclipse/documentation/velocity/developer-guide.html?rev=951064&r1=951063&r2=951064&view=diff ============================================================================== --- click/trunk/tools/eclipse/org.apache.click.eclipse/documentation/velocity/developer-guide.html (original) +++ click/trunk/tools/eclipse/org.apache.click.eclipse/documentation/velocity/developer-guide.html Thu Jun 3 16:44:58 2010 @@ -1,3758 +1,2873 @@ - - - - - - - - - - - - - - - - - - - - - Velocity - Developer's Guide - - - - - - - - - - - -
  - - Velocity Developers Guide - -
-
-
- - - - -
- - Contents - -
-
-

-

    - -
  1. -Introduction and Getting Started -
  2. - -
  3. -Resources -
  4. - -
  5. -How Velocity Works - -
  6. - -
  7. -To Singleton Or Not To Singleton... - -
  8. - -
  9. -The Context - -
  10. - -
  11. -Using Velocity in Servlets - -
  12. - -
  13. -Using Velocity in General Applications - -
  14. - -
  15. - Application Attributes -
  16. - -
  17. -EventCartridge and Event Handlers -
  18. - -
  19. -Velocity Configuration Keys and Values -
  20. - -
  21. -Configuring the Log System - -
  22. - -
  23. -Configuring the Resource Loaders (template loaders) - -
  24. - -
  25. -Template Encoding for Internationalization -
  26. - -
  27. -Velocity and XML -
  28. - -
  29. -FAQ (Frequently Asked Questions) -
  30. - -
  31. -Summary -
  32. - -
  33. -Appendix 1 : Deploying the Example Servlet - -
  34. - -
-

-
-

-

- - - - -
- - Introduction - -
-
-

-Velocity is a Java-based template engine, a simple and powerful development tool -that allows you to easily create and render documents that format and present -your data. In this guide, we hope to give an overview of the basics of -development using Velocity, focusing on the two main areas for Velocity usage : -

-
    -
  • servlet-based WWW development
  • -
  • general application use
  • -
-

-You will see that there is no real difference between these, other than we make -servlet development with Velocity very easy if you use our provided class -VelocityServlet as a base class for your servlet, and offer a utility class to -help with application development. -

-

-Getting Started -

-

-While this information is found elsewhere on the Velocity site and in the -documentation, it is included here for completeness. Getting Velocity running on -your computer is very easy. Note that all directory references are relative the -root of the Velocity distribution tree. -

    -
  1. - Get the Velocity distribution. This is available as a release, nightly snapshot or - directly from the CVS code repository. Any are fine, although for the latest - features, the nightly snapshot is most likely the best way. For more - information, go here. -
  2. -
  3. - If you don't have Jakarta Ant, - the Java build tool already installed, please do so. It is required for - building Velocity, although not required for using Velocity. -
  4. -
  5. - Go to the build directory in the distribution. -
  6. -
  7. - Type ant <build target> where <build target> - is one of: -
      -
    • - jar builds the complete Velocity jar in the - bin directory. This jar will be called 'velocity-X.jar', - where 'X' is the current version number. This jar does not include - necessary dependencies for Velocity. If you use this - target, you must get the Collections component jar from Jakarta Commons and add - to your CLASSPATH (or WEB-INF/lib). - If you wish to use the built-in logging or template conversion, - you must include the appropriate jars in your CLASSPATH or - webapp's WEB-INF/lib. - For convenience, you can use the jar-dep target to build - a jar with ORO, Logkit and Commons Collections included. -
    • -
    • - jar-dep builds the complete Velocity jar in - the bin directory, including necessary - support for logging from the - Jakarta - Avalon Logkit package, critical configuration support from the - Jakarta Commons - and the necesary support for WebMacro - template conversion using the - Jakarta ORO - package. -
    • -
    • - jar-core builds a slimmer Velocity jar in the - bin directory, called 'velocity-core-X.jar'. This jar - contains the core Velocity functionality, and doesn't include example - and utility things like Anakia, Texen or the VelocityServlet support - baseclass. It has the same external dependency requirements as the - regular jar target. -
    • -
    • - jar-util builds a utility Velocity jar in the - bin directory, called 'velocity-util-X.jar'. This jar - contains utility code, specifically Anakia, Texen, and the WebMacro - template conversion utility. It has the same external dependency requirements as the - regular jar target. -
    • -
    • - jar-servlet builds a utility Velocity jar in the - bin directory, called 'velocity-servlet-X.jar'. This jar - contains utility code for servlet programmers. It has the same external dependency requirements as the - regular jar target. -
    • -
    • - jar-J2EE builds a complete jar, like the 'jar' target, - that includes any components that require J2EE support. Currently, this - includes only org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader. - As usual, it is placed in the bin directory, called - 'velocity-j2ee-X.jar'. NOTE : if you wish to use this build target, you - must place (or link) a copy of j2ee.jar into the build/lib directory. - We do not provide it as part of the distribution. A good source is - http://java.sun.com/. It has the same external dependency requirements as the - regular jar target. -
    • -
    • - jar-J2EE-dep build a complete jar with J2EE support - and includes logging support from the Jakarta Avalon Logkit and - regexp support fromt the Jakarta ORO package. See the notes on the - jar-dep target, above. -
    • -
    • - examples builds the example code in the example programs - found in the examples directory. This build target will - also build the forumdemo example project. -
    • -
    • - forumdemo builds the example webapplication in the - examples/forumdemo directory. -
    • -
    • - docs builds these docs in the docs directory - using Velocity's Anakia XML transformation tool. - Allowing you to use - Velocity templates in place of stylesheets - - give it a try! Note: This target requires that the jakarta-site2 project - is located as a peer directory to the jakarta-velocity distribution directory. - Please see the note in the build.xml file for this target for further information. -
    • -
    • - jar-src bundles all the Velocity source code into a single - jar, placed in the bin directory. -
    • -
    • - javadocs builds the Javadoc class documentation in the - docs/api directory -
    • -
    • - test (after jar) will test Velocity against it's testbed - suite of test routines -
    • -
    • - help lists the build targets that are available. -
    • -
    -
  8. -
  9. - While not required, testing the build is a good idea. Use the - test target mentioned above. -
  10. -
  11. - That's it! Velocity is ready to be used. Put the jar into your classpath, or - into other appropriate places (such as the lib directory of your webapp if - using with servlets) -
  12. -
  13. - If you want to play with the examples, which is highly recommended when - getting started, use build the examples via - ant examples. -
  14. -
-

- Dependencies -

-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). -

-

-Velocity also is dependent upon a few packages for general functionality. They -are included in the build/lib 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. -

- -
-

-

- - - - -
- - Resources - -
-
-

-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 : -

-
    -
  • - The user and developer community : join us via the - mail-lists. -
  • -
  • - Mail-list archives : - http://www.mail-archive.com is a good one. Type 'velocity' into the search - box to see both our -user and -dev archives. -
  • -
  • - source code : src/java/... : all the source code to the - Velocity project -
  • -
  • - application example 1 : examples/app_example1 : a simple - example showing how to use Velocity in an application program. -
  • -
  • - application example 2 : examples/app_example2 : a simple - example showing how to use Velocity in an application program using the - Velocity application utility class. -
  • -
  • - servlet example : examples/servlet_example1 : a simple example - showing how to use Velocity in a servlet. -
  • -
  • - logger example : examples/logger_example : a simple example - showing how to create a custom logging class and register it with - Velocity to receive all log messages. -
  • -
  • - XML example : examples/xmlapp_example : 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. -
  • -
  • - event example : examples/event_example : An example that - demonstrates the use of the event handling API in Velocity 1.1 -
  • -
  • - Anakia application : examples/anakia : example application - showing how to use Velocity for creating stylesheet renderings of xml data -
  • -
  • - Forumdemo web app : examples/forumdemo : working example of a - simple servlet-based forum application -
  • -
  • - documentation : docs : all the generated documentation for the - Velocity project in html -
  • -
  • - API documentation : docs/api : the generated Javadoc - documentation for the Velocity project -
  • -
  • - templates : test/templates : a large collection of template - examples in our testbed directory, these are a great source of useage - examples of VTL, the Velocity Template Language -
  • -
  • - context example : examples/context_example : two examples - showing how the Velocity context can be extended. For advanced users. -
  • -
-

-All directory references above are relative to the distribution root directory. -

-
-

-

- - - - -
- - How Velocity Works - -
-
-

-'The Fundamental Pattern' -

-

-When using Velocity in an application program or in a servlet -(or anywhere, actually), you will generally do the following : -

-
    -
  1. 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.
  2. -
  3. Create a Context object (more on what that is later).
  4. -
  5. Add your data objects to the Context.
  6. -
  7. Choose a template.
  8. -
  9. 'Merge' the template and your data to produce the ouput.
  10. -
-

-In code, using the singleton pattern via the -org.apache.velocity.app.Velocity class, -this looks like -

-
- - - - - - - - - - - - - - - - -
-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 );
-
-
-
-

-That's the basic pattern. It is very simple, isn't it? This is generally what -happens when you use Velocity to render a template. You probably won't be -writing code exactly like this - we provide a few tools to help make it even -easier than this for both servlet and application programmers. -Later on in this guide, we will talk about using Velocity in both servlets -as well as general applications, and we discuss the tools we provide to make -things easier. In each case, though, the above sequence is what is happening -either explicitly, or behind the scenes. -

-
-

-

- - - - -
- - To Singleton Or Not To Singleton... - -
-
-

-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. -

-

-Singleton Model -

-

- This is the legacy pattern, where there is only one instance of the Velocity - engine in the JVM (or web application, depending) that is shared by all. - This is very convenient as it - allows localized configuration and sharing of resources. For example, this - is a very appropriate model for use in a Servlet 2.2+ compliant web application - as each web application can have it's own instance of Velocity, allowing - that web application's servlet to share resources like templates, a logger, etc. - The singleton is accessable via the org.apache.velocity.app.Velocity - class, and and example of use : -

-
- - - - - - - - - - - - - - - - -
-
-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");
-
-
-

-Please note that the Singleton model is used in the -org.apache.velocity.servlet.VelocityServlet base class, -a utility class provided with the distribution to make writing servlets -easier. While extending this class is the most common and convenient -way to write servlets using Velocity, you are free to not use this -class if you needs require something different. -

-

-Separate Instance -

-

- 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 org.apache.velocity.app.VelocityEngine - class. An example, which parallels the above singleton example, looks - like : -

-
- - - - - - - - - - - - - - - - -
-
-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");
-
-
-

-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. -

-

-As a programmer, the classes you should use to interact with the Velocity -internals are the org.apache.velocity.app.Velocity class if -using the singleton model, or org.apache.velocity.app.VelocityEngine -if using the non-singleton model ('separate instance'). -

-

-At no time should an application use the internal Runtime, RuntimeConstants, -RuntimeSingleton or RuntimeInstance classes in the -org.apache.velocity.runtime 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 org.apache.velocity.app package, and are the -Velocity and VelocityEngine classes. If anything is -missing or needed from those classes, do not hesitate to suggest changes - these -classes are intended for the application developer. -

-
-

-

- - - - -
- - The Context - -
-
- The Basics -

-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 - references. 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. -

-

-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. -

-

-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. -

-

-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 -

-
- - - - - - - - - - - - - - - - -
-public Object put(String key, Object value);
-public Object get(String key);
-
-
-

-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. -

-

-That's really all there is to basic context operations. For more information, -see the API documentation included in the distribution. -

-

-Support for Iterative Objects for -#foreach() -

-

-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 #foreach() directive. -

-
    - -
  • Object [] 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. -
  • - -
  • java.util.Collection Velocity will use the -iterator() method to get an Iterator to use in the loop, -so if you are implementing a Collection interface on your object, please -ensure that iterator() returns a working Iterator. -
  • - -
  • java.util.Map Here, Velocity depends upon the -values() method of the interface to get a Collection -interface, on which iterator() is called to retrieve an Iterator -for the loop. -
  • - -
  • java.util.Iterator 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. -
  • - -
  • java.util.Enumeration USE WITH CAUTION : Like -java.util.Iterator, 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. -
  • - -
-

-In the case of the Iterator and Enumeration, 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. -

-

-There are good reasons to use the java.util.Iterator 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: -

-
- - - - - - - - - - - - - - - - -
-Vector v = new Vector();
-v.addElement("Hello");
-v.addElement("There");
-
-context.put("words", v.iterator() );
-
-
-

-where the Iterator itself is placed into the context. Instead, if you -simply did: -

-
- - - - - - - - - - - - - - - - -
-context.put("words", v );
-
-
-

-then all would be fine: Velocity would figure out that Vector implement -Collection (via List), and therefore will find the iterator() -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 #foreach(), Velocity has -no way of getting a new one to use for the next #foreach() -it is used in. The result is no output from any subsequent -#foreach() blocks using that reference. -

-

-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. -

- Context Chaining -

-An innovative feature of Velocity's context design is the concept -of context chaining. Also sometimes referred to as -context wrapping, this advanced feature allows you to connect -separate contexts together in a manner that makes it appear as one -'contiguous' context to the template. -

-

-This is best illustrated by an example : -

-
- - - - - - - - - - - - - - - - -
-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 );
-
-
-

-In the code above, we have set up context2 such that it chains -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". -

-

-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'. -

-

-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 #set() 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. -

-

-This feature has many uses, the most common so far is providing layered -data access and toolsets. -

-

-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 org.apache.velocity.context -to see how the provided contexts are put together. Futher, there are a few -examples in the examples/context_example directory in the -distribution which show alternate implementations, including [a goofy] one -that uses a database as the backing storage. -

-

-Please note that these examples are unsupported and are there for -demonstration/educational purposes only. -

- Objects Created in the -Template -

- There are two common situations where the Java code must deal with objects - created at runtime in the template : -

-

-When a template author calls a method of an object placed into -the context by Java code. -

-
- - - - - - - - - - - - - - - - -
-#set($myarr = ["a","b","c"] )
-$foo.bar( $myarr )
-
-
-

-When a template adds objects to the context, the Java code can access -those objects after the merge process is complete. -

-
- - - - - - - - - - - - - - - - -
-#set($myarr = ["a","b","c"] )
-#set( $foo = 1 )
-#set( $bar = "bar")
-
-
-

-Dealing with these cases if very straighforward, as there are just a few -things to know: -

-
    -
  • - The VTL RangeOperator [ 1..10 ] and ObjectArray ["a","b"] are - java.util.ArrayList 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. -
  • -
  • - Numbers will be Integers in the context, and strings will be, of course, Strings. -
  • -
  • - Velocity will properly 'narrow' args to method calls, so calling - setFoo( int i ) with an int placed into the - context via #set() will work fine. -
  • -
- Other Context Issues -

-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. -

-

-The VelocityContext will accumulate intropection information about the -syntax nodes in a template as it visits those nodes. So, in the following -situation: -

-
    -
  • - You are iterating over the same template using the same VelocityContext - object. -
  • -
  • -Template caching is off. -
  • -
  • -You request the Template from getTemplate() on each iteration. -
  • -
-

-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 : -

-
    -
  • 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. -VelocityContext useThis = new VelocityContext( populatedVC ); -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 -Context chaining for more -information. -
  • - -
  • -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. -
  • - -
  • -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. -
  • -
-
-

-

- - - - -
- - Using Velocity In Servlets - -
-
- Servlet Programming -

-The most common use of Velocity is in the area of Java Servlet programming -for the WWW. There are many reasons why Velocity is well suited for this -task, one of the primary ones is Velocity's enforcement of the -separation of the presentation (or view) layer from the -code layer. There are many resources on this subject, including - -this. -

-

-The basic technique of using Velocity in a servlet environment is very simple. -In a nutshell, all you must do is extend the provided VelocityServlet base class -and implement a single method, handleRequest(). That's really all that is -required to use Velocity in your servlet development. -

-

-As of Velocity 1.1, there are two handleRequest() methods : - -
-
- -public Template handleRequest( Context ) - -

- This is the older of the two methods. This method requires that you - return a valid Template object. If not valid, or null, - this is considered an error condition, and will result in the error() error - handling method being called. You may override the - error() if you wish. If returning a null is - something you expect to do (for example, you will want to redirect - requests) it is recommended that you use the newer method, listed - next. -
-
- -public Template handleRequest( HttpServletRequest, HttpServletResponse, Context ) - -
- This is the newer of the two handleRequest() methods, - implemented in version 1.1. The difference with this method is that - the HttpServletRequest and - HttpServletResponse objects are passed to you as - arguments to the method, as well as in the Context. The - other difference is that this method can return null to - indicate that all processing has been handled by the method, and that - Velocity should do nothing further than call - requestCleanup(). - This is extremely useful is you wish to redirect the request, for - example. -
- -As always, please refer to the Javadoc API documentation for the definitive and -latest notes. -

-

-The following code is similar to the SampleServlet.java class included -in the distribution in the examples directory. -

-
- - - - - - - - - - - - - - - - -
-public class SampleServlet extends VelocityServlet
-{
-    public Template handleRequest( HttpServletRequest request,
-                                   HttpServletResponse response,
-                                   Context context )
-    {
-
-        String p1 = "Jakarta";
-        String p2 = "Velocity";
-
-        Vector vec = new Vector();
-        vec.addElement( p1 );
-        vec.addElement( p2 );
-
-        context.put("list", vec );
-
-        Template template = null;
-
-        try
-        {
-            template =  getTemplate("sample.vm");
-        }
-        catch( ResourceNotFoundException rnfe )
-        {
-          // couldn't find the template
-        }
-        catch( ParseErrorException pee )
-        {
-          // syntax error : problem parsing the template
-        }
-        catch( Exception e )
-        {}
-
-        return template;
-    }
-}
-
-
-

-Look familiar? With the exception of creating the context object, which is -done for you by the VelocityServlet base class, and the merge() step -which is also done for you by the VelocityServlet base class, it's identical -to the basic code pattern we mentioned at the beginning of this guide. -We take the context, add our application data, and return a template. -

-

-The default Context object that is passed into the -handleRequest() methods contains both the current -HttpServletRequest and HttpServletResponse -objects. They are placed in the context using the the constants -VelocityServlet.REQUEST (value = 'req') and -VelocityServlet.RESPONSE (value = 'res') -respectively. To access and use these objects in your Java code : -

-
- - - - - - - - - - - - - - - - -
-public Template handleRequest(  Context context )
-{
-    HttpServletRequest request =  (HttpServletRequest) context.get( REQUEST );
-    HttpServletResponse response =  (HttpServletResponse) context.get( RESPONSE );
-
-   ...
-
-
-

-and in your templates: -

-
- - - - - - - - - - - - - - - - -
-#set($name = $req.getParameter('name') )
-
-
-

-For more advanced uses, the VelocityServlet base class allows you to override -parts of the handling of the request processing. The following methods may -be overridden : -
-
- - Properties loadConfiguration( ServletConfig ) -

- Allows you to override the normal configuration mechanism and add or - alter the configuation properties. This is useful for overriding or - augmenting template and log paths, to set the absolute path into the - webapp root at runtime. -
- - -Context createContext(HttpServletRequest, HttpServletResponse ) -
- Allows you to create the Context object yourself. This allows more advanced - techniques, such as chaining or pre-loading with tools or data. The default - implementation simply returns a VelocityContext object with the request - and response objects placed inside. The request and response objects are - wrapped in simple wrapper classes to avoid introspection problems that may - occurr in some servlet container implementations. You can use the request - and repsponse objects normally, accessing methods of either from the - template. Just note that they aren't specifically javax.servlet.XXXX - classes, if that is important to you. -
- -void setContentType( HttpServletRequest,HttpServletResponse ) -
- Allows you to examine the request and set the content type yourself, - depending on the request or client. The default implementation sets - the content type to be that either specified in the - velocity.properties, if any, or the default, "text/html" if not - specified in the properties. -
- -void mergeTemplate( Template, Context, HttpServletResponse ) -
- Allows you to produce the output stream. The VelocityServlet uses a - pool of very efficient Writer classes, so this would usually be - overridden in special situations. -
- -void requestCleanup( HttpServletRequest, - HttpServletResponse , Context ) -
- Allows you to do any cleanup or resource reclamation at the end of the - request processing. The default does nothing. -
- -protected void error( HttpServletRequest, - HttpServletResponse, Exception ) -
- Error handler that is called an exception occurrs in request - processing. Default implementation will send a simple HTML message - with stacktrace and exception information back to the user. Override - for custom client messages and more advanced problem handling. -
- -For further information, please see the Javadoc API documentation. -

- Deployment -

-When you deploy your Velocity-based servlets, you will certainly want to -ensure that your properties file is used to configure the Velocity runtime. -Under Tomcat, one way to accomplish this is by placing your velocity.properties -file into the root directory of your web app (webapps/appname ) and then -add the following to your WEB-INF/web.xml file : -

-
- - - - - - - - - - - - - - - - -
-<servlet>
-  <servlet-name>MyServlet</servlet-name>
-  <servlet-class>com.foo.bar.MyServlet</servlet-class>
-  <init-param>
-      <param-name>properties</param-name>
-      <param-value>/velocity.properties</param-value>
-  </init-param>
-</servlet>
-
-
-

-Assuming all is right, this will ensure that when MyServlet is loaded, -it will use the velocity.properties file to initialize itself -rather than relying on it's internal defaults. -

-

-Note that Velocity uses a singleton model for it's central core Runtime -class, so it is a very good idea to put the velocity-XX.jar -into the WEB-INF/lib directory in all web applications that use -Velocity to ensure that the web app classloader is -managing your Runtime instance, rather than putting it in the CLASSPATH -or the top level lib directory of the servlet runner. -

-

-This deployment method will ensure that different web applications will -not be subject to Velocity configuration conflicts. -

-
-

-

- - -
- - Using Velocity In General Applications - -
-
-

-As Velocity was designed to be a general-use tool, it is just as useful in -general application programs as it is servlets. In general, you can use the -same programming pattern discussed at the beginning of this guide, but there -are a few utility methods provided for application use, just like we provide -the VelocityServlet base class for ease of use in servlet programming. -The only new responsibility you have as the application programmer is to -initialize the Velocity runtime engine, but that is easy. -

- The Velocity Helper Class -

-Velocity contains an application utility class called Velocity -( org.apache.velocity.app.Velocity ). 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. -

-

-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. -

-

-The five configuration methods are : -

-
    - -
  • setProperty( String key, Object o )
    -Sets the property key with the value o. 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. -
  • - -
  • Object getProperty( String key )
    -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. -
  • - -
  • init()
    -Initializes the runtime with the default properties provided in the -distribution.(These are listed below in the section pertaining to -properties.) -
  • - -
  • init( Properties p )
    Initialize the runtime with the -properties contained in the java.util.Properties object passed -as an argument. -
  • - -
  • init( String filename )
    initilizes the runtime -using the properties found in the properties file filename -
  • - -
-

-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. -

-

-Another thing to note is that the init() calls may be called -more than once without harm in an application. However, the first call to any -of the init() functions will configure the engine with the -configuration properties set at that point, and any further configuration -changes or init() calls will be ignored. -

-

-The most common approaches to initializing Velocity will be something like : -

-
    -
  1. 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 java.util.Properties, and then -call either init( filename ) or init( Properties ) -
  2. - -
  3. Set the configuration values individually using setProperty() -and then call init(). 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. -
  4. -
-

-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 : -

-
    -
  • - evaluate( Context context, Writer out, String logTag, - String instring )
    - evaluate( Context context, Writer writer, String logTag, - InputStream instream )
    - 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. -
  • - -
  • - invokeVelocimacro( String vmName, String namespace, String params[], - Context context, Writer writer )
    - Allows direct access to Velocimacros. This can also be accomplished - via the evaluate() 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. -
  • - -
  • - mergeTemplate( String templateName, Context context, Writer writer ) -
    - 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. -
  • - -
  • - boolean templateExists( String name )
    - Determines if a template name is able to be found by - the currently configured resource loaders. -
  • -
-

-Once we know about these basic helpers, it is easy to write Java program -that uses Velocity. Here it is: -

-
- - - - - - - - - - - - - - - - -
-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 );
-    }
-}
-
-
-

-When we run this program, and have the template testtemplate.vm -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 : -

-
- - - - - - - - - - - - - - - - -
-template : Hi!  This Velocity from the Jakarta project.
-
-string : We are using Jakarta Velocity to render this.
-
-
-

-where the template we used, testtemplate.vm, is -

-
- - - - - - - - - - - - - - - - -
-Hi!  This $name from the $project project.
-
-
-

-That's all there is to it! Note that we didn't have to use both -mergeTemplate() and evaluate() 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. -

-

-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 mergeTemplate() is used, -mergeTemplate() 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 evaluate() method does the merging for you using -lower level calls. -

-

-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. -

- Exceptions -

-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 org.apache.velocity.exception and are: -

-
    -
  1. -ResourceNotFoundException
    -Thrown when the resource managment system cannot find a resource (template) that -was requested. -
  2. - -
  3. -ParseErrorException
    -Thrown when a VTL syntax error is found when parsing a resource (template). -
  4. - -
  5. -MethodInvocationException
    -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. -
  6. -
-

-In each case, a message is put into the runtime log. For more information, -see the Javadoc API documentation. -

- Miscellaneous Details -

-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 init(String) -method of the Velocity utility class, or make a -java.util.Properties object, add the desired properties and -values, and pass that to the init(Properties) method. -The latter method is convenient, because you can either fill it directly -from a separate properties file via the load() method, or even [... 4804 lines stripped ...]