Handle ViewExpiredExceptions from AJAX requests with Primefaces 5.1 - ajax

I have a JSF 2.1 + Primefaces 5.1 web application and I want to handle ViewExpiredExceptions. Besides the configuration in web.xml (mapping the exception to a location via <error-page>), I read that we need to treat these exceptions when they are thrown during ajax requests.
Primefaces provides a <p:ajaxExceptionHandler> for this purpose. I tried to use it and, although I could see the exception being thrown in the server log, I could not do anything else. Maybe I'm using it the wrong way. How could I, for instance, send the user to the index.xhtml page when such an exception occurs, refreshing all ajax components?
I defined the exception handler factory in faces-config.xml:
<factory>
<exception-handler-factory>
org.primefaces.application.exceptionhandler.PrimeExceptionHandlerFactory
</exception-handler-factory>
</factory>
And declared the facelets handler in my template page:
<p:ajaxExceptionHandler type="javax.faces.application.ViewExpiredException"/>
Here's my web.xml configuration for these exceptions:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/index.xhtml</location>
</error-page>
After being unsuccessful with this approach, I tried the explicit definition of the exception handler (Check if session exists JSF) but without success either.
Can anyone tell me how to solve this problem? (I'm trying to stick with plain JSF and Primefaces, although I know that Omnifaces provides a similar solution to Primefaces', but I haven't tried it yet).

Related

org.omnifaces.EXCEPTION_TYPES_TO_UNWRAP doesn't work for non-ajax requests

I use FullAjaxExceptionHandlerFactory to handle exceptions during both ajax and non-ajax requests.
The OmniFaces showcase page says
The FullAjaxExceptionHandler will transparently handle exceptions during ajax requests exactly the same way as exceptions during synchronous (non-ajax) requests.
I noticed that if an exception happened during a synchronous request, findExceptionRootCause (the method that actually does unwrapping) doesn't get called. Therefore, the rules defined in the web.xml aren't being applied since they rely on FullAjaxExceptionHandler unwrapping.
Does it mean I need to extend the FullAjaxExceptionHandler or is there something I am missing?
Stack trace :
(non-ajax request)
javax.servlet.ServletException:
Caused by: javax.faces.view.facelets.TagAttributeException
Caused by: javax.el.ELException
Caused by: xxx.MyException
web.xml:
<context-param>
<param-name>org.omnifaces.EXCEPTION_TYPES_TO_UNWRAP</param-name>
<param-value>javax.servlet.ServletException,javax.faces.view.facelets.TagAttributeException,javax.el.ELException</param-value>
</context-param>
...
<error-page>
<exception-type>xxx.MyException</exception-type>
<location>/xxx/page-not-found.xhtml</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/xxx/internal-server-error.xhtml</location>
</error-page>
*I remember ELException may be omitted since it will be included anyway. For the sake of certainty, I included every type preceded my exception in the stack trace.
Result:
/xxx/internal-server-error.xhtml is shown
Expected:
/xxx/page-not-found.xhtml is shown
Update:
For the exception mentioned above, if I define <error-page> like
<error-page>
<exception-type>javax.faces.view.facelets.TagAttributeException</exception-type>
<location>/blueglue/templates/error/page-not-found.xhtml</location>
</error-page>
or
<error-page>
<exception-type>javax.servlet.ServletException</exception-type>
<location>/blueglue/templates/error/page-not-found.xhtml</location>
</error-page>
I will get the expected outcome - the 404 page.
For javax.el.ELException and xxx.MyException, the exception results in the 500 page which isn't what I am expecting.
I use FullAjaxExceptionHandler to handle exceptions during both ajax and non-ajax requests.
The FullAjaxExceptionHandler does not handle exceptions during non-ajax requests. Its sole purpose is to handle exceptions during ajax requests the same way as non-ajax requests (namely, showing an error page defined in web.xml).
Further in the showcase page which you linked you can find this section:
Normal requests
Note that the FullAjaxExceptionHandler does not deal with normal (non-ajax) requests at all. To properly handle JSF and EL exceptions on normal requests as well, you need an additional FacesExceptionFilter. This will extract the root cause from a wrapped FacesException and ELException before delegating the ServletException further to the container (the container will namely use the first root cause of ServletException to match an error page by exception in web.xml).
So, all you need to do is to install the FacesExceptionFilter in order to get the same unwrapping behavior as FullAjaxExceptionHandler.

How to redirect from error-page preRenderView in JSF 2.2?

I wanted to upgrade JSF 2.1 (myfaces) to 2.2 in my application. I just changed two myfaces....jar files in TomEE/lib folder (TomEE-1.7.5). Everything seems to work well except one thing. I have an error page configured in web.xml:
<error-page>
<error-code>500</error-code>
<location>/error/500.jsf</location>
</error-page>
In order to catch error in case of ajax post, omnifaces' FullAjaxExceptionHandlerFactory is declared in faces-config.xml:
<factory>
<exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>
</factory>
In error page there is a preRenderView function, in which there is a conditional redirect. In JSF 2.1 it was working perfectly. But with JSF 2.2 in case of redirection, because of some other exception I get this message:
Oops!
A problem occurred during processing the ajax request. Subsequently,
another problem occurred during processing the error page which should
inform you about that problem.
The other exception in log:
SEVERE: FullAjaxExceptionHandler: Well, another exception occurred
during rendering error page '/error/500.jsf'. Trying to render a
hardcoded error page now. java.lang.IllegalStateException: Cannot
change buffer size after data has been written
I tried to use something other event handler instead of preRenderView (I thought maybe the redirection should be made at an earlier point of the lifecycle(?)). With postAddToView event the result is the same, other events are not called at all.
Also instead of f:event I tried to use f:viewAction of JSF 2.2, but in case of ajax post none of the possible viewAction events is called on the error page (onPostback="true" parameter also did not help).
Questions:
Why I get the other exception on error page in case of redirection? (There was no any problem with myfaces 2.1)
Why viewAction function is not called at all on error page? (when the error resulted to go to the error page occured in an ajax request)
So how to make (conditional) redirect from error-page with JSF (myfaces) 2.2?

If i lost the JSF Session scope i want to change to the login page

I used JSF 2.2 Mojarra and the Session Scope.
After some time the Session Scope is delete or something else. If I go back to the login page and login again I have a new Session Scope and everything worked again.
If I worked on the web application the Session Scope is not lost, and I have no problem. So I think it must be lost after some time if I don't use the web application.
Any idea how can I automatically go back to the login page if I lost the session scope?
To expect this first your state saving method should be set to server like below
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
After this you should have a session time out like below in your web.xml
<session-config>
<session-timeout>20</session-timeout>
</session-config>
If you are idle for more than 20 minutes and if try to make any request from the page then you would see a exception stack trace of ViewExpiredException. Now to redirect to the login page on this you have a have the following config in web.xml
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>your login page path</location>
<error-page>
This would work if you make a non ajax request from the page after session time out. Now to make it to work on click of a an ajax button it requires special exception handler for exceptions on ajax requests. you can use <pe:ajaxErrorHandler> from primefaces extension library.
To use this you need to have following in your faces-config.xml
<application>
<el-resolver> org.primefaces.application.exceptionhandler.PrimeExceptionHandlerELResolver</el-resolver>
</application>
<factory>
<exception-handler-factory>org.primefaces.application.exceptionhandler.PrimeExceptionHandlerFactory</exception-handler-factory>
</factory>
And primefaces extension namespace xmlns:pe="http://primefaces.org/ui/extensions".
Now in your page just have <pe:ajaxErrorHandler /> in your page. This would navigate to login page on ajax button click in a page after session time out.
For automatic navigation to login page on time out you can use <p:idleMonitor> Something like
<p:idleMonitor timeout="6000" onidle="idleDialog.show()" />
Please have a look at this question for correct implementation of idle monitor
Timeout via idlemonitor (primefaces)
If you are using icefaces please visit the following link
JSF Session timeout and auto redirect to login page without user intraction eventhough Ajax push is active
You can also use omnifaces FullAjaxExceptionHandler, Please google for this.
Hope this helps!!!

websphere 7 shows full error to customer on web app deployment/starting error

i have deployed my web application in WebSphere 7. this application is build using spring and jsp servlets. some times when it get deployed due to errors it shows the following attached image like errors.
i have handled my web application errors as follows, by redirecting the errors to spring controller.
<error-page>
<error-code>500</error-code>
<!--Internal server error -->
<location>/error.p?message=500</location>
</error-page>
<error-page>
<error-code>403</error-code>
<!--Forbidden -->
<location>/main.p</location>
</error-page>
but it only works when the web application is successfully deployed. when deployment error happens WebSphere shows full error message like above.
is there any way to hide this error page and add custom error page in websphere when such deployment errors happens?
If you have an Apache server (or other) in front of your WebSphere, you may use it to redirect error 500 on a custom static web page.
Since you're using Spring, if this error can occur often, you can try to use lazy bean initialization on the remoteOMSConnectorWS (See LazyInitTargetSource). This would delay bean instantiation until its first use, most likely after webapp complete startup. In this case, your error configuration from web.xml could be used.

Error pages with Servlet 3.0

In the web.xml file, I'm trying to specify an error page as follows.
<error-page>
<location>/WEB-INF/jsp/admin/ErrorPage.jsp</location>
</error-page>
I expect it to go without an error code according to Servlet 3.0 but it doesn't. I have to explicitly specify an appropriate error code for it to work something like the following.
<error-page>
<description>Missing page</description>
<error-code>404</error-code>
<location>/WEB-INF/jsp/admin/ErrorPage.jsp</location>
</error-page>
Why doesn't the former approach work with Servlet 3.0?
I have upgraded NetBeans 7.2.1. It supports Apache Tomcat 7.0.27.0 which has Servlet 3.0 API.
By the way, I have disabled the HTTP Monitor as it raises the following warning.
MonitorFilter::WARNING: the monitor filter must be the first filter in
the chain.
It happened when I used Spring security in my application and it was reported as a jira issue.
Have a look at this post. I never personally made this
<error-page>
<location>/WEB-INF/jsp/admin/ErrorPage.jsp</location>
</error-page>
working on Tomcat 7, as for the bug described in the link I gave you. I don't know if Apache solved it in later version of Tomcat, but I doubt.
My previous statement was probably wrong. Digging a bit, I found this: https://issues.apache.org/bugzilla/show_bug.cgi?id=52135 and the problem should have been solved in Tomcat 7.0.29, so your only solution is to update to post-29 version.
Here: http://tomcat.apache.org/tomcat-7.0-doc/changelog.html, in the changelog for version 7.0.29 you can read why there was such an issue:
Add support for a default error page to be defined in web.xml by
defining an error page with just a nested location element. It appears
this feature was intended to be included in the Servlet 3.0
specification but was accidently left out. (markt)

Resources