5

I have some code that works just fine locally, but when I try to run it on my remote server, it throws a null pointer exception. It does so when attempting to get the template from Velocity. It fails the first time, and every time after.

The code in question is this bit:

    URL location = Thread.currentThread().getContextClassLoader().getResource("velocity.properties");
    String fullPath = location.getPath();
    log.debug("Path: " + fullPath);
    Velocity.init(fullPath);
    Template tmplt = Velocity.getTemplate( "template.html" );  //This line throws the error

Logging shows the path to be correct, and I can verify that the file is there.

The properties file used to initialize velocity contains:

resource.loader = file
file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
file.resource.loader.path=/var/lib/tomcat6/webapps/geoip/WEB-INF/templates/template.html
file.resource.loader.cache = true

input.encoding=UTF-8
output.encoding=UTF-8

The stack trace for the error looks like this:

SEVERE: Servlet.service() for servlet Jersey REST Service threw exception
java.lang.NullPointerException
at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1533)
at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1514)
at org.apache.velocity.runtime.RuntimeSingleton.getTemplate(RuntimeSingleton.java:299)
at org.apache.velocity.app.Velocity.getTemplate(Velocity.java:358)
at ca.company.ipservice.models.MyClass.toHTML(MyClass.java:48)

I've Googled around and searched StackOverflow but I can't find any answer. Any ideas?

kidl33t
  • 1,527
  • 2
  • 10
  • 9
  • Try the below link http://stackoverflow.com/questions/2931516/loading-velocity-template-inside-a-jar-file – sunshine Jul 24 '13 at 18:16
  • 1
    BTW, I had a similar error message once when using Velocity in a multi-threaded environment and calling init() multiple times, it appeared only once in hundreds of executions, though, seems to be a rare race-condition although RuntimeInstance.init() is synchronized, so not sure how it could happen... – centic May 05 '14 at 11:18

2 Answers2

6

The property file.resource.loader.path should point to a directory. Try to set it to the directory /var/lib/tomcat6/webapps/geoip/WEB-INF/templates

file.resource.loader.path=/var/lib/tomcat6/webapps/geoip/WEB-INF/templates

instead of

file.resource.loader.path=/var/lib/tomcat6/webapps/geoip/WEB-INF/templates/template.html

Also you seem to have a web application. In this case it is better to use the WebappResourceLoader from the velocity tools

resource.loader = webapp
webapp.resource.loader.class = org.apache.velocity.tools.view.WebappResourceLoader
webapp.resource.loader.path = templates
webapp.resource.loader.cache = false

and set the servlet context property before initializing it

VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.setApplicationAttribute("javax.servlet.ServletContext", context);

where context is the ServletContext. The directory templates should be located in your web root, thus in the same location as WEB-INF.

EDIT

If you package your application into a war file and deploy it onto the app server which does not unpack it so that you have direct access to the filesystem then you might consider using the ClasspathResourceLoader. For that you'll have to package your templates into an own jar file an put it into WEb-INF/lib. The argument for getTemplate(...) will have to follow the rule of retrieving ressources located in the classpath (see ClassLoader#getResourceAsStream).

resource.loader = classpath
classpath.resource.loader.description = Velocity Classpath Resource Loader
classpath.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
classpath.resource.loader.cache = false

Here you can find more informations about how to load templates (a.k.a. resources).

A4L
  • 17,353
  • 6
  • 49
  • 70
  • I tried all of your suggestions, and they run just fine locally. Sadly they still don't work on the server. Thanks for your excellent suggestions though! – kidl33t Jul 24 '13 at 19:31
  • 1
    Thanks for all your help! Using your suggestions in addition to adding this line to my velocity.properties file got it working in all environments! Your changes got me past the initial error to a secondary velocity logging error, which was solved by adding this to properties: 'runtime.log.logsystem.class=org.apache.velocity.runtime.log.NullLogSystem' . Thank you very much for all your help, I really appreciate it. It got me out of a bind! – kidl33t Jul 25 '13 at 14:55
1

I think this code[1] should be more robust. When there's any error configuring the Logging, the velocity engine ends up in the weird state in which initialized=false and initializing=true for the lifetime of your application. I'm also not sure why Logging is initialized first than resource manager. I'm thinking on opening a bug to the project.

[1] http://grepcode.com/file/repository.springsource.com/org.apache.velocity/com.springsource.org.apache.velocity/1.6.2/org/apache/velocity/runtime/RuntimeInstance.java#RuntimeInstance.init%28%29

andres.santana
  • 624
  • 1
  • 6
  • 13