Thursday, January 24, 2013

JSF 2.x Tip of the Day: AJAX Redirection from @WebFilter (Filter)

I was working on an application where I needed to have it redirect to a login page when certain conditions exist in the application, e.g. session timeout, etc. A ViewExpiredException custom exception handler (available in JSF 2.0) can handle this case, but I had a need for another type of "Session" object to be monitored to determine if I should redirect based on its status. The other object was stored in the HttpSession object as an attribute so I decided to handle it with a Filter (@WebFilter).

The first thing is to determine if the request is a partial/ajax request. If it is a normal post, we can handle it with a HttpResponse.sendRedirect(String location) mechanism. If it is AJAX, we need to handle it in a completely different manner.
1
2
3
4
5
6
7
8
private boolean isAJAXRequest(HttpServletRequest request) {
    boolean check = false;
    String facesRequest = request.getHeader("Faces-Request");
    if (facesRequest != null && facesRequest.equals("partial/ajax")) {
        check = true;
    }
    return check;
}
Once I determined that the request was AJAX, I needed to be able to pass the appropriate response back to the JSF page in a format that it could understand. A great tip came from Jim Driscoll's blog: Redirecting from a JSF 2.0 Ajax Request which gave me the general syntax for what I needed to send back.

Note: This is being intercepted in a Filter so I don't have access to the FacesContext. Here is a partial code snippet of how to send the redirect. You would need to set the variable TARGET to go to the desired location.
1
2
3
4
5
6
7
8
9
10
11
12
String redirectURL = response.encodeRedirectURL(request.getContextPath() + TARGET);
 
if (isAJAXRequest(request)) {
    StringBuilder sb = new StringBuilder();
    sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><partial-response><redirect url=\"").append(redirectURL).append("\"></redirect></partial-response>");
    response.setHeader("Cache-Control", "no-cache");
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/xml");
    PrintWriter pw = response.getWriter();
    pw.println(sb.toString());
    pw.flush();
}

2 comments :

Markus Eisele said...

Hi John,

thanks for that post. I love to follow your JSF experiences and tips.
Just a short head ups, that there actually _IS_ a way to get hand on the FacesContext in Filters and Servlets ...
please compare what Lincoln and BalusC wrote:

http://ocpsoft.org/java/jsf-java/jsf-20-extension-development-accessing-facescontext-in-a-filter/

http://balusc.blogspot.de/2006/06/communication-in-jsf.html#AccessingTheFacesContextInsideHttpServletOrFilter

Thanks,
- M

John Yeary said...

Those are some great blog posts. ;-)

In my case, I had some external actors on my application that cause a state holder in the application to timeout (outside of JSF). This timeout could occur if some navigated to a page and just let it sit until it timed out. There is a filter which checks the state holder, and I needed a mechanism to redirect in a very simple manner back to a login page in JSF.

The details I posted are a simple solution to a PITA problem that was added to the requirements after the code for the application was written.

If I had to do it again, knowing about these blog posts I would have reconsidered it. However, I think my solution is simple.

If you take the posts lists, and combined them with the code from Jim Driscoll's blog http://weblogs.java.net/blog/driscoll/archive/2009/05/redirecting_fro.html you would have another solution where you could do some more complex processing.

I will keep the information you added in my archive of useful tips.

I love our community. Share the love.

Popular Posts