-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Description
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