Sometimes it appears you don't have a choice - technology decisions are made based on all sorts of factors, ranging from network externalities ("They're using it - I should too...") to legacy considerations ("They used it - I have to...").
In the event where the usage of JSP is mandatory, we offer a JSP tag library that lets you take advantage of the simple control directives and powerful binding to the Java object model offered by Velocity. Using Velocity in your JSPs is as simple as :
<%@ taglib uri="/WEB-INF/veltag.tld" prefix="vel" %> <html> <head> <title> Velocity! </title> </head> <jsp:useBean id="mybean" class="GeirBean" /> <body> <vel:velocity strictaccess="true"> #set($mybean = $scopetool.getPageScope("mybean")) #if(true) this is true! #end <br> $mybean.string <br> #foreach($item in $mybean.array) $item <br> #end </vel:velocity> </body> </html>
Not hard at all, is it?
What Are The Advantages?The first question asked when confronted with this subject is something along the lines of "What advantage does this have over 'pure' Velocity?". Generally, there are few reasons why one would take a Velocity-only system, and convert it to a JSP system with Velocity embedded in the JSP pages. The only reason that you might want to do this is to use an existing JSP taglib that you want to use that you don't have the source code for, or don't wish to dig out the core functional classes of a taglib you do have the source for. Otherwise, you could just drop those core classes in the Context, and access them directly from within the Velocity template.
The advantages, then, are found in a JSP-centric environment, where an existing application is already written in JSP and you wish to add or maintain functionality. Some things that Velocity provides :
<vel:velocity strictaccess="true"> #set($reqbean = $scopetool.getRequestScope("beaninrequest")) #set($newthing = $reqbean.getThing().makeBlue("azure")) $request.getSession().setAttribute("bluething", $newthing) </vel:velocity>Or something like that :)
The biggest challenge in bringing together Velocity and JSP is the 'impedance matching' related to scope and bean access. 'Scope', the fundamental storage mechanism in JSP, is a concept that comes from the underlying servlet API, where data objects are stored for later retrieval within the page, request, session or application. Velocity organizes data in a non-hierachical mechanism called the 'context', the expectation being that a controller servlet or other non-view code will manage and organize the data accessable to the template.
So to make data access in JSPs easy using the Velocity taglib, two separate approaches are offered. These two approaches, automatic access and strict access, allow two distinct ways of managing and accessing data. These two ways can also be used together.
Automatic Scope AccessThe first way, automatic access, is the most convenient. When an object is referenced (via a VTL 'reference'), the scopes are searched to find an object with the same id. The scopes are searched in the order of :
Automatic scope access is enabled by default. To use automatic scope access, just access the bean by name. For example :
<!-- place a bean in page scope --> <jsp:useBean id="mybean" class="GeirBean" /> <vel:velocity> <!-- just access by id - the context --> <!-- will find it automatically --> #foreach($item in $mybean.array) $item <br> #end </vel:velocity>
While automatic scope access is the easier of the two methods, integrating with existing applications might require using the other access mode, strict scope access, or a combination of the two.
Strict Scope AccessThe alternative (or addition to) Automatic Scope Access is something called Strict Scope Access. Strict Scope Acccess means that the Velocity Context won't search the scopes for you - you must retrieve objects directly using ScopeTool that is provided for your use in the template. This is a closer model to that of regular JSP, where the designer must be aware of the scopes that objects are stored in.
For example, the following snippet of JSP shows how the scopetool is used to
access an object in the request scope, and add it to the Velocity context.
Note how the strictaccess
property is set to true in the
<vel:velocity strictaccess="true">
tag. This tells
the Veltag taglib to not do any automatic scope searching. Note that you can
mix the two modes, leaving off (or setting to false) strictaccess
and also using the scopetool to eliminate any question about the source
of an object.
<jsp:useBean id="beaninrequest" class="GeirBean" scope="request" /> <vel:velocity strictaccess="true"> #set($reqbean = $scopetool.getRequestScope("beaninrequest")) $reqbean.string <br> #foreach($item in $reqbean.array) $item <br> #end </vel:velocity>
Again, pretty straightforward.
To use the Velocity taglib, you need to build it, as it is not
yet included in the main Velocity jar. In the Jakarta tradition,
we made it very easy to build. The code for the project is
located in the contrib section of the Subversion code repository under
/contrib/temporary/veltag
. It is under the
temporary directory as it is hoped this package will
be accepted by the
Jakarta Taglibs
project. See
here
for more about the Subversion code repository.
The Veltag taglib can be built using a new, experimental jar management tool called JJAR (Jakarta Jar Archive & Repository) which makes finding and retrieving the dependencies to build the taglib simple.
Please note that JJAR is currently a work in progress - while every effort will be made to ensure that the JJAR-based build works, it may not always be so. In that case, do it the regular way, listed below.
To build with JJAR :
/contrib/temporary/veltag
directory in the Velocity distribution.
$ ant getjarsThis will fetch JJAR and then use JJAR to fetch the dependencies du jour for Veltag.
$ant jarwhich will build the veltag-XX.jar (XX = current version).
That's it. Pretty easy.
The JJAR-Is-A-Work-In-Progress WayIn the event the JJAR-based build is broken, or you just enjoy schlepping around finding jars, do the following to build Veltag.
To build, you need the following :
/contrib/temporary/veltag/lib/
directory. Modification
of the build script is easy if they are in another location. Look for
'servlet.home' and 'velocity.home' in the
/contrib/temporary/veltag/build.xml
file.
/contrib/temporary/veltag
in the Velocity
distribution and type 'ant'. The jar should build
for you.
Using the taglib is very straightforward. The following assumes that you have setup a servlet container with JSP support, such as Tomcat, and know enough to write and view a simple JSP page. Also, all directory references are relative to the root of the veltag project, not the Velocity distribution.
To test the Velocity Taglib :
You need to copy the veltag-XX.jar to the
WEB-INF/lib
directory of your webapp. (Where XX
is the current version number.
Take the example taglib descriptor,
/examples/veltag.tld
and place in WEB-INF of your
webapp.
Finally, add<taglib> <taglib-uri>http://jakarta.apache.org/taglibs/veltag-1.0</taglib-uri> <taglib-location>/WEB-INF/veltag.tld</taglib-location> </taglib>to your web.xml file, within the <webapp> section.
If you wish to use the included example JSP, you will also need to compile
examples/SimpleBean.java
and place the resulting
SimpleBean.class
into the WEB-INF/classes
directory in your webapp.
After that, try the example JSP found in examples/
. Drop it
into the root of your webapp and view it with your browser. Enjoy!
Please direct all comments, questions, fixes and contributions to Geir Magnusson Jr. or the Velocity user list. To subscribe to the Velocity lists, read this and follow the instructions at the end.
Please note that this code is not an official part of the Velocity distribution.