richfacesajax4jsfonerror

Usage of onError attribute in Richfaces 4.5


I want to make use of onerror attribute in Richfaces to handle exceptions for my ajax requests. For that i have used

<a4j:commandButton value="OK" 
actionListener="#{aBean.handler()}"
onerror="showNotification();">

and in my Managed bean :

ABean{
    public void handler(){
        throw new SomeException("Error to the browser");
    }
}

Though, i have thrown exception in my handler, my showNotification() is never called.

Can I handle my application level exceptions using onerror attribute? Any pointers or examples on this topic is much appreciated.


Solution

  • In docs you can read that onerror attribute works:

    when the request results in an error

    This basically means that request must ends with HTTP error. For example HTTP 500, which can mean that server is not avaible at the moment.

    Example of it (java):

    public void handler2() throws IOException {
        FacesContext context = FacesContext.getCurrentInstance();
        context.getExternalContext().responseSendError(HttpServletResponse.SC_NOT_FOUND,
                "404 Page not found!");
        context.responseComplete();
    }
    

    and a4j:commandButton (xhtml)

    <a4j:commandButton value="OK" actionListener="#{bean.handler2}" 
        onerror="console.log('HTTP error');" />
    

    In JavaScript console you should see "HTTP error".

    In any other case of exceptions oncomplete code will be fired, since AJAX request end with success. So if you wan't to react to the exception in your code you must handle it yourself. There are many ways to do this. I use this:

    public boolean isNoErrorsOccured() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        return ((facesContext.getMaximumSeverity() == null) || 
                    (facesContext.getMaximumSeverity()
                        .compareTo(FacesMessage.SEVERITY_INFO) <= 0));
    }
    

    And my oncomplete looks like this:

    <a4j:commandButton value="OK" execute="@this" actionListener="#{bean.handler1}"
        oncomplete="if (#{facesHelper.noErrorsOccured})
            { console.log('success'); } else { console.log('success and error') }" />
    

    and with handler like this:

    public void handler1() {
        throw new RuntimeException("Error to the browser");
    }
    

    In JavaScript console you would see "success and error".


    BTW. It's better to write actionListener="#{bean.handler3}" instead of actionListener="#{bean.handler3()}". The reason behind it:

    public void handler3() { // will work
        throw new RuntimeException("Error to the browser");
    }
    
    // the "real" actionListener with ActionEvent won't work and
    // method not found exception will be thrown
    public void handler3(ActionEvent e) { 
        throw new RuntimeException("Error to the browser");
    }