Skip to content

Velocity MethodInvocationExceptions not properly reported [SPR-6246] #10914

@spring-projects-issues

Description

@spring-projects-issues

Will Glass-Husain opened SPR-6246 and commented

My velocity properties include the following
<entry key="runtime.references.strict" value="true" />

(I'm using Velocity 1.6.2)

This will throw a MethodInvocationException (runtime exception, as of Velocity 1.5) if a reference is incorrect.

When I have a bad reference in my page (example: $!user.firstName when $user is not available in the context), I get a runtime error reported in my browser. (This is good). The problem is that the Velocity error is not wrapped correctly due to an apparent bug in NestedServletException which does not wrap the cause.

The actual error reported:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: Can't overwrite cause
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:583)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

...

com.forio.servlet.RequestEncodingFilter.doFilter(RequestEncodingFilter.java:37)

root cause

java.lang.IllegalStateException: Can't overwrite cause
java.lang.Throwable.initCause(Throwable.java:320)
org.springframework.web.util.NestedServletException.<init>(NestedServletException.java:65)
org.springframework.web.servlet.view.velocity.VelocityView.mergeTemplate(VelocityView.java:556)
org.springframework.web.servlet.view.velocity.VelocityLayoutView.doRender(VelocityLayoutView.java:162)

root cause

org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:174)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:257)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1183)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:902)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

This is due to the following code in VelocityView:

protected void mergeTemplate(
Template template, Context context, HttpServletResponse response) throws Exception {

try {
template.merge(context, response.getWriter());
}
catch (MethodInvocationException ex) {
throw new NestedServletException(
"Method invocation failed during rendering of Velocity view with name '" +
getBeanName() + "': " + ex.getMessage() + "; reference [" + ex.getReferenceName() +
"], method '" + ex.getMethodName() + "'",
ex.getWrappedThrowable());
}
}

specifically failing on the "initCause" line in NestedServletException:

public NestedServletException(String msg, Throwable cause) {
super(msg, cause);
// Set JDK 1.4 exception chain cause if not done by ServletException class already
// (this differs between Servlet API versions).
if (getCause() == null) {
initCause(cause);
}
}

I have solved this by creating a CustomVelocityView which just lets the MethodException pass through.

protected void mergeTemplate(Template template, Context context, HttpServletResponse response) throws
{
template.merge(context, response.getWriter());
}

Then I get the much more useful message:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.apache.velocity.exception.MethodInvocationException: Variable $user has not been set at layout/slide_login.vm[line 13, column 117]
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:583)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)


Affects: 2.5 final

Referenced from: commits 0e85c66, bce723d, c63cdb2

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: webIssues in web modules (web, webmvc, webflux, websocket)type: bugA general bug

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions