Wednesday, December 7, 2011

PrimeFaces: Dealing with ViewExpiredException on Ajax Request Response

After pressing a p:commandButton :
<p:commandButton id="refresh" value="Send" action="#{connectionDBController.createDataTable}" update="result,messages"/>

I was getting this as a response in the browser:
<partial-response>
  <error>
    <error-name>class javax.faces.application.ViewExpiredException</error-name>
    <error-message><![CDATA[viewId:/index.xhtml - View /index.xhtml could not be restored.]]>
    </error-message>
  </error>
  <changes>
    <extension primefacesCallbackParam="validationFailed">{"validationFailed":false}</extension>
  </changes>
</partial-response>


BUT in the server log, there where NO LOG ERROR.The error was ONLY being sent through the http response, so the error-page tag in the web.xml couldn't work:

http://jhonjairoroa87.blogspot.com/2011/12/primefaces-viewexpiredexception-server.html

After googling for a couple of days , I couldn't find anything so  I decided to handle that error in my way, I know it could be better, but It works.

I added the oncomplete attrib to the p:commandButton:
<p:commandButton id="refresh" oncomplete="handleAjaxRequest2(xhr, status, args);" value="Send" action="#{connectionDBController.createDataTable}" update="result,messages"/>

The handleAjaxRequest method  has:


function handleAjaxRequest2(xhr, status, args){                       
            myValidationObject1 = new validationObject({'property':'data' , 'value':'class javax.faces.application.ViewExpiredException'}, null)
            myValidationObject2 = new validationObject({'property':'localName' , 'value':'error-name'}, myValidationObject1)
            myValidationObject3 = new validationObject({'property':'localName' , 'value':'error'}, myValidationObject2)
            myValidationObject4 = new validationObject({'property':'localName' , 'value':'partial-response'}, myValidationObject3)                                   
            myBoolResult = validateInternalPropery(xhr.responseXML , myValidationObject4);           
            if (myBoolResult == true){
                //alert("myBoolResult" + myBoolResult);
                alert("Session expired, please login again")
                window.location = '/myProject/faces/Login/Login.xhtml';
            }                      
        }

The validateInternalPropery method has

function validateInternalPropery(myObj , myValidationObject){
            returnValue = false;
            console.log("myObj");
            console.log(myObj);
            console.log("myValidationObject");
            console.log(myValidationObject);           
            //myObj = xhr.responseXML;
            if(myObj.hasChildNodes() == true){ //validate has chid nodes
                for(childNode in myObj.childNodes){ // iter child nodes in object
                    if (typeof myObj.childNodes[childNode] == 'object'){ // validate if the current childnode is an object
                        if(myObj.childNodes[childNode].hasOwnProperty(myValidationObject.iniValidation.property) == true){ // validate if the childnode has the given a Property
                            if(myObj.childNodes[childNode][myValidationObject.iniValidation.property] == myValidationObject.iniValidation.value){ // evaluatee the value of given property
                                if (myValidationObject.endValidation == null){
                                    returnValue = true;
                                    break;
                                }else{
                                    validateInternalPropery(myObj.childNodes[childNode] , myValidationObject.endValidation)
                                }                               
                            }
                        }
                    }
                }
            }
            return returnValue;
        }


The validationObject class method has

function validationObject(myIniValidation, myEndValidation){
            this.iniValidation = myIniValidation;
            this.endValidation = myEndValidation;
        }

I that way I can locate the error that I want , in this case, class javax.faces.application.ViewExpiredException, and do the window.location to redirect to the login page

References:
http://forum.primefaces.org/viewtopic.php?f=3&t=5909
http://yigitdarcin.wordpress.com/2011/10/06/dealing-with-viewexpiredexception-on-regular-and-ajax-requests/ 

http://weblogs.java.net/blog/driscoll/archive/2009/05/jsf_2_ajax_even.html 
http://stackoverflow.com/questions/6946078/primefaces-pajaxstatus-onerror-not-called 

No comments: