简体   繁体   中英

Catch hibernate exceptions with errorpage handler?

I'm catching all exceptions within: java.lang.Throwable /page.xhtml java.lang.Error /page.xhtml

But what If I get eg a hibernate ex: org.hibernate.exception.ConstraintViolationException

Do I have to define error-pages for EVERY maybe occuring exception? Can't I just say "catch every exception"?

Update

Redirect on a 404 works. But on a throwable does not!

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/error.xhtml</location>
</error-page>
<error-page>
    <error-code>404</error-code>
    <location>/error.xhtml</location>
</error-page>

There is a better way to handle exceptions in JSF - via custom exception handler which can be set in your faces-config.xml :

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
              version="2.0">
  <factory>
    <exception-handler-factory>com.mycompany.CustomExceptionHandlerFactory</exception-handler-factory>
  </factory>
</faces-config>

In that case you can examine exception, it's root cause and perform any actions you want as you will always have handy FacesContext . Below is an example how to handle annoying ViewExpiredException :

Factory:

public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {
  private ExceptionHandlerFactory parent;

  public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) {
    this.parent = parent;
  }

  @Override
  public ExceptionHandler getExceptionHandler() {
    return new CustomExceptionHandler(parent.getExceptionHandler());
  }
}

Handler:

public class CustomExceptionHandler extends ExceptionHandlerWrapper {
  private ExceptionHandler wrapped;

  public CustomExceptionHandler(ExceptionHandler wrapped) {
    this.wrapped = wrapped;
  }

  @Override
  public ExceptionHandler getWrapped() {
    return wrapped;
  }

  @Override
  public void handle() throws FacesException {
    Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();
    while (i.hasNext()) {
      ExceptionQueuedEvent event = i.next();
      ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
      Throwable t = context.getException();
      FacesContext fc = context.getContext();
      boolean exceptionHandled = handleException(t, fc);
      if(exceptionHandled) i.remove(); // remove from queue
    }
    getWrapped().handle(); // let wrapped ExceptionHandler do the rest
  }

  private boolean handleException(Throwable t, FacesContext fc) {
    if (t instanceof ViewExpiredException) {
      try {
        fc.getExternalContext().redirect("/expired/url/");
        return true;
      } catch (IOException e) {
        throw new FacesException(e);
      }
    } else return false;
  }
}

The java.lang.Throwable class is the least common ancestor of all classes in the Java exception class hierarchy. All exception and error classes extend Throwable , directly or indirectly.

If you have an error page for Throwable , any exception that doesn't have a more specific error page will end up there.

Therefore, the answer to your question is "No". You can handle Hibernate exceptions separately if you want to (at any granularity you think is appropriate), but you don't have to.


UPDATE

There are a number of possible reasons why the exceptions are not producing error pages. For example, they might be occurring during redirect processing or they might be caught by a filter. Or they might be thrown after the response header has been committed; eg if the exception occurs during the formatting of the response HTML.

(One salient clue will be whether you are getting any error page at all when an exception is thrown. If you are getting a '500' error page then something is happening. If not then you are probably in one of those situations which prevent any error page generation.)

Anyway, here is what the Servlet spec (version 3.0) says. Read it carefully.


10.9.2 Error Pages

To allow developers to customize the appearance of content returned to a Web client when a servlet generates an error, the deployment descriptor defines a list of error page descriptions. The syntax allows the configuration of resources to be returned by the container either when a servlet or filter calls sendError on the response for specific status codes, or if the servlet generates an exception or error that propagates to the container.

If the sendError method is called on the response, the container consults the list of error page declarations for the Web application that use the status-code syntax and attempts a match. If there is a match, the container returns the resource as indicated by the location entry.

A servlet or filter may throw the following exceptions during processing of a request:

  • runtime exceptions or errors
  • ServletExceptions or subclasses thereof
  • IOExceptions or subclasses thereof

The Web application may have declared error pages using the exception-type element. In this case the container matches the exception type by comparing the exception thrown with the list of error-page definitions that use the exception-type element. A match results in the container returning the resource indicated in the location entry. The closest match in the class hierarchy wins.

If no error-page declaration containing an exception-type fits using the class- hierarchy match, and the exception thrown is a ServletException or subclass thereof, the container extracts the wrapped exception, as defined by the ServletException.getRootCause method. A second pass is made over the error page declarations, again attempting the match against the error page declarations, but using the wrapped exception instead.

Error-page declarations using the exception-type element in the deployment descriptor must be unique up to the class name of the exception-type. Similarly, error-page declarations using the status-code element must be unique in the deployment descriptor up to the status code.

The error page mechanism described does not intervene when errors occur when invoked using the RequestDispatcher or filter.doFilter method. In this way, a filter or servlet using the RequestDispatcher has the opportunity to handle errors generated.

If a servlet generates an error that is not handled by the error page mechanism as described above, the container must ensure to send a response with status 500. The default servlet and container will use the sendError method to send 4xx and 5xx status responses, so that the error mechanism may be invoked. The default servlet and container will use the setStatus method for 2xx and 3xx responses and will not invoke the error page mechanism.

If the application is using asynchronous operations as described in Section 2.3.3.3, “Asynchronous processing” on page 2-10, it is the application's responsibility to handle all errors in application created threads. The container MAY take care of the errors from the thread issued via AsyncContext.start. For handling errors that occur during AsyncContext.dispatch see Section n, “Any errors or exceptions that may occur during the execution of the dispatch methods MUST be caught and handled by the container as follows:” on page 2-16

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM