Reputation: 12876
I have a JSF Phase Listerner that checks to see if the user is logged in, and if not, redirects them to the login page. This is working fine for non-ajax requests. However, if the user is on a page, in my case, one that has a primefaces data table, and clicks on a button that invokes an ajax request -- but their session has timed out -- the code gets executed that issues the redirect (using ExternalContext#redirect
), however the user is not navigated to the login page.
Any idea why this is not working?
Here is my phase listener:
private static final String IS_LOGGED_IN_INDICATOR = "loggedIn";
private static final String LOGIN_PAGE = "/login.jsp";
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
public void beforePhase(PhaseEvent event) {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
HttpSession session = (HttpSession)ec.getSession(false);
if (session==null || session.getAttribute(IS_LOGGED_IN_INDICATOR) == null) {
try {
ec.redirect(LOGIN_PAGE);
}
catch(IOException e) {
// log exception...
}
}
}
public void afterPhase(PhaseEvent event) {
// no-op
}
}
Upvotes: 1
Views: 4836
Reputation: 1108742
It failed because the ajax context is trying to obtain the render kit from the view root, while there is no view root at all. It has not been restored at that point yet. This resulted in a NullPointerException
in PartialViewContext#createPartialResponseWriter()
. This exception is in turn not been thrown, but instead been put in an ajax exception queue which is supposed to be handled by a custom ExceptionHandler
. You apparently don't have any one. This exception is visible if you create/use such one like the FullAjaxExceptionHandler
(see also this blog for more detail).
To fix the particular problem, do the job in afterPhase()
instead. The view root is then fully restored and the ajax context can obtain the render kit from it in order to write a specialized XML response which instructs the JSF ajax engine in JavaScript to change the window location. Without ajax, a render kit was not necessary as a redirect is basically just a matter of setting a response header.
Whether the particular NullPointerException
is in turn a bug in Mojarra or not is a different question which can better be posted in flavor of an issue report at their own issue tracker.
Upvotes: 3
Reputation: 418
this is because you have to send a special response in XML for Ajax request in order to do redirect (check this answer) , I have implemented this in a Filter like this..
// Check if it's an Ajax Request
if ("partial/ajax".equals(((HttpServletRequest) request).getHeader("Faces-Request"))) {
//redirect
response.setContentType("text/xml");
response.getWriter()
.append("<?xml version= \"1.0\" encoding=\"UTF-8\"?>")
.printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>",url);
you should port this to your Phase Listener.
Upvotes: -1