Re: Inconsistent and strange NPE when initializing Velocity
Will Glass-Husain <[email protected]>
| Newsgroups | gmane.comp.jakarta.velocity.user |
|---|---|
| Message-ID | <CADDz7ZvU92drgZqsL=0q9oCY9rX-+Z1FQyR_smRg6q58DGos-w@mail.gmail.com> |
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
> > > >> >
> > > >>
> > > >
> > > >
> > >
>