Manually-configuring a WebappResourceLoader

Christopher Schultz <[email protected]> Mon, 19 Dec 2022 09:31:59 -0500
Newsgroups gmane.comp.jakarta.velocity.user
Message-ID <[email protected]>
Hello,

I need to be able to initialize and use a VelocityEngine from within a 
web application but without the benefit of using Velocity*Servlet, etc. 
in order to do the setup.

I'm already using Velocity as the templating engine for this web 
application and I need to keep this usage separate. I'd also like to be 
able to instantiate the engine and discard it at will.

But I'm having trouble configuring the web application class loader. 
Here's my code (roughly, it's more complicated than this but it boils 
down to this):

         Properties props = getConfigProperties();

         VelocityEngine engine = new VelocityEngine();

         engine.init(props);

         String bundleName = props.getProperty("resource-bundle.name");
         VelocityContext global = new VelocityContext();
         global.put("date", new 
org.apache.velocity.tools.generic.ComparisonDateTool());
         global.put("math", new 
org.apache.velocity.tools.generic.MathTool());
         global.put("escape", new 
org.apache.velocity.tools.generic.EscapeTool());
         global.put("locale", getLocale());
         if(null != bundleName) {
             global.put("msg", new MessageTool(bundleName, getLocale()));
         }

         VelocityContext ctx = new VelocityContext(global);
         // set up my local context e.g. ctx.put("foo", new Bar());

         ctx = new VelocityContext(ctx);

         customize(ctx);

         try {
             Template template = getTemplate(engine);

             template.merge(ctx, w);
         } catch (ParseException pe) {
             throw new IOException("Failed to parse template", pe);
         }

This works great when I use a file loader with a definite path or with a 
ClasspathResourceLoader, but the way the WebappResourceLoader gets 
access to the ServletContext is kind of awkward.

I *think* I can do this, which seems insanely hacky:

         // (This is experimental)
         // Specifically add support for WebappReourceLoader
         if(props.containsKey("javax.servlet.ServletContext")) {
 
engine.setApplicationAttribute("javax.servlet.ServletContext", 
props.get("javax.servlet.ServletContext"));
         }


I'm wondering if there is a better way. For example, can I provide a 
pre-constructed WebappClassLoader to the VelocityEngine? Ir all seems to 
be based upon the configuration properties and wants to construct its 
own Loader objects.

Thanks,
-chris