0

My webapp cannot find its template file. I have read the material in this article, but it doesn't seem to solve the problem. My velocity.properties file, which is installed into my WEB-INF directory, contains the lines

resource.loader=class
resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader

and the Java servlet is

package test;

import java.io.*;
import javax.servlet.http.*;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.view.VelocityViewServlet;
import org.apache.velocity.app.Velocity;

import org.apache.commons.lang.StringEscapeUtils;

public class Recipes extends VelocityViewServlet {

    public Template handleRequest(HttpServletRequest request,
                                  HttpServletResponse response,
                                  Context context) {
        Velocity.init();
        Template template=null;
        try {
            context.put("recipeList","r1");
            template = Velocity.getTemplate("Recipes.vm");
        } catch (Exception e) {
            System.err.println("Exception caught: " + e.getMessage());
        }
        return template;
    }
}

When I navigate to that URL, it fails. I've tried placing the vm file in the WEB-INF directory, in the classes subdirectory, in the lib directory, and in a jar in the lib directory. After things fail, catalina.out contains

Jan 12, 2013 6:35:25 PM org.apache.velocity.runtime.log.CommonsLogLogChute log
SEVERE: ResourceManager : unable to find resource 'Recipes.vm' in any resource loader.
Exception caught: Unable to find resource 'Recipes.vm'

and in localhost.log

Jan 12, 2013 6:35:25 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet recipes threw exception
java.lang.NullPointerException
at org.apache.velocity.tools.view.VelocityView.performMerge(VelocityView.java:942)
at org.apache.velocity.tools.view.VelocityView.merge(VelocityView.java:902)
at org.apache.velocity.tools.view.VelocityViewServlet.mergeTemplate(VelocityViewServlet.java:318)
at org.apache.velocity.tools.view.VelocityViewServlet.doRequest(VelocityViewServlet.java:220)
at org.apache.velocity.tools.view.VelocityViewServlet.doGet(VelocityViewServlet.java:182)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)

Can someone explain to me what is going on? Thanks.

Community
  • 1
  • 1
rogerl
  • 185
  • 2
  • 8

1 Answers1

0

You should be using:

class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader

The resource loader "type" precedes the property name defining the loader class.

See the Velocity Developer Guide to Resource Loaders. Note that the answer you link to points at the correct docs but doesn't (appear) to include the correct config

(All this said, are you sure that's how you're supposed to use the VelocityViewServlet? I thought you'd normally request the *.vm file, do something like a fillContext, and be done with it.)


You're calling Velocity.init() from within a VelocityViewServlet, which is most likely not what you want to do. That aside, from the docs:

initialize the Velocity runtime engine, using the default properties of the Velocity distribution

If you do the following, the configuration I show works:

String propFile = getServletContext().getRealPath("/WEB-INF/velocity.properties");
Velocity.init(propFile);

That said, I'm not convinced you're going about this the right way, but I could be mistaken--I've never used it in a standalone web app before, but this doesn't strike me as being correct.

If nothing else, I'd at least move some stuff into a base class, like:

public abstract class BaseVelocityServlet extends VelocityViewServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        Velocity.init(getServletContext().getRealPath("/WEB-INF/velocity.properties"));
    }

    @Override
    protected Template getTemplate(HttpServletRequest request, HttpServletResponse response) {
        return Velocity.getTemplate(getTemplateName());
    }

    public abstract String getTemplateName();

}

Then each URL's servlet can just fill the context and provide a template name:

public class Recipes extends BaseVelocityServlet {

    @Override
    protected void fillContext(Context context, HttpServletRequest request) {
        context.put("recipeList", "r1");
    }

    @Override
    public String getTemplateName() {
        return "Recipes.vm";
    }

}

Again, I'm not convinced this is right; I'm still under the impression that it should be finding the config file under WEB-INF by default, but for me, at least, it's not.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • So, that did not solve the problem. I still get exactly the same error. – rogerl Jan 13 '13 at 02:34
  • @rogerl What version of things are you using? (Engine, Tools, etc.) – Dave Newton Jan 13 '13 at 02:35
  • The jars are velocity-1.7.jar, velocity-tools-generic-2.0.jar, and velocity-tools-view-2.0.jar. – rogerl Jan 13 '13 at 02:40
  • The localhost log file also contains the message Velocity [debug] Could not load resource 'VM_global_library.vm' from Resource Loader org.apache.velocity.runtime.resource.loader.ClassspathResourceLoader: ClasspathResourceLoader Error: cannot find resource VM_global_library.vm. – rogerl Jan 13 '13 at 02:45
  • @rogerl Because you're calling `Velocity.init()` without giving it the path to the property file name. See updated answer. – Dave Newton Jan 13 '13 at 03:03
  • @rogerl Or it *is* working with your config file, but it's not including the defaults for some reason, like the global macro library. – Dave Newton Jan 13 '13 at 03:54
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/22661/discussion-between-rogerl-and-dave-newton) – rogerl Jan 13 '13 at 13:35