You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by Serge Knystautas <sk...@gmail.com> on 2006/02/26 20:36:54 UTC
Avoid reparsing velocity templates
I'm working on a CMS that uses velocity template extensively (many
thousands of templates), and we're trying to figure out how to avoid
reparsing these templates over and over.
First idea... does anyone have experience creating alternate resource
cache implementations? I've looked at the basic cache impl that's
available, and it seems like I could very easily swap it with an LRU
Map to avoid sucking up a lot of memory... we have perhaps hundreds or
maybe thousands of templates and couldn't keep them all cached in
memory. That could help reduce reparsing on the most heavily used
templates.
Really though, something like caching the parsed templates (i.e., the
AST nodes) to disk or somehow using bytecode generation or something
to avoid reparsing my templates every time and make this much more
memory friendly... if anyone has any experience or ideas with this,
I'd greatly appreciate it.
--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by Will Glass-Husain <wg...@forio.com>.
Doesn't the source code head (1.5 prerelease) use an LRU cache?
Anyone using this want to comment?
WILL
----- Original Message -----
From: "Serge Knystautas" <sk...@gmail.com>
To: "Velocity Developers List" <ve...@jakarta.apache.org>
Sent: Sunday, February 26, 2006 11:36 AM
Subject: Avoid reparsing velocity templates
I'm working on a CMS that uses velocity template extensively (many
thousands of templates), and we're trying to figure out how to avoid
reparsing these templates over and over.
First idea... does anyone have experience creating alternate resource
cache implementations? I've looked at the basic cache impl that's
available, and it seems like I could very easily swap it with an LRU
Map to avoid sucking up a lot of memory... we have perhaps hundreds or
maybe thousands of templates and couldn't keep them all cached in
memory. That could help reduce reparsing on the most heavily used
templates.
Really though, something like caching the parsed templates (i.e., the
AST nodes) to disk or somehow using bytecode generation or something
to avoid reparsing my templates every time and make this much more
memory friendly... if anyone has any experience or ideas with this,
I'd greatly appreciate it.
--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by Serge Knystautas <sk...@gmail.com>.
On 2/27/06, Jonathan Revusky <re...@wanadoo.es> wrote:
> > Heh, if freemarker can parse Velocity templates, then maybe. Like I
> > said, I've got thousands of temlates (not to mention users) that would
> > need converting...
>
> Actually, we've got an automatic conversion tool that works fairly well,
> reads in VTL and spits out FTL. A real miracle. The modern equivalent of
> turning water into wine.
Heh, if VTL to FTL transformation is water to wine, then perhaps XML
transformation is parting the Red Sea? What templating feature is
curing leprocy or blindness? I have to argue that that would be
mathematical functions that support decimal calculations.
Now if only you had a conversion tool that would change how my users
had been trained. That'll take some real divine power.
> > Yes, it is a fair point as to whether the serializable API would be
> > faster, but I would hope so. Given the number of pages, I have to
> > turn off memory caching, so every page requires parsing.
>
> What you need, I think, is the MRU cache.
Yeah, gonna throw that in and run some performance tests. Fortunately
the cache strategy is very easy to swap out... I only wish the parser
pool management was as easy to swap out...
> > My benchmarks calculated 37ms/MB to read a file (just read into a
> > string), 754ms/MB to compile (create a Template object), and 31ms/MB
> > to merge it with a simple context. Obviously if I can eat into that
> > 700+ms/MB rate by serializing the ASTNodes or something else, then
> > that'd be great.
>
> Maybe the question is how much of the overhead in parsing VTL is in the
> lexical scanning. From what you're saying it seems that not much of it
> is in actually physically reading the file. Offhand (I could be wrong)
> it seems the gain you'd get from a binary storage format is that,
> instead of scanning ahead for #foreach and all the other tokens they are
> stored as a single byte, say.
Ergo, my idea of serialization. :)
> But probably the solution you'll implement will be some kind of MRU
> cache. Or you can just buy a lot more RAM, I guess. :-)
Yeah, unfortunately more RAM will only get me through this year. With
our growth projections, I'll need to solve this in the fall.
--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by Jonathan Revusky <re...@wanadoo.es>.
Serge Knystautas wrote:
> On 2/26/06, Jonathan Revusky <re...@wanadoo.es> wrote:
>
>>Serge Knystautas wrote:
>>
>>>I'm working on a CMS that uses velocity template extensively (many
>>>thousands of templates), and we're trying to figure out how to avoid
>>>reparsing these templates over and over.
>>
>>Have you actually determined that this is a bottleneck in your application?
>
>
> Yes. Why would I ask otherwise? :)
It wouldn't be logical, but in my experience, many people are willing to
spend quite a bit of time and energy speculating about the performance
implications of whatever without any proof that it's a real-world
bottleneck.
>
>>Well, you could look at FreeMarker. :-) I think we have a pretty good
>>MRU template caching implementation. I don't know too much about it, it
>>was written by Attila Szegedi, not me. It's probably pretty good. Attila
>>is a pretty thorough guy. This stuff is quite well tested. It's been
>>part of our stable release for several years.
>
>
> Heh, if freemarker can parse Velocity templates, then maybe. Like I
> said, I've got thousands of temlates (not to mention users) that would
> need converting...
Actually, we've got an automatic conversion tool that works fairly well,
reads in VTL and spits out FTL. A real miracle. The modern equivalent of
turning water into wine.
>
> Besides Velocity is extremely flexible and trivial to stick a
> memory-based LRU template cache. JDK 1.4 provides an LRU map, so I
> can create that with a cap instead of the default hashtable, and I've
> got an impl that I would hope is as reliable as what Attila
> implemented.
>
> But my real goal is to cache without using memory...
>
>
>>>Really though, something like caching the parsed templates (i.e., the
>>>AST nodes) to disk
>>
>>Well, you're talking about storing the AST in some format on disk, but
>>there is already a way of storing a VTL AST on disk and that is the way
>>it is stored already, as a .vtl file. I mean, it is not obvious to me
>>offhand why re-instantiating the AST from the disk in your scenario is
>>going to be that much more efficient than just reparsing the template
>>from its canonical VTL format.
>>
>>I mean, at the end of the day, you're just reading the template (in some
>>format) off the disk again. Okay, you could have a binary format for
>>storage that is a bit more efficient than the VTL text format, but how
>>much difference would it make?
>>
>>In terms of overall Velocity development, how much value added could
>>their be?
>
>
> Yes, it is a fair point as to whether the serializable API would be
> faster, but I would hope so. Given the number of pages, I have to
> turn off memory caching, so every page requires parsing.
What you need, I think, is the MRU cache.
>
> My benchmarks calculated 37ms/MB to read a file (just read into a
> string), 754ms/MB to compile (create a Template object), and 31ms/MB
> to merge it with a simple context. Obviously if I can eat into that
> 700+ms/MB rate by serializing the ASTNodes or something else, then
> that'd be great.
Maybe the question is how much of the overhead in parsing VTL is in the
lexical scanning. From what you're saying it seems that not much of it
is in actually physically reading the file. Offhand (I could be wrong)
it seems the gain you'd get from a binary storage format is that,
instead of scanning ahead for #foreach and all the other tokens they are
stored as a single byte, say.
But probably the solution you'll implement will be some kind of MRU
cache. Or you can just buy a lot more RAM, I guess. :-)
Jonathan Revusky
--
lead developer, FreeMarker project, http://freemarker.org/
>
> And beyond serialization, if Velocity templates could get translated
> into bytecode, then we've changed velocity from interpreted to
> compiled templating, much like what Resin is doing with PHP
> (http://wiki.caucho.com/Quercus). I'm not expecting someone else
> write it... Just wondering if it seemed at all feasible and/or
> querying for other people who have dealt with this.
>
> --
> Serge Knystautas
> Lokitech >> software . strategy . design >> http://www.lokitech.com
> p. 301.656.5501
> e. sergek@lokitech.com
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by "Henning P. Schmiedehausen" <hp...@intermeta.de>.
"Serge Knystautas" <sk...@gmail.com> writes:
>The problem I see is that every extends SimpleNode, which holds
>references to RuntimeServices and Parser, neither of which are really
>serializable. The RuntimeServices seems manageable since you can init
The main problem here is our entwined JavaCC dependency that cannot be
untied. I tried doing this in Dec and ended up breaking the
interface. We won't change that in the 1.x cycle. In the (vaporware)
2.x, I'm thinking about using a different parser generator. antlr
comes to mind. Oh, if I only had time... :-)
Best regards
Henning
--
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen INTERMETA GmbH
hps@intermeta.de +49 9131 50 654 0 http://www.intermeta.de/
RedHat Certified Engineer -- Jakarta Turbine Development -- hero for hire
Linux, Java, perl, Solaris -- Consulting, Training, Development
Social behaviour: Bavarians can be extremely egalitarian and folksy.
-- http://en.wikipedia.org/wiki/Bavaria
Most Franconians do not like to be called Bavarians.
-- http://en.wikipedia.org/wiki/Franconia
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by Serge Knystautas <sk...@gmail.com>.
On 2/27/06, Will Glass-Husain <wg...@forio.com> wrote:
> I took a quick look at the code. Seems like we can remove the need to
> include a reference to Parser in ASTDirective by passing in a direct
> reference to the directive instead.
Cool!
> By "init the top node" method, I assume you mean we would require the user
> to call init(RuntimeServices) after deserializing?
Yes, the cache implementation would do it (if that's what you mean by user).
--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by Will Glass-Husain <wg...@forio.com>.
I took a quick look at the code. Seems like we can remove the need to
include a reference to Parser in ASTDirective by passing in a direct
reference to the directive instead.
By "init the top node" method, I assume you mean we would require the user
to call init(RuntimeServices) after deserializing?
WILL
----- Original Message -----
From: "Serge Knystautas" <sk...@gmail.com>
To: "Velocity Developers List" <ve...@jakarta.apache.org>
Sent: Sunday, February 26, 2006 8:11 PM
Subject: Re: Avoid reparsing velocity templates
On 2/26/06, Llewellyn Falco <is...@setgame.com> wrote:
> if everything isn't serializable, checkout the code and make it
> serialiable
> shouldn't take very long, doubt even 15 minutes to add implements
> serializable to the nessicary classes.
The problem I see is that every extends SimpleNode, which holds
references to RuntimeServices and Parser, neither of which are really
serializable. The RuntimeServices seems manageable since you can init
the top node and it will descend and set the variable everywhere else
(hopefully that's all init does). Parser is a bit harder to extract,
but really only because of one place... ASTDirective uses it in the
init method.
> out of curioustity 700 ms / mb ? i've never seen a template so big....
I had 4 sized templates (tiny 102b, medium 4kb, large 60kb, huge
243kb) of the same Velocity script repeated, ran them thousands of
times, then adjusted the units to express it as duration per MB.
Yeah, not really that big. :)
--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by Serge Knystautas <sk...@gmail.com>.
On 2/26/06, Llewellyn Falco <is...@setgame.com> wrote:
> if everything isn't serializable, checkout the code and make it serialiable
> shouldn't take very long, doubt even 15 minutes to add implements
> serializable to the nessicary classes.
The problem I see is that every extends SimpleNode, which holds
references to RuntimeServices and Parser, neither of which are really
serializable. The RuntimeServices seems manageable since you can init
the top node and it will descend and set the variable everywhere else
(hopefully that's all init does). Parser is a bit harder to extract,
but really only because of one place... ASTDirective uses it in the
init method.
> out of curioustity 700 ms / mb ? i've never seen a template so big....
I had 4 sized templates (tiny 102b, medium 4kb, large 60kb, huge
243kb) of the same Velocity script repeated, ran them thousands of
times, then adjusted the units to express it as duration per MB.
Yeah, not really that big. :)
--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by "Henning P. Schmiedehausen" <hp...@intermeta.de>.
"Llewellyn Falco" <is...@setgame.com> writes:
>out of curioustity 700 ms / mb ? i've never seen a template so big....
:-) I've written an application that renders >500 page PDF documents
containing pictures, tables and text by piping Velocity output into
FOP. Average template size was 40 MB...
Best regards
Henning
--
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen INTERMETA GmbH
hps@intermeta.de +49 9131 50 654 0 http://www.intermeta.de/
RedHat Certified Engineer -- Jakarta Turbine Development -- hero for hire
Linux, Java, perl, Solaris -- Consulting, Training, Development
Social behaviour: Bavarians can be extremely egalitarian and folksy.
-- http://en.wikipedia.org/wiki/Bavaria
Most Franconians do not like to be called Bavarians.
-- http://en.wikipedia.org/wiki/Franconia
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by Llewellyn Falco <is...@setgame.com>.
Actually, this is a rather interesting point.
imagine if everything was serializable. then you could easily create a
function
getTemplate(resourceName)
{
fileName = resourceName + resource.getTimeModified();
if (fileName.exist())
{
deserialize
}
else
{
getTemplateOldFashionWay();
serializeToFile();
}
return template;
}
if everything isn't serializable, checkout the code and make it serialiable
shouldn't take very long, doubt even 15 minutes to add implements
serializable to the nessicary classes.
cached, no memory.
llewellyn.
out of curioustity 700 ms / mb ? i've never seen a template so big....
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by Geir Magnusson Jr <ge...@pobox.com>.
Serge Knystautas wrote:
>
> Besides Velocity is extremely flexible and trivial to stick a
> memory-based LRU template cache. JDK 1.4 provides an LRU map, so I
> can create that with a cap instead of the default hashtable, and I've
> got an impl that I would hope is as reliable as what Attila
> implemented.
It should be trivial. The thing is designed to be pluggable for this
reason.
>
> But my real goal is to cache without using memory...
And compute w/o cycles!
The holy grail of computing.
>
>>> Really though, something like caching the parsed templates (i.e., the
>>> AST nodes) to disk
>> Well, you're talking about storing the AST in some format on disk, but
>> there is already a way of storing a VTL AST on disk and that is the way
>> it is stored already, as a .vtl file. I mean, it is not obvious to me
>> offhand why re-instantiating the AST from the disk in your scenario is
>> going to be that much more efficient than just reparsing the template
>> from its canonical VTL format.
>>
>> I mean, at the end of the day, you're just reading the template (in some
>> format) off the disk again. Okay, you could have a binary format for
>> storage that is a bit more efficient than the VTL text format, but how
>> much difference would it make?
>>
>> In terms of overall Velocity development, how much value added could
>> their be?
>
> Yes, it is a fair point as to whether the serializable API would be
> faster, but I would hope so. Given the number of pages, I have to
> turn off memory caching, so every page requires parsing.
>
> My benchmarks calculated 37ms/MB to read a file (just read into a
> string), 754ms/MB to compile (create a Template object), and 31ms/MB
> to merge it with a simple context. Obviously if I can eat into that
> 700+ms/MB rate by serializing the ASTNodes or something else, then
> that'd be great.
There should be no reason why not. (Thinking, thinking...) I've oft
wanted to modify the VelocityEngine and add something like
Template t = compileTemplate(Reader r)
and also maybe a helper to serialize and de-serialize a Template instance.
>
> And beyond serialization, if Velocity templates could get translated
> into bytecode, then we've changed velocity from interpreted to
> compiled templating, much like what Resin is doing with PHP
> (http://wiki.caucho.com/Quercus). I'm not expecting someone else
> write it... Just wondering if it seemed at all feasible and/or
> querying for other people who have dealt with this.
We thought about that years ago, and came to the conclusion that absent
some kind of dynamic optimization like a JIT (which I'd argue you could
do now), that you wouldn't get much.
The code in each node in the AST needs to be executed, and already is
bytecode. So I never saw what you'd be able to wring out of it, other
than save the method calls where one node in a AST invokes it's children.
Maybe a JIT would help. Dunno.
geir
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by Serge Knystautas <sk...@gmail.com>.
On 2/26/06, Jonathan Revusky <re...@wanadoo.es> wrote:
> Serge Knystautas wrote:
> > I'm working on a CMS that uses velocity template extensively (many
> > thousands of templates), and we're trying to figure out how to avoid
> > reparsing these templates over and over.
>
> Have you actually determined that this is a bottleneck in your application?
Yes. Why would I ask otherwise? :)
> Well, you could look at FreeMarker. :-) I think we have a pretty good
> MRU template caching implementation. I don't know too much about it, it
> was written by Attila Szegedi, not me. It's probably pretty good. Attila
> is a pretty thorough guy. This stuff is quite well tested. It's been
> part of our stable release for several years.
Heh, if freemarker can parse Velocity templates, then maybe. Like I
said, I've got thousands of temlates (not to mention users) that would
need converting...
Besides Velocity is extremely flexible and trivial to stick a
memory-based LRU template cache. JDK 1.4 provides an LRU map, so I
can create that with a cap instead of the default hashtable, and I've
got an impl that I would hope is as reliable as what Attila
implemented.
But my real goal is to cache without using memory...
> > Really though, something like caching the parsed templates (i.e., the
> > AST nodes) to disk
>
> Well, you're talking about storing the AST in some format on disk, but
> there is already a way of storing a VTL AST on disk and that is the way
> it is stored already, as a .vtl file. I mean, it is not obvious to me
> offhand why re-instantiating the AST from the disk in your scenario is
> going to be that much more efficient than just reparsing the template
> from its canonical VTL format.
>
> I mean, at the end of the day, you're just reading the template (in some
> format) off the disk again. Okay, you could have a binary format for
> storage that is a bit more efficient than the VTL text format, but how
> much difference would it make?
>
> In terms of overall Velocity development, how much value added could
> their be?
Yes, it is a fair point as to whether the serializable API would be
faster, but I would hope so. Given the number of pages, I have to
turn off memory caching, so every page requires parsing.
My benchmarks calculated 37ms/MB to read a file (just read into a
string), 754ms/MB to compile (create a Template object), and 31ms/MB
to merge it with a simple context. Obviously if I can eat into that
700+ms/MB rate by serializing the ASTNodes or something else, then
that'd be great.
And beyond serialization, if Velocity templates could get translated
into bytecode, then we've changed velocity from interpreted to
compiled templating, much like what Resin is doing with PHP
(http://wiki.caucho.com/Quercus). I'm not expecting someone else
write it... Just wondering if it seemed at all feasible and/or
querying for other people who have dealt with this.
--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org
Re: Avoid reparsing velocity templates
Posted by Jonathan Revusky <re...@wanadoo.es>.
Serge Knystautas wrote:
> I'm working on a CMS that uses velocity template extensively (many
> thousands of templates), and we're trying to figure out how to avoid
> reparsing these templates over and over.
Have you actually determined that this is a bottleneck in your application?
>
> First idea... does anyone have experience creating alternate resource
> cache implementations? I've looked at the basic cache impl that's
> available, and it seems like I could very easily swap it with an LRU
> Map to avoid sucking up a lot of memory... we have perhaps hundreds or
> maybe thousands of templates and couldn't keep them all cached in
> memory. That could help reduce reparsing on the most heavily used
> templates.
Well, you could look at FreeMarker. :-) I think we have a pretty good
MRU template caching implementation. I don't know too much about it, it
was written by Attila Szegedi, not me. It's probably pretty good. Attila
is a pretty thorough guy. This stuff is quite well tested. It's been
part of our stable release for several years.
>
> Really though, something like caching the parsed templates (i.e., the
> AST nodes) to disk
Well, you're talking about storing the AST in some format on disk, but
there is already a way of storing a VTL AST on disk and that is the way
it is stored already, as a .vtl file. I mean, it is not obvious to me
offhand why re-instantiating the AST from the disk in your scenario is
going to be that much more efficient than just reparsing the template
from its canonical VTL format.
I mean, at the end of the day, you're just reading the template (in some
format) off the disk again. Okay, you could have a binary format for
storage that is a bit more efficient than the VTL text format, but how
much difference would it make?
In terms of overall Velocity development, how much value added could
their be?
> or somehow using bytecode generation or something
> to avoid reparsing my templates every time and make this much more
> memory friendly... if anyone has any experience or ideas with this,
> I'd greatly appreciate it.
It's not likely that something like this would produce much value-added
to hardly any users. I'm only speculating but it seems unlikely that
whoever is involved in Velocity development would want to invest much
effort in this. After all, there are glaring problems in Velocity, like
whitespace handling, lame macro system, deficient error reporting, that
have not been adequately addressed in years. Surely they'd want to
address some of these things first.
Jonathan Revusky
--
lead developer, FreeMarker project, http://freemarker.org/
>
> --
> Serge Knystautas
> Lokitech >> software . strategy . design >> http://www.lokitech.com
> p. 301.656.5501
> e. sergek@lokitech.com
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org