The Velocity Project < Tools - View >

Velocity Tools

VelocityView

VelocityView Tools

Other Subprojects

Overview
       

VelocityView provides support for rapidly and cleanly building web applications using Velocity templates as the view layer. The project is designed with the Pull-MVC Model in mind and works well in conjunction with web application frameworks that act as the controller (e.g. Struts), but can be used quite effectively on its own for those creating simpler applications.

Key features:

  • VelocityViewServlet class - standalone servlet that renders Velocity templates. Invoked directly from web clients requests, or via servlet forwarding similar to how JSP files are rendered by JSPServlet.
  • The HttpServletRequest, HttpSession, ServletContext, and their attributes are automatically available in your templates.
  • Tools can also be made available to your templates, through a toolbox configuration file.
  • A number of useful, extendable tools for developing web applications are already provided for your convenience.
  • Logging can be directed to the log infrastructure of the Web application. (default is the logging facility provided by the Servlet API).

Using VelocityViewServlet, it becomes possible to write web applications that are independent of a particular view technology. This opens a straightforward migration path between JSP pages and Velocity templates as the view layer technology in web applications.

A typical application use-case is to provide the view rendering layer for a servlet-based web application framework. The VelocityStruts subproject uses the approach to bring Velocity templates to the Struts application framework.

Installation
       

The VelocityViewServlet needs to be installed into your servlet container so it can handle all request for *.vm (velocity template) files. There are only two additional configuration files, and they are shown in detail below.


Servlet Setup
       

The servlet configuration (web.xml) must be modified to include a reference to the VelocityViewServlet (or subclass thereof) which will perform the rendering. All *.vm files are mapped to this servlet which will populate the 'context' with Request, Session, and Application scopes plus any additional tools specified in the toolbox.xml file. The servlet will use this contextual information and the Velocity Engine to render the template file.


Note: Additional functionality can be achieved through subclassing the VelocityViewServlet, and will be discussed further in the VelocityLayoutServlet below.

web.xml

<!-- Define Velocity template compiler -->
<servlet>
  <servlet-name>velocity</servlet-name>
  <servlet-class>
    org.apache.velocity.tools.view.servlet.VelocityViewServlet
  </servlet-class>

  <!-- 
    Unless you plan to put your toolbox.xml and velocity.properties
    under different folders or give them different names, then these
    two init-params are unnecessary as of VelocityTools 1.3.  The
    VelocityViewServlet will automatically look for these files in
    the following locations.
  -->
  <init-param>
    <param-name>org.apache.velocity.toolbox</param-name>
    <param-value>/WEB-INF/toolbox.xml</param-value>
  </init-param>

  <init-param>
    <param-name>org.apache.velocity.properties</param-name>
    <param-value>/WEB-INF/velocity.properties</param-value>
  </init-param>
</servlet>

<!-- Map *.vm files to Velocity -->
<servlet-mapping>
  <servlet-name>velocity</servlet-name>
  <url-pattern>*.vm</url-pattern>
</servlet-mapping>
Velocity Configuration
       

Velocity configuration is optional, and for most applications the defaults will work fine. The velocity.properties file contains settings that affect logging, encoding, and macro settings.

The default configuration specifies the location of a 'global' Velocimacro template. This file can contain macros which will be made available to all templates.

The location of the configuration file may be specified in web.xml, but it is recommended the file be placed inside the hidden WEB-INF directory of the web application and named 'velocity.properties' which is where the VelocityViewServlet will look for it in the absence of any location specified in the web.xml. An example configuration file is included with the distribution.

Please see the Velocity User's Guide for more information on Velocity configuration.

  velocimacro.library = /WEB-INF/VM_global_library.vm
  velocimacro.permissions.allow.inline = true
  velocimacro.permissions.allow.inline.to.replace.global = false
  velocimacro.permissions.allow.inline.local.scope = false
  velocimacro.context.localscope = false

Toolbox Configuration
       

The toolbox file, WEB-INF/toolbox.xml by default, maps names of our choosing to the classes that they will represent. It's easier than that sounds.

Think about asking our friend Jon to grab us a 'wrench' from a real toolbox. Jon just needs to know which wrench we want (metric, pipe, crescent etc,). He doesn't need to know what the wrench does nor what we are planning to do with it.

The Velocity Toolbox works the same way, we must only specify which tool to assign to a name, and then the Velocity engine takes care of the rest by making any public method available to the template. For example, from the definitions below, the template could call $wrench.getSize() or $wrench.size .

PipeWrench.java

public class PipeWrench {
  public String getSize() {
	return "Large Pipe Wrench!";
  }
} 

toolbox.xml

<?xml version="1.0"?>
<toolbox>
  <tool>
     <key>wrench</key>
     <scope>application</scope>
     <class>PipeWrench</class>
  </tool>
</toolbox>

Tool Scopes

The toolbox support built into the VelocityViewServlet also provides support for specifying the scope of your tool with regards to the servlet environment. Tools may be placed within the request, session, or application scopes of your web app.

The scope that you set for your tool will determine both its lifecycle and, if the tool has a public init(Object) method, then the scope will also determine what data is passed to that method:

  • application scoped tools will be instantiated only once and then reused for each request. Due to this, it is strongly encouraged that your application scoped tools be completely threadsafe. The MathTool in the GenericTools section is a good example of tool meant to be application scoped. If an application scoped tool implements ViewTool, then the javax.servlet.ServletContext for the webapp will be passed to its init(Object) method after it is instantiated.
  • session scoped tools are instantiated once per unique session and are then reused for every request associated with that particular session. If a session scoped tool implements ViewTool, then its init(Object) method will be passed the ViewContext of the request during which the session was created.
  • request is the default scope. If no scope is specified for a <tool> in your toolbox.xml, then it will be automatically set as request scope. Tools with this scope are instantiated for every servlet request fed to the VelocityViewServlet. If a request scoped tool implements ViewTool, then its init(Object) method will be passed the current ViewContext.

You can specify the scope of your tools by adding a <scope> element to your toolbox.xml entries like this:

<tool>
   <key>math</key>
   <scope>application</scope>
   <class>org.apache.velocity.tools.generic.MathTool</class>
</tool>

Tool Request Paths

You can specify a restriction on the request URIs for which the tool will be put in the context using the <request-path> element. It can be an exact request path (matching one page) or end with the * wildard, meaning that incoming request paths need only start with the provided value for the tool to be available in the context. For instance:

<tool>
   <key>catalog</key>
   <scope>request</scope>
   <request-path>/catalog/*</request-path>
   <class>com.mycompany.tools.CatalogTool</class>
</tool>

For now, this request-path filter is only valid for request scoped tools. In VelocityTools 2.0, we plan to support this for session and application scoped tools as well.


Tool Parameters

The toolbox support built into the VelocityViewServlet also provides support for passing configuration parameters to tools that have a public void configure(java.util.Map params) method. This method will only be called if parameters have been specified for the tool.

You can specify parameters for your tools by adding a <parameter> element to your toolbox.xml entries like this:

<tool>
   <key>math</key>
   <scope>application</scope>
   <class>com.foo.tools.MyTool</class>
   <parameter name="my.parameter.name" value="my.parameter.value"/>
</tool>

Toolbox Data

In addition to specifiying arbitrary Java classes as tools to be automatically available to your templates, the toolbox support also includes the ability to specify arbitrary strings, booleans, and numbers to be automatically available in your templates. The format is as follows:

<?xml version="1.0"?>
<toolbox>
  <data type="number">
     <key>app_version</key>
     <value>0.9</value>
  </data>
  <data type="string">
     <key>app_name</key>
     <value>Jon's Tool Shop</value>
  </data>
  <data type="boolean">
     <key>debug</key>
     <value>true</value>
  </data>
</toolbox>

As with your tools, your data will be exposed to your templates under the specified key (e.g. $app_version, $app_name, $debug).


VelocityLayoutServlet
       

One derivative of the VelocityViewServlet is the VelocityLayoutServlet. This servlet performs a simplified 'two-pass render' in order to apply a shared, common layout to all of the web pages in an application.

The Struts "template" tag library does something similar, but requires a separate file to define which 'layout' file to use and which .jsp files to render into that layout. The VelocityLayoutServlet takes a simpler approach. It first renders the primary template being called (example: showDetails.vm) into a content holder variable (ex. $screen_content). Next, the servlet loads a 'layout' file. It uses the existing data, including any additional variables set or changed by the first template, to render a the layout template.

The VelocityLayoutServlet also allows you to specify an 'error' template to be displayed when an exception is thrown during the processing of a requested template. This allows you to provide a customized error screen for a more user-friendly application.

Detailed documentation here: VelocityLayoutServlet.


Examples
       

A simple application example has been included to demonstrate the use of the VelocityViewServlet with automatically loaded view tools.

To run the examples you need Tomcat 4.x, Tomcat 5.0.x, Tomcat 5.5.x, or a compatible servlet runner.

The build process automatically generates a ready-to-deploy simple.war archive file located in the examples subdirectory. Deploy (i.e. copy) this simple.war file to the webapps directory of your servlet runner and restart. Now point a web browser at the following url:

http://<your_server>:<port>/simple/


Known Issues
       

Since Tomcat 5.5 is using commons-logging as a complete logging facility, we are no longer able to direct commons-logging output to the servlet log by default. The result of this is that our example apps can no longer contain a commons-logging.properties on the classpath if we want them to work with all servlet engines.

When using Tomcat 5.5+, this means that log messages from our tools and tool management code are by default sent to the Tomcat console, rather than the servlet log. Velocity Engine and VelocityViewServlet messages will still be sent to the servlet log by default. When using other servlet engines or earlier Tomcat versions (e.g. Jetty or Tomcat 4.x), you must now add a commons-logging.properties file at the root of the classpath that contains: org.apache.commons.logging.Log=org.apache.velocity.tools.generic.log.LogSystemCommonsLog if you wish to have tool and tool management log output sent to the servlet log. If you are using Tomcat 5.5+, do NOT do that, as it will cause an infinite loop.

We plan to resolve this in future versions by removing commons-logging from our code in favor of the much improved log wrappers in Velocity Engine 1.5. In the meantime, commons-logging remains the most flexible solution.



Copyright © 1999-2003, Apache Software Foundation