JSP error page added to previous release

I have a Spring MVC project where I use controller advice to handle errors that occur in controllers. However, I also want to display a good error page if the error occurs in JSP files (although this should not happen!). Therefore, I added the following file to my web.xml project:

 <error-page> <error-code>500</error-code> <location>/WEB-INF/views/application/error/view-error.jsp</location> </error-page> <error-page> <exception-type>java.lang.Exception</exception-type> <location>/WEB-INF/views/application/error/view-error.jsp</location> </error-page> 

If I specifically cause an error in JSTL, the content of view-error.jsp displayed fine. However, the content is added to the output of the JSP file in which the error occurred. For example, if an error occurs in display-users.jsp on line 50, the result is that the result that was generated before the error occurred (line 1-50) adds content to view-error.jsp .

This is very undesirable as it creates a funky error page. And since I canโ€™t say where the exception will be thrown (if I could, I would fix the error), then what the user sees will most likely look bad.

I suppose, because the output is already in the buffer and may already be sent to the client? Is there a way to fix this, or perhaps an alternative approach? Thanks!

+7
java jsp
source share
3 answers

This is a problem with large JSPs generating large HTML, and the Java code for the script is mixed everywhere. Once enough data has been written, the server captures the headers (sends them to the client) and sends the top of the page. At this point, you will no longer be able to roll back anything to return data that has already been received (and possibly displayed) by the browser.

This is one of the reasons why scriplet is not recommended, and if you really need to add some intelligence to the JSP, this should be at the top of the page before anything is really sent to the browser. But ideally, everything should have been pre-calculated in the servlet and prepared data placed in the request attributes. Therefore, the JSP should only contain simple conditional or loop tags in addition to representing HTML attributes and queries. All this with little risk for throwing an exception.

+1
source share

It looks like the OutputStream HttpServletResponse is being written before the JSP completes the rendering.

This should ideally be controlled by the autoflush property. https://tomcat.apache.org/tomcat-5.5-doc/jspapi/javax/servlet/jsp/JspWriter.html

But just in case, this is not solvable:

You can intercept everything written in HttpServletResponse using the HttpServletResponseWrapper approach.

The general idea is that you create a filter, and this filter passes the Response Wrapper to the next layers. This response wrapper provides a link to an instance of the real answer. Everything that is written to the Response can then be processed by the response response tool, and then sent to the real Response instance.

So, for your case, you can add all the data to a StringBuilder, and then when the controls return to the filter, the filter can print the entire StringBuilder before the actual Response OutputStream.

Here is an example that hooks something like servlets, etc. they write, and then sends the gzipped version of this to the browser:

http://tutorials.jenkov.com/java-servlets/gzip-servlet-filter.html

+1
source share

Been there, done it. Here's a quick and dirty workaround until you can reverse engineer.

1) Put all the JSTL code that generates the output in the new JSP - call it display-users-view.jsp (name it whatever you want).

2) Import display-users-view.jsp from the display-users.jsp page via <c: import>, but make sure you dump the contents in var (!). eg:.

 <c:import url="display-users-view.jsp" var="output"/> 

3) As a final step in display-users.jsp, upload the output to the screen with a simple one:

 ${output} 

Now, if an error is thrown before $ {output} .. no harm, no foul, because you have not yet output anything to the browser. If there is no error, $ {output} will unload the HTML that was generated in display-users-view.jsp.

Note that with c: import you do not need to pass any request or form parameters that were submitted to display-users.jsp because you will still have them available in your display-users-view.jsp.

0
source share

All Articles