I want to display the default Tomcat error page in JSF 2.0 (MyFaces) application when exception is thrown.
I added following lines to web.xml:
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/ErrorHandler</location>
</error-page>
<context-param>
<param-name>org.apache.myfaces.ERROR_HANDLING</param-name>
<param-value>false</param-value>
</context-param>
And here is ErrorHandler servlet:
public class ErrorHandler extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Error");
}
}
But instead of the default Tomcat error page an empty page is displayed with error code 500.
When I try to access ErrorHandler servlet directly through URL, it works OK: Tomcat error page is displayed.
So I guess the reason is JSF error handling mechanism? What am I doing wrong?
If you want to display the default error page of the app server, just remove the error page entry from your web.xml and set the context init-parameter javax.faces.PROJECT_STAGE to Production.
Related
I have a simple application to test the communication between html and jsp. My jsp is located in
WEB-INF/test.jsp
Here is the structure of my files:
ProjectA
src
irstServlet.java
Web-Content
test1.html
WEB-INF
test.jsp
Here is the code from servlet
protected void doPost(HttpServletRequest request, response) throws ServletException, IOException {
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/test.jsp");
request.setAttribute("userName", request.getParameter("userName"););
dispatcher.forward(request, response);
}
First I have deploy in tomcat start my test1.html: It take me to the servlet: FirstServlet.java and I can enter userName there.
But after i enter the values in and press enter I expect it to forward me to test.jsp which is not working. I get the error:
The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Edited:
In my html I am trying to use it like:
<form method="POST" name="XX" action="/HelloWorldServlet">
Still not working.
Please can someone help me?
Your code does not look like it would compile at all.
Parameter response has no type - should be HttpServletResponse
There is a semicolon (;) after request.getParameter("userName")
Also I'm not sure why you're getting RequestDispatcher from servlet context rather than from the request - then again I've never checked if it makes any difference.
Anyway, I would rewrite doPost method like this:
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("userName", request.getParameter("userName"));
req.getRequestDispatcher("/WEB-INF/test.jsp").forward(req, resp);
}
EDIT:
I'm assuimng you have either a correct servlet mapping in your web.xml:
<servlet>
<servlet-name>HelloWorldServlet</servlet-name>
<servlet-class>FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/HelloWorldServlet</url-pattern>
</servlet-mapping>
or your servlet is annotated with #WebServlet annotation:
#WebServlet("/HelloWorldServlet")
public class FirstServlet extends HttpServlet {
//your code
}
. If neither of those is true, that's your problem right there.
I have a web-app developed with servlet & JSP. I configured my app to throw an IllegalArgumentException if I insert bad parameters.
Then I configured my web.xml file in this way:
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
When I rise a 404 error, then it works and calls error.jsp, but when I rise a java.lang.IllegalArgumentException, then it does not work and I've a blank page instead of error.jsp. Why?
The server is Glassfish, and logs show really IllegalArgumentException rised.
You should not catch and suppress it, but just let it go.
I.e. do not do:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
doSomethingWhichMayThrowException();
} catch (IllegalArgumentException e) {
e.printStackTrace(); // Or something else which totally suppresses the exception.
}
}
But rather just let it go:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doSomethingWhichMayThrowException();
}
Or, if you actually intented to catch it for logging or so (I'd rather use a filter for that, but ala), then rethrow it:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
doSomethingWhichMayThrowException();
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw e;
}
}
Or, if it's not an runtime exception, then rethrow it wrapped in ServletException, it will be automatically unwrapped by the container:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
doSomethingWhichMayThrowException();
} catch (NotARuntimeException e) {
throw new ServletException(e);
}
}
See also:
How does server prioritize which type of web.xml error page to use?
Submitting form to Servlet which interacts with database results in blank page
Another (simplified) approach is not to declare multiple handlers for various <error-code> and <exception-type> situations but rather have one, sort of catch-all sink, e.g.
<error-page>
<location>/error-page.jsp</location>
</error-page>
Inside your error-page.jsp you can determine the cause, be it a return status code or an exception as described here: https://www.tutorialspoint.com/servlets/servlets-exception-handling.htm These constants are a part of the standard Servlet 3.0 API.
For instance a primitive error-page.jsp response handler placed into the root of your webapp can look like this:
Server encountered a situation
Status code: <%=(Integer) request.getAttribute(javax.servlet.RequestDispatcher.ERROR_STATUS_CODE)%>
<br>
Exception: <%=(Throwable) request.getAttribute(javax.servlet.RequestDispatcher.ERROR_EXCEPTION)%>
For security reasons I wouldn't recommend sending the exact exception type to the client; this is just an example of how to handle different types of errors and response statuses inside a JSP handler; a servlet can be used instead of JSP.
One common catch-all handler vs one per status code is certainly dependent on the situation and requirements.
I have today the same issue. (JavaEE 7 and Glassfish 4.0)
The problem seems that the framework check it as String instead with the Class.
String based check (the hypothesis)
When a Exception is twrown, e.getClass() is compared with <exception-type> as string.
So you can't use inheritance.
Note that nested classes must be pointed as '$' instead '.' (same as getClass() method).
Class based check
The framework create an instance of the class, and <exception-type> text refer to it, and the class.isInstance() is used to check.
This will need reflection and policy file could break it.
I hope that this response solves future issues.
I am getting troubles with handling exceptions in web servlet app.
I've created ErrorHandler servlet, which handles all incoming exceptions and added entry in web.xml file :
<servlet>
<servlet-name>ErrorHandler</servlet-name>
<servlet-class>ServletPackage.ErrorHandler</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ErrorHandler</servlet-name>
<url-pattern>/ErrorHandler</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/ErrorHandler</location>
</error-page>
The problem is the server does not invoke ErrorHandler servlet at all.
Glassfish just throws Exception in the console and web browser refreshes the servlet which thrown exception (with no data due to unhandled exception).
Warning: StandardWrapperValve[SessionChecker]: Servlet.service() for servlet SessionChecker threw exception
javax.servlet.ServletException: Forced exception thrown
at ServletPackage.SessionChecker.processRequest(SessionChecker.java:158)
at ServletPackage.SessionChecker.doPost(SessionChecker.java:174)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
.
.
.
Any suggestions?
I had this same issue. All over the web are examples as you've shown and when I tried it it seemed that my handler servlet was just being ignored completely.
What worked for me to make sure that my error handling servlet implemented both doGet and doPost:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
processError(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
processError(request, response);
}
private void processError(HttpServletRequest request, HttpServletResponse response) throws IOException
{
Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");
...
}
The examples that I had based my servlet on had only implemented doGet. So while my servlet was being loaded and called on errors, nothing was happening with those errors. Implementing doPost to handle the errors the same way solved this for me.
If the exception is being thrown from your web server the exception handler you have declared in the web.xml is not ever going to deal with it.
The exception handler in the web.xml is to handle request coming into the web server.
This is pretty simple and straightforward. I want to throw a 503 error from the servlet side.
response.sendError(503);
When this is thrown, I need it to hit a custom error page. Basically a 503 error page itself, but with a few modifications.
Say I have 503.html, and I added
<error-page>
<error-code>503</error-code>
<location>/503.html</location>
</error-page>
in web.xml.
I created a war file, with a servlet which throws the 503 error, and web.xml with this content. I kept the 503.html in the parent folder location. (Should I keep it elsewhere ?)
I deployed the app in WLS, but this custom 503.html is not getting hit. I am getting the generic 503 error.
Am I missing something?
My code is below:
webapp1.war
->web-inf
->web-inf->classes->prject4->Class1.class
->web-inf->jsp->error->custom.html
web.xml
<?xml version="1.0"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>Class1</servlet-name>
<servlet-class>project2.Class1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Class1</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<error-page>
<error-code>503</error-code>
<location>/WEB-INF/jsp/error/custom.html</location>
</error-page>
</web-app>
class1.java
public class Class1 extends HttpServlet
{
private ServletConfig config;
public void init(ServletConfig config)throws ServletException
{
this.config=config;
}
public void service (HttpServletRequest request, HttpServletResponse response)
throws IOException
{
response.setContentType("text/html");
ServletOutputStream l_out = response.getOutputStream();
response.sendError(503);
}
}
Ok, this was a minor error which I didn't figure out in the beginning.
In my web.xml the servlet-mapping was given as /*, which was causing an infinite loop condition as it throws the same code for which it has been mapped. So I had to adjust the servlet mapping so that Class1 doesn't map to any error pages - like say /images/*.
And then everything started working fine. :)
You can also try handling it with custom Error Handler.
public void service (HttpServletRequest request, HttpServletResponse response)
throws IOException
{
try
{
//some error generating code
throw new Exception("503_Exception");
}
catch(Exception e)
{
response.sendRedirect(HandleError.handle(e, request));
}
}
A separate class to handle errors. This can handle different types of errors.
You can add functionality to log stacktrace, send out emails if something is wrong etc.
public class HandleError{
public static String handle(Throwable t, javax.servlet.http.HttpServletRequest request)
{
String sErrorMsg = t.getMessage();
if (sErrorMsg.equals("503_Exception")) {
request.setAttribute("msg", Constants.EINVALSESSION);
return "/503.html";
}
return "/default_error.html";
}
}
If you are using Maven as your project build tool then it will look in the src/main/webapp directory, so for example our config looks like this:
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/error/error404.html</location>
</error-page>
and our error404.html sits in the folder:
${PROJECT_NAME}/src/main/webapp/WEB-INF/jsp/error/
If your not using Maven the path in the location will have a base directory of wherever you put your index.jsp
I guess there's a minimum limit on the number bytes your custom error page has. The lower limit is usually 512 Bytes. See Important note for your Custom error pages. I've seen this behavior in Google-Chrome too when using Tomcat.
How do I throw a 404 error from within a java servlet? My web.xml already specifies what page to show when there is a 404, how do I throw a 404 from within a servlet?
The Servlet API gives you a method to send a 404 or any other HTTP status code. It's the sendError method of HttpServletResponse:
public void doGet(HttpServletRequest request, HttpServletResponse response) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
In your doGet or doPost method you have a parameter HttpServletResponse res
404 is a status code which can be set by:
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
For adding Request URL with 404 use this below code
public void doGet(HttpServletRequest request, HttpServletResponse response) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI());
}