ViewExpiredException - why different behaviour? - jsf-2

I have a JSF 2 application and configured the following in web.xml:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/error.html</location>
</error-page>
For testing purposes I have the following code in a #SessionScoped class within an init Method annotated with #PostConstruct in order to let the session quickly expire:
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
HttpSession session = (HttpSession) ec.getSession(false);
session.setMaxInactiveInterval(5);
Now, when I have an h:commandButton with outcome = "somepage.jsf" then a click after the 5s will redirect to the error page.
When I instead call some bean action or putting the page name in action on the very same button using the action attribute , I see the ViewExpiredException in the server's log, but no redirection occurs.
Why is that so? And how to generally redirect to another page no matter which action took place after the session expires?

The behaviour is different because an asynchronous (ajax) request is been sent. Ajax requests require a special XML response. Exceptions on ajax requests needs to be handled by either the jsf.ajax.addOnError handler in JavaScript or a custom ExceptionHandler.
By default they have namely no single form of helpful feedback in the client side. Only in Mojarra with project stage set to Development you'll see a bare JavaScript alert message with the exception message. But that's it. There is no single form of feedback in Production stage.
With a custom ExceptionHandler you would be able to simulate exactly the same form of feedback as in synchronous requests. You could parse the web.xml to find the proper error page location, create a new UIViewRoot around it and force JSF to set ajax rendering to #all. Since that's after all relatively quite some work, the JSF utility library OmniFaces provides exactly such an exception handler out the box in flavor of FullAjaxExceptionHandler. You can find the showcase page here.

Related

ExternalContext.dispatch() not working

On p:ajax call,listener invokes method which contains
FacesContext.getCurrentInstance().getExternalContext().dispatch("/uri.jsf");
doesn't work. Ive set a break point on the line and it remains at the same point on execution.It doesn't move forward, I ve got to restart server to run the application again.
FacesContext.getCurrentInstance().getExternalContext().redirect("/uri.jsf");
redirection works perfectly fine. But i want page forward which is dispatch to navigate to another page.
The ExternalContext#dispatch() does not support ajax requests. It causes JSF to render the HTML output of the given resource which can't be understood by the JavaScript ajax engine. The ajax request has to return a special XML response which can be understood by the JavaScript ajax engine.
The ExternalContext#redirect() supports ajax requests. It will automatically return a special XML response instructing the JavaScript ajax engine to invoke a window.location call on the given URL (you can find an XML example in this answer).
You have 2 options:
Make it a non-ajax request.
Perform a normal JSF navigation.
Making a non-ajax request is most likely not an option for <p:ajax>. In that case, performing a normal navigation is really your only option.
FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().getNavigationHandler().handleNavigation(context, null, "/uri.jsf");
It will in case of ajax requests automatically force an render="#all" with the new content.

Error page defined in web.xml is embedded in partially rendered JSF page

I have the following defined in web.xml:
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/shared/errors/DefaultErrorPage.xhtml</location>
</error-page>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/shared/errors/ViewExpired.xhtml</location>
</error-page>
I'm also using the FullAjaxExceptionHandler from Omnifaces in faces-config.xml:
<factory>
<exception-handler-factory>
org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory
</exception-handler-factory>
</factory>
The FullAjaxExceptionHandler is working fine for ajax calls, but when I hit a page directly and there is an error, it starts rendering the page I was trying to go to, but it doesn't finish, and then the error page defined in web.xml is rendered, which results in the error page being embedded after a partially rendered page.
(I'm using Glassfish 3.1.1 which has Mojarra JSF 2.1.3) Edit: now using Glassfish 3.1.2.2 and JSF 2.1.11
Edit: Discovered the following:
The page where the error is happening is using templates (<ui:composition template="/shared/shared/commonLayout.xhtml">) If I change it so that the page is no longer using the template, and then just add in all of the code from the template then it works fine.
This will happen when the response is already committed before the exception is been thrown. The response will be committed when ServletOutputStream#flush() has deep under the JSF covers explicitly been invoked in some way, which is more than often only when the response buffer (defaults usually to 2KB in most containers) has been overflowed. A committed response is a point of no return. The server cannot take the already-sent bytes back from the client. The server has basically 2 options:
Leave the response as is and log the exception to the server log only.
Try writing the error page to the response anyway.
Your Glassfish setup apparently chooses the 2nd way. None of them is perfect. The client would still end up with a halfbaked HTML response and whatever it would end up to look like to the enduser depends on how the webbrowser can do its best in interpreting and presenting the so far obtained HTML.
You, as JSF developer, can however use several approaches to avoid this from happening. In first place, why exactly is that exception been thrown during rendering the response? Doesn't that actually indicate a bug in your own code? Wouldn't you better perform the exception-sensitive business job before rendering the response? You could use among others <f:event type="preRenderView"> for this.
<f:event type="preRenderView" listener="#{bean.init}" />
If that's really not an option for some reason, you could consider increasing the response buffer size to above the size of the largest HTML response, so that the response won't be auto-flushed before the exception occurs. You can do that by the following context parameter which assumes that every HTML response fits within the 100KB limit:
<context-param>
<param-name>javax.faces.FACELETS_BUFFER_SIZE</param-name>
<param-value>102400</param-value><!-- 100KB -->
</context-param>

How to prevent form submission using GET method in JSF 2.0?

I am developing an JSF 2.0 application for IBM Webshere 7.0 and I want to prevent user submitting a form using the GET method for security reason i.e user will not be able to submit a form appending the form values to the Query String.
Is there any simple solution for this or I need to build filter to prevent this ?
When you use JSF <h:form> it does a POST request be default. Even though a Query string is sent, since the submission method is POST, the result is not sent as a query string, that is, it is not added to the action URL of the form. Rather, the string is sent as the body of the HTTP request and the doPost() method of the FacesServlet will be invoked.
See also:
Proper way to call servlet from Facelets?
http://en.wikipedia.org/wiki/Query_string

Redirection to an external website in a Portlet

I have a portlet where the doView method calls the display.jsp page with the following instruction :
getPortletContext().getRequestDispatcher("/views/display.jsp").dispatcher.include(request, response);
In the display.jsp, I want to do a redirection to an external website :
<%
response.sendRedirect("http://www.google.fr");
%>
Why is it not working at all ?
(I put a <div>foobar<div> in the JSP to see if that works and it does)
Is there another solution to make a redirection to an external URL ?
(The idea is to "stay" in the portlet/portal where the user can see the "targetted" website)
Regards.
If you look at Page 141 of the Portlet 2.0 specification , it mentions that HttpServletRespone#sendRedirect() is a NO-OP in the render phase.
So that is the reason why you don't see this working. As per the semantics, the response object is a HttpServletResponse which corresponds to the response for the whole page and not just the portlet to which this JSP belongs. Since the page is now a composition of multiple portlets and each portlet having it's own lifecycle, you should be using one of the renderResponse, actionResponse objects and avoid using the servlet objects.
I am yet to find a solution for your original problem though.

How to implement a navigation button in JSF 2.0 that doesnt do any validations of anything on the current page?

I want to implement a navigation button that takes the user to another page. I have no desire or need for any validations to run nor for the model to be updated, etc. I have implemented this as an ajaxified client-side redirect (note, I am using Primefaces 3.2).
It works-- but is this the best way to do this?
Navigating from the "onePage.xhtml" to the "anotherPage.xhtml"
onePage.xhtml:
...
<p:commandButton value="Navigate to Another Page"
process="#this"/>
action="anotherPage?faces-redirect=true"
...
Note, I have tried using immediate="true", however Apply Request Values phase still runs, which results in a NPE for me in a getter in my managed bean (as I no longer have the data that my getter needs).
Just use <h:button> or <p:button>. It sends a normal GET request. There's really no need for a POST-Redirect-GET request if it's just page-to-page navigation.
<h:button value="Navigate to Another Page" outcome="anotherPage" />
For the PrimeFaces look'n'feel, just replace h: by p:. Note that this component doesn't require a <h:form>. The link equivalent is the <h:link> (for which there's no PrimeFaces equivalent, there's anyway nothing which needs to be restyled).
See also:
When should I use h:outputLink instead of h:commandLink?
Set attribute immediate to true on commandButton, this will skip all validations, conversions or updates. Attributes causes JSF lifecycle to jump from Apply request values phase directly to Render Response phase.

Resources