javaservletsweb-applicationsweb-inf

Unable to read a file in Java web application


I am developing a web application using servlets in which i want to use Velocity templates. For this purpose i have kept my templates under WEB-INF/templates directory.

I have another plain Java class which generates code from this template and which requires to read this file.

My servlet calls method from this simple java class to get the generated code.

I tried to use the real path to read the template but i'm getting ResourceNotFoundException every time i access the servlet.

Following is the code which i'm using in the sevlet

TemplateParser parser = new TemplateParser(getServletContext().getRealPath("/WEB-INF/templates/index.vm"));
        String html = parser.parser();
        out.println(html);

TemplateParser is my simple java class.

I'm using it in a Netbeans project and the path string generated is C:\Users\Sushil Kumar\Documents\NetBeansProjects\ALTTC\build\web\WEB-INF\templates\index.vm. This file exits at the given path but still getting the exception.

Stacktrace of the exception

org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource 'C:\Users\Sushil Kumar\Documents\NetBeansProjects\ALTTC\build\web\WEB-INF\templates\index.vm'
at org.apache.velocity.runtime.resource.ResourceManagerImpl.loadResource(ResourceManagerImpl.java:452)
at org.apache.velocity.runtime.resource.ResourceManagerImpl.getResource(ResourceManagerImpl.java:335)
at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1102)
at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1077)
at org.apache.velocity.app.VelocityEngine.getTemplate(VelocityEngine.java:528)
at me.uni.sushilkumar.alttc.TemplateParser.parser(TemplateParser.java:52)
at me.uni.sushilkumar.alttc.TemplateController.processRequest(TemplateController.java:38)
at me.uni.sushilkumar.alttc.TemplateController.doGet(TemplateController.java:57)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)

EDIT as suggested by TheNewIdiot in the comments.

Properties p = new Properties();
    p.setProperty("resource.loader", "file");
    p.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
    p.setProperty("file.resource.loader.path", path); <== path = getServletContext().getRealPath("/WEB-INF/templates")
    p.setProperty("file.resource.loader.cache", "false");
    p.setProperty("file.resource.loader.modificationCheckInterval", "0");

Solution

  • Don't use FileResourceLoader. Have a look at the documentation:

    The simplest replacement for FileResourceLoader in a web application is actually a part of the VelocityTools project. It is the WebappResourceLoader. This ResourceLoader implementation is specifically designed to work just like the FileResourceLoader, but it is aware of the servlet context and allows you to configure resource paths relative to the servlet root, rather than the local file system.

    If you are using the VelocityViewServlet, then it is automatically configured and ready to use the WebappResourceLoader. So if you want to change the configured path(s), you need only add a line like the following to your velocity.properties:

    webapp.resource.loader.path=/WEB-INF/mytemplates/
    

    If you need to set the WebappResourceLoader up on your own, then you can make your properties something like this:

    resource.loader=webapp
    webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader
    webapp.resource.loader.path=/WEB-INF/mytemplates/
    

    Or:

    Properties props = new Properties();
    props.setProperty("resource.loader", "webapp");
    props.setProperty("webapp.resource.loader.class", "org.apache.velocity.tools.view.WebappResourceLoader");
    props.setProperty("webapp.resource.loader.path", "/WEB-INF/mytemplates/");
    VelocityEngine engine = new VelocityEngine(props); 
    

    You will also need to put the ServletContext into your VelocityEngine's application attributes before initializing that Engine. This is how the WebappResourceLoader knows how to find templates.

    myVelocityEngine.setApplicationAttribute("javax.servlet.ServletContext", servletContext);