Overwriting the errorPage property in JSP - java

I've defined <%# page errorPage="/error.jsp" %> in the header that all JSP files include, to catch any unhandled exceptions and redirect to that error page instead of printing them. This works fine with one caveat - if error.jsp itself throws an exception, it will continuously redirect to itself in an infinite loop. I want to erase the errorPage value for just error.jsp so that it'll just print the exception as normal. I tried just redefining the errorPage property to be blank but I get the following error:
Page directive: illegal to have multiple occurrences of errorPage with different values (old: /error.jsp, new: )
Is there any way for me to overwrite that property? Or any other suggestions on how to prevent this issue?

It is indeed illegal to have multiple page declarations with the same attribute. Your choices are:
Not include your header into your error page.
Ensure that your error page doesn't throw any exception on its own. It should really be rather simple and straightforward - error page is no place for business logic. If you want to do something complicated there, consider redirecting to another page instead.

Why don't you just have a different include header for the error page which do not include it himself?!!
So, instead of having:
header.jsp
==========
a
b
c
errorPage=error.jsp
You could have:
commonHeader.jsp
===========
a
b
c
Without the errorPage directive
And modify the header to include the new one.
header.jsp
===========
include=commonHeader.jsp
errorPage=error.jsp
That way you don't need to change anything in the rest of your jsp's
You just need to change your errorPage from:
include="header.jsp"
to
include="commonHeader.jsp"
And the errorPage won't have an error page anymore ....

I ended up taking care of it simply by surrounding the page with < c:catch > tags to avoid making the redirect in the first place, and printing a barebones message with the exception to make certain it can't break.

Related

Is it possible to call methods in one JSP from another while using dynamic include?

I need to call in a JSP a method that is defined in another JSP that should be included dynamically (include page ) not statically (include file), but I get a jsp compilation error "method is undefined". It works fine when I use <%#include file=""%>.
The reason I need this is that our JSP ends up getting too big and we get this error: "The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes limit" (whence the need to include other jsps dynamically), therefore we're splitting some of its funcionality into smaller JSPs.
Foo.jsp
<%#page language="java"%>
<%!
public String getSomeID(String param) throws Exception {
return "someId";
}
%>
Bar.jsp
<jsp:include page="Foo.jsp"></jsp:include>
String id = getSomeID(param);
I'm aware that the better option here is to use a preprocessing servlet. We'll probably do that. But, for now, I merely wish to know if it is possible to call methods from another jsp while including it dynamically.
You can't reference the code from your Foo.jsp in Bar.jsp
if you are doing that with jsp:include.
Both pages in that cases are compiled into independent servlets behind the scene. Let's call them Foo_Servlet and Bar_Servlet.
What actually happens in that case is the following: Bar_Servlet while handling the request passes control and original request to Foo_Servlet.
Once Foo_Servlet completes the response of execution of Foo_Servlet (and not original jsp code) is combined with a response of Bar_Servlet.

response.sendRedirect() from jsp:include being ignored?

I've got a jsp file, which includes another jsp file to check some values and such:
<jsp:include page="setup.jsp" />
Inside the setup.jsp I've got some conditional code which determines if some needed values are set in the session and if not redirects them to a different page. Or at least it is supposed to, but the redirect seems to be getting ignored.
System.err.println("Redirecting!");
response.sendRedirect("http://www.google.com");
return;
I see "Redirecting!" get logged to the console, but the page continues on and renders normally. I had curl dump the headers for me and saw that the response is HTTP/1.1 200 OK so it definitely isn't sending a 302 redirect.
Any idea what the problem is and how I can fix this?
EDIT: I have verified that my response is not yet committed. response.isCommitted() returns false meaning the status code and headers have not been sent yet.
EDIT 2: I've tried calling response.sendRedirect() in many other places and find that I can successfully redirect before the . The redirect inside the JSP seems to be ignored and if I try to redirect right AFTER the jsp then I get an illegal state exception because the response has already been committed.
The <jsp:include> uses under the covers RequestDispatcher#include(). Click the link to see the javadoc. Here's an extract of relevance (emphasis mine):
...
The ServletResponse object has its path elements and parameters remain unchanged from the caller's. The included servlet cannot change the response status code or set headers; any attempt to make a change is ignored.
...
The HttpServletResponse#sendRedirect() basically sets the HTTP response status to 302 and the HTTP Location header to the target URL. It is thus totally being ignored.
The deeper problem is that you're abusing JSP as a page controller/filter. You should actually be using a normal servlet or filter class for this which runs far before JSP.
The redirect header (I believe) needs to be at the top of the page. View the HTML spec for reference.
Have you tried placing it at the very top of the page? A code sample would help us debug...

How to set HTTP status code in JSP error handlers

I have a JSP page (in Tomcat) which uses JSP Tags to retrieve some data. But these JSP Tags can throw exceptions (For example when parameter values are invalid). Now I want to implement a nicer error handling for these situation. I failed to find a way to GLOBALLY specify an exception handler (error-page definitions in web.xml don't work for exceptions thrown in a JSP). The only way I found so far is specifiying an errorPage attribute in the page header of ALL JSP-files.
<% page errorPage="/WEB-INF/jsp/errors/500.jsp" %>
Quite annoying to do this for ALL JSPs, but acceptable. But not acceptable is the fact that the error page is always delivered with a HTTP status code of 200. I want a 500 instead. I tried using a servlet as errorPage instead of a JSP and tried to set response.setStatus(500) and also response.sendError(500) but both calls seems to be ignored. So this code prints "200" two times and I have no idea why:
System.out.println(response.getStatus());
response.setStatus(500);
System.out.println(response.getStatus());
So the question is: How can I set the HTTP status code in JSP error handlers?
You can configure your error pages in web.xml.
<error-page>
<error-code>
500
</error-code>
<location>
/500.jsp
</location>
</error-page>
in your 500.jsp, set the directive as <%# page isErrorPage="true" %>
Instead of setStatus(500), you'd better use sendError(500) - there are some differences.
The config in web.xml works fine with sendError, however, if you don't want the config in web.xml, error-page from page directive worked just for exceptions for me, not for HTTP error codes.

JSP renders weird HTML

I'm getting a very strange behaviour in one of my JSP pages. It looks like it doesn't render the complete HTML. It looks like this:
<html>
...
<table>
...
</table>
<div id=
So the last line is exactly what you get when the page is rendered. Furthermore, when you do a view source you get exactly the same. This page doesn't have any fancy logic ... there are no javascript erros, no missing closing tags, etc ...
Is there any sort of page limit for a jsp page?
A bit more background: This page works just fine in a WIN2K server running Tomcat 5.5. I'm upgrading this app to run under a server with WIN2008 + Tomcat 6.0. That's where I get the error ...
Any help is appreciated.
Is there any sort of page limit for a jsp page?
AFAIK, no.
I think that the most likely cause is that your JSP is throwing an exception. Check the Tomcat logs, and look at the JSP at the point after the last HTML that was output.
EDIT
#Adam Crume says: "The exception may be thrown at a point further down from where the output stops, due to buffering."
True. As a temporary hack to get around this, you could surround the JSP's content with a try / finally, and flush the output stream in the finally block.
Is there any sort of page limit for a jsp page?
Yes, there is. It's about 64KB. JSP's are basically compiled into a large try statement. In Java, there's a 64KB limit for try statement. But if you exceed this, it would have prouced a different exception.
This problem at least indicates that you're using scriptlets in the JSP. This is a bad practice. Whenever an exception occurs halfway a JSP page, you'll get a blank or halfbaked page without information about the problem. Don't execute business stuff in JSP, but in a preprocessing Servlet.

JSP: How can I still get the code on my error page to run, even if I can't display it?

I've defined an error-page in my web.xml:
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/error.jsp</location>
</error-page>
In that error page, I have a custom tag that I created. The tag handler for this tag e-mails me the stacktrace of whatever error occurred. For the most part this works great.
Where it doesn't work great is if the output has already begun being sent to the client at the time the error occurs. In that case, we get this:
SEVERE: Exception Processing ErrorPage[exceptionType=java.lang.Exception, location=/error.jsp]
java.lang.IllegalStateException
I believe this error happens because we can't redirect a request to the error page after output has already started. The work-around I've used is to increase the buffer size on particularly large JSP pages. But I'm trying to write a generic error handler that I can apply to existing applications, and I'm not sure it's feasible to go through hundreds of JSP pages making sure their buffers are big enough.
Is there a way to still allow my stack trace e-mail code to execute in this case, even if I can't actually display the error page to the client?
The errorPage isn't going to be used if you've already started sending data to the client.
What I do is use a JavaScript callback to check for an incomplete page and then redirect to the error page. At the beginning of your page in an includes header or something, initialize a boolean javascript variable to false, and register an onload handler to check the state and redirect to an error page.
<script type="text/javascript">
var pageLoadSuccessful = false;//set to true in footer.jsp
dojo.addOnLoad(function(){
if (!pageLoadSuccessful) window.location = "<c:url value="/error.do" />";
});
</script>
Then in a footer jsp, be sure to set this variable to true:
<script type="text/javascript">
pageLoadSuccessful = true;//declared in header.jsp
</script>
Have you tried using the <%# page errorPage="/myerrorpage.jsp" %> directive?
You also need to use <% page isErrorPage="true" $> in myerrorpage.jsp, then.
I think that may solve your problem. The only problem with that is that you need to include it in every JSP somehow.
In fact, this particular problem indicates that you were using scriptlets in JSP. This is a bad practice and this particular problem is one of the major reasons for that. You need to move all your business logic to a real java class so that you end up with only taglibs/EL in JSP. In a servlet/filter you can perfectly handle exceptions before forwarding the request to a JSP.

Categories

Resources