You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by David Hoffer <dh...@gmail.com> on 2015/12/20 20:14:13 UTC

ClasspathResourceLoader can't find template resources.

I'm getting ResourceNotFoundException errors using Velocity (1.7) in a web
application.  The following is the error I get but its somewhat random.

org.apache.velocity.exception.ResourceNotFoundException: Unable to find
resource 'Body-1_v2.vm'

Or

org.apache.velocity.exception.ResourceNotFoundException: Unable to find
resource 'Body-1.vm'

My application is an EAR running in Wildfly.  The EAR has several web apps
(Wars).  Each of the Wars is a service that uses velocity each with two
templates that generates email content.  There are close to 20 services
like this and they work fine with velocity.  However I have two that are
somewhat different, I've had one of these different ones for a long time
w/o trouble but now that I have two 'different' ones I get the above error.

These 'different' services use Quartz to schedule a job that uses
Velocity.  The Quartz job will fire and it will create a new instance of
the Job and those Job instances create new instances of VelocityEngine
& VelocityContext.  I use the following configuration for Velocity in all
the apps.


Properties properties = new Properties();
properties.put("resource.loader", "class");
properties.put("class.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
properties.put("class.resource.loader.description", "Load resources from
the CLASSPATH");

properties.put("runtime.log.logsystem.class",
"org.apache.velocity.runtime.log.Log4JLogChute");
properties.put("runtime.log.logsystem.log4j.category", "velocity");
properties.put("runtime.log.logsystem.log4j.logger", "velocity");

velocityEngine = new VelocityEngine();
velocityEngine.init(properties);

Then when I use the template I have:

VelocityContext velocityContext = new VelocityContext();
velocityContext.put("updatedRates", updatedRates);

StringWriter writer = new StringWriter();
velocityEngine.mergeTemplate("Body-1_v2.vm", "utf-8", velocityContext,
writer);
String s = writer.toString();

Where 'Body-1_v2.vm' is in the War's classpath, e.g.
WEB-INF/classes/Body-1_v2.vm

My wars are skinny in that all of their jars are loaded from the Ear's lib
folder but each War has its custom code and resources in its
WEB-INF/classes folder

This does work sometimes, it seems that one of these Quartz fired apps will
work but not both (one is a second version of the other).

So it seems to be there is a bug in Velocity's resource loader in that it
can't property resolve the classpath when velocity is loaded by a thread
created by Quartz (which was loaded by the web app).

How can I fix this?  How can I be more explicit in telling Velocity where
the resources are regardless of what thread launched Velocity?

-Dave

Re: ClasspathResourceLoader can't find template resources.

Posted by David Hoffer <dh...@gmail.com>.
Yeah its definitely an issue where Velocity can't reliably load resources
using the web app's class path.  I found a workaround by by using a
FileResourceLoader an setting its path to the calculated path of the
webapp's WEB-INF/classes folder and that does appear to work reliably.
Sure would be good to use class path only though as my workaround will only
work if container expands the archives.

-Dave

On Sun, Dec 20, 2015 at 12:14 PM, David Hoffer <dh...@gmail.com> wrote:

> I'm getting ResourceNotFoundException errors using Velocity (1.7) in a web
> application.  The following is the error I get but its somewhat random.
>
> org.apache.velocity.exception.ResourceNotFoundException: Unable to find
> resource 'Body-1_v2.vm'
>
> Or
>
> org.apache.velocity.exception.ResourceNotFoundException: Unable to find
> resource 'Body-1.vm'
>
> My application is an EAR running in Wildfly.  The EAR has several web apps
> (Wars).  Each of the Wars is a service that uses velocity each with two
> templates that generates email content.  There are close to 20 services
> like this and they work fine with velocity.  However I have two that are
> somewhat different, I've had one of these different ones for a long time
> w/o trouble but now that I have two 'different' ones I get the above error.
>
> These 'different' services use Quartz to schedule a job that uses
> Velocity.  The Quartz job will fire and it will create a new instance of
> the Job and those Job instances create new instances of VelocityEngine
> & VelocityContext.  I use the following configuration for Velocity in all
> the apps.
>
>
> Properties properties = new Properties();
> properties.put("resource.loader", "class");
> properties.put("class.resource.loader.class",
> "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
> properties.put("class.resource.loader.description", "Load resources from
> the CLASSPATH");
>
> properties.put("runtime.log.logsystem.class",
> "org.apache.velocity.runtime.log.Log4JLogChute");
> properties.put("runtime.log.logsystem.log4j.category", "velocity");
> properties.put("runtime.log.logsystem.log4j.logger", "velocity");
>
> velocityEngine = new VelocityEngine();
> velocityEngine.init(properties);
>
> Then when I use the template I have:
>
> VelocityContext velocityContext = new VelocityContext();
> velocityContext.put("updatedRates", updatedRates);
>
> StringWriter writer = new StringWriter();
> velocityEngine.mergeTemplate("Body-1_v2.vm", "utf-8", velocityContext,
> writer);
> String s = writer.toString();
>
> Where 'Body-1_v2.vm' is in the War's classpath, e.g.
> WEB-INF/classes/Body-1_v2.vm
>
> My wars are skinny in that all of their jars are loaded from the Ear's lib
> folder but each War has its custom code and resources in its
> WEB-INF/classes folder
>
> This does work sometimes, it seems that one of these Quartz fired apps
> will work but not both (one is a second version of the other).
>
> So it seems to be there is a bug in Velocity's resource loader in that it
> can't property resolve the classpath when velocity is loaded by a thread
> created by Quartz (which was loaded by the web app).
>
> How can I fix this?  How can I be more explicit in telling Velocity where
> the resources are regardless of what thread launched Velocity?
>
> -Dave
>
>
>
>