Re: Inconsistent and strange NPE when initializing Velocity
Bradley Wagner <[email protected]>
| Newsgroups | gmane.comp.jakarta.velocity.user |
|---|---|
| Message-ID | <CAEbivYW7=-HBrsnc_2tFN48upcBVeoL4afZhbN8CZ=eQx1E1-w@mail.gmail.com> |
We're noticing something now that may or may not be related to our change to only use a single instance of the Velocity Engine. Macros that we define in one template seem to be sticking around and being used when we go to merge or evaluate a different template. Is this possible related and to be expected when using a single instance of the VelocityEngine? On Thu, Jun 7, 2012 at 5:28 PM, Bradley Wagner < [email protected]> wrote: > Thanks Will. We'll make sure to just initialize it once. > > > On Thu, Jun 7, 2012 at 3:36 PM, Will Glass-Husain <[email protected]>wrote: > >> Hi, >> >> You should use either the Velocity static calls or the VelocityEngine but >> not both-- it's confusing. They don't technically interfere with each >> other, but it'll be simpler and less error prone not to mix. >> >> It's also a performance hit to continually reinitialize Velocity. There's >> no need to do this every time you process a page. Besides the cost of >> initialization, it also prevents you from doing any caching. >> >> Here's the general pattern >> * On app start up, initialize a VelocityEngine. Store it somewhere. >> * Every time you need to process a template >> --> get the template >> --> create and populate a context >> --> using the velocity engine, merge the template (with the context) >> >> WILL >> >> >> On Thu, Jun 7, 2012 at 8:26 AM, Bradley Wagner < >> [email protected]> wrote: >> >> > Thanks Will. >> > >> > So looking over the developer documentation about initialization and our >> > code, it looks like we're using a mix of the Singleton Velocity Engine >> and >> > Separate Instances in certain cases. However, in all these cases, we're >> > using the same set of properties. The documentation suggests that the >> > Separate Instance method is the newer way to do it, but you're saying >> that >> > if we can get away with initializing Velocity one using Velocity.init() >> we >> > should do that for better performance, yes? Are both mechanisms for >> > evaluating templates thread-safe? >> > >> > In one place we're doing: >> > >> > VelocityContext context = new VelocityContext(contextMap) >> > Properties props = VelocityProperties.getProperties(); >> > Velocity.init(props); >> > String templatePath = VelocityTemplates.getTemplatePath(templateName); >> > Template template = Velocity.getTemplate(templatePath); >> > StringWriter writer = new StringWriter(); >> > template.merge(context, writer); >> > return writer.toString(); >> > >> > and in another we're doing: >> > >> > VelocityEngine engine = new VelocityEngine(); >> > Properties velocityProps = VelocityProperties.getProperties(); >> > engine.init(velocityProps); >> > >> > // Get a template as stream. >> > StringWriter writer = new StringWriter(); >> > StringReader reader = new StringReader(template); >> > // create a temporary template name >> > String tempTemplateName = "velocityTransform-" + >> > System.currentTimeMillis(); >> > >> > // ask Velocity to evaluate it. >> > boolean result = engine.evaluate(context, writer, tempTemplateName, >> > reader); >> > >> > String strResult = null; >> > if (result) >> > { >> > strResult = writer.getBuffer().toString(); >> > } >> > return strResult; >> > >> > Thanks a bunch for your help! >> > >> > On Wed, Jun 6, 2012 at 6:34 PM, Will Glass-Husain < >> [email protected]> >> > wrote: >> > > >> > > You only need to initialize Velocity once. Performance is much better >> > that >> > > way. >> > > >> > > WILL >> > > >> > > On Wed, Jun 6, 2012 at 2:37 PM, Bradley Wagner < >> > > [email protected]> wrote: >> > > >> > > > The odd part about that is that while I could see this being a race >> > > > condition... once Velocity gets into this state it doesn't matter >> how >> > many >> > > > times we call Velocity.init, it returns the NPE every time. I guess >> I >> > > > should have mentioned that in the original post. Basically once it >> > starts >> > > > returning NPE our only recourse is to restart Tomcat, which fixes >> the >> > > > problem, until it pops up again. >> > > > >> > > > On Wed, Jun 6, 2012 at 5:35 PM, Bradley Wagner < >> > > > [email protected]> wrote: >> > > > >> > > > > Ha, that's a good question. Yes, we're initializing Velocity LOTS >> of >> > > > > times. Basically every time we use it to create these messages in >> our >> > > > > message util. I'm guessing that's not recommended? >> > > > > >> > > > > >> > > > > On Wed, Jun 6, 2012 at 1:53 PM, Will Glass-Husain < >> > > > [email protected]>wrote: >> > > > > >> > > > >> Hi Bradley, >> > > > >> >> > > > >> Are you initializing Velocity multiple times? >> > > > >> >> > > > >> Though I haven't heard of this issue before, it sounds like a >> race >> > > > >> condition, perhaps if the initialization is called twice at the >> same >> > > > time. >> > > > >> >> > > > >> WILL >> > > > >> >> > > > >> On Wed, Jun 6, 2012 at 8:37 AM, Bradley Wagner < >> > > > >> [email protected]> wrote: >> > > > >> >> > > > >> > Hi, >> > > > >> > >> > > > >> > I sent this message before I had subscribed to the list so I >> > wasn't >> > > > >> sure if >> > > > >> > the original made it. My apologies if this is a duplicate. >> > > > >> > >> > > > >> > One of our clients running our software is *occasionally* >> running >> > into >> > > > >> the >> > > > >> > stack trace at the bottom when Velocity is initialized. A >> restart >> > > > tends >> > > > >> to >> > > > >> > fix this problem. But it pops back up after running the system >> for >> > a >> > > > >> while. >> > > > >> > >> > > > >> > They're running: >> > > > >> > >> > > > >> > - Velocity 1.7 >> > > > >> > - Tomcat 6.0.35 >> > > > >> > - Using the 3.2 of the Apache Commons Collections library >> > > > >> > - Running Java 1.6.0_31 in Mac OS X 10.6.8 >> > > > >> > >> > > > >> > Unfortunately we don't have the ability to debug this problem >> > > > remotely, >> > > > >> so >> > > > >> > we can't see exactly what's going on, but having looked a bit >> at >> > the >> > > > >> > Extended Properties class, it doesn't seem like it should be >> > possible >> > > > to >> > > > >> > get an NPE at that line, because of the containsKey() check a >> few >> > > > lines >> > > > >> > before. >> > > > >> > >> > > > >> > java.lang.NullPointerException >> > > > >> > at >> > > > >> > >> > > > >> >> > > > >> > >> > >> org.apache.commons.collections.ExtendedProperties.clearProperty(ExtendedProperties.java:797) >> > > > >> > at >> > > > >> > >> > > > >> >> > > > >> > >> > >> org.apache.commons.collections.ExtendedProperties.setProperty(ExtendedProperties.java:722) >> > > > >> > at >> > > > >> > >> > > > >> >> > > > >> > >> > >> org.apache.commons.collections.ExtendedProperties.combine(ExtendedProperties.java:783) >> > > > >> > at >> > > > >> > >> > > > >> >> > > > >> > >> > >> org.apache.velocity.runtime.RuntimeInstance.setProperties(RuntimeInstance.java:657) >> > > > >> > at >> > > > >> > >> > > > >> >> > > > >> > >> org.apache.velocity.runtime.RuntimeInstance.init(RuntimeInstance.java:645) >> > > > >> > at >> > > > >> > >> > > > >> >> > > > >> > >> > >> org.apache.velocity.runtime.RuntimeSingleton.init(RuntimeSingleton.java:226) >> > > > >> > at org.apache.velocity.app.Velocity.init(Velocity.java:97) >> > > > >> > at >> > > > >> > >> > > > >> >> > > > >> > >> > >> com.hannonhill.cascade.velocity.VelocityEngineUtil.generateMessage(VelocityEngineUtil.java:66) >> > > > >> > >> > > > >> > Also, here's the code that's calling the Velocity.init: >> > > > >> > >> > > > >> > Properties velocityProps = >> > VelocityProperties.getProperties(); >> > > > >> > >> > > > >> > Velocity.init(velocityProps); >> > > > >> > >> > > > >> > Velocity Properties are just loading the following file >> contents >> > into >> > > > a >> > > > >> > properties object: >> > > > >> > >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > # This controls if Runtime.error(), info() and warn() messages >> > include >> > > > >> the >> > > > >> > # whole stack trace. The last property controls whether invalid >> > > > >> references >> > > > >> > # are logged. >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > runtime.log.error.stacktrace = false >> > > > >> > runtime.log.warn.stacktrace = false >> > > > >> > runtime.log.info.stacktrace = false >> > > > >> > runtime.log.invalid.reference = true >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > # Configuration for the Log4JLogSystem. >> > > > >> > # You must define the runtime.log.logsystem.class property to >> be: >> > > > >> > # org.apache.velocity.runtime.log.Log4JLogSystem >> > > > >> > # >> > > > >> > # You must also include Log4J's .jar files into your classpath. >> > They >> > > > are >> > > > >> > # included with the Velocity distribution in the build/lib >> > directory. >> > > > >> > # >> > > > >> > # There are several different options that you can configure. >> > > > >> > # Uncomment the ones that you want and also define their >> settings. >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > # T E M P L A T E E N C O D I N G >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > input.encoding=UTF-8 >> > > > >> > output.encoding=UTF-8 >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > # F O R E A C H P R O P E R T I E S >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > # These properties control how the counter is accessed in the >> > #foreach >> > > > >> > # directive. By default the reference $velocityCount will be >> > available >> > > > >> > # in the body of the #foreach directive. The default starting >> > value >> > > > >> > # for this reference is 1. >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > directive.foreach.counter.name = velocityCount >> > > > >> > directive.foreach.counter.initial.value = 1 >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > # T E M P L A T E L O A D E R S >> > > > >> > >> > > > >> > >> > > > >> >> > > > >> > >> > >> #---------------------------------------------------------------------------- >> > > > >> > resource.loader = class >> > > > >> > class.resource.loader.description = Velocity Classpath Resource >> > Loader >> > > > >> > class.resource.loader.class = >> > > > >> > >> > org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader >> > > > >> > >> > > > >> >> > > > > >> > > > > >> > > > >> > >> > >