ajax ppr redirect on error

UI Components for JSF
sideswipe
Posts: 5
Joined: 28 Sep 2010, 21:08

27 Nov 2010, 06:20

still no "all works fine" solution.. i had some progress but am stuck at the point that i can
1) do redirect in case of ajax calls
2) do redirect in case of non-ajax calls
there is no 1) and/or 2), only 1) XOR 2).. means i can handle ajax calls OR non-ajax calls to do a redirect and some other problems i will mention in the following

first i would like to say what i have done so far (it feels like hackish.. expecialy the ajax-call redirect)

i combined varoius solutions and ideas to the following:
(most of it i found googleing and combined it.. sources are
ajax redirect http://stackoverflow.com/questions/1990 ... 895#579895
non ajax redirect http://techieexchange.wordpress.com/200 ... -solution/)

here is what i have combined the ideas to:
MySessionListener

Code: Select all

import java.util.Date;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * Thanks to hturksoy
 **/
public class MySessionListener implements HttpSessionListener {

	public MySessionListener() {
	}

	public void sessionCreated(HttpSessionEvent event) {
		System.out.println("Current Session created : "
				+ event.getSession().getId() + " at " + new Date());
	}

	public void sessionDestroyed(HttpSessionEvent event) {
		// get the destroying session...
		HttpSession session = event.getSession();
		System.out.println("Current Session destroyed :" + session.getId()
				+ " Logging out user...");

		// Only if needed
		try {
			prepareLogoutInfoAndLogoutActiveUser(session);
		} catch (Exception e) {
			System.out
					.println("Error while logging out at session destroyed : "
							+ e.getMessage());
		}
	}

	/**
	 * Clean your logout operations.
	 */
	public void prepareLogoutInfoAndLogoutActiveUser(HttpSession httpSession) {

		// Only if needed
		httpSession.invalidate();
	}
}
SessionTimeoutFilter

Code: Select all

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Scope;

/**
 * When the session destroyed, MySessionListener will do necessary logout
 * operations. Later, at the first request of client, this filter will be fired
 * and redirect the user to the appropriate timeout page if the session is not
 * valid.
 * 
 * Thanks to hturksoy
 * 
 */
@Scope(ScopeType.APPLICATION)
public class SessionTimeoutFilter implements Filter {


	private String timeoutPage = "home";
	
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain filterChain) throws IOException, ServletException {
		if ((request instanceof HttpServletRequest)
				&& (response instanceof HttpServletResponse)) {
			HttpServletRequest httpServletRequest = (HttpServletRequest) request;
			HttpServletResponse httpServletResponse = (HttpServletResponse) response;
			// is session expire control required for this request?
			if (isSessionControlRequiredForThisResource(httpServletRequest)) {
				// is session invalid?
				if (isSessionInvalid(httpServletRequest)) {
					String timeoutUrl = httpServletRequest.getContextPath()
							+ "/" + getTimeoutPage();
					// NON-AJAX ONLY
					httpServletResponse.sendRedirect(timeoutUrl);
					// AJAX ONLY
					httpServletResponse.addHeader("GOTO_TIMEOUT_PAGE",timeoutUrl);
					return;
				}
			}
		}
		filterChain.doFilter(request, response);
	}

	private boolean isSessionControlRequiredForThisResource(
			HttpServletRequest httpServletRequest) {
		String requestPath = httpServletRequest.getRequestURI();
		boolean controlRequired = !StringUtils.contains(requestPath,
				getTimeoutPage());
		return controlRequired;
	}

	private boolean isSessionInvalid(HttpServletRequest httpServletRequest) {
		boolean sessionInValid = (httpServletRequest.getRequestedSessionId() != null)
				&& !httpServletRequest.isRequestedSessionIdValid();
		return sessionInValid;
	}

	public void destroy() {
	}

	public String getTimeoutPage() {
		return timeoutPage;
	}

	public void setTimeoutPage(String timeoutPage) {
		this.timeoutPage = timeoutPage;
	}
}
web.xml (part)

Code: Select all

<session-config><!-- timeout 1 minute to test the expire redirect -->
		<session-timeout>1</session-timeout>
	</session-config>
	<listener>
		<listener-class>package.MySessionListener</listener-class>
	</listener>
	<filter>
		<filter-name>SessionTimeoutFilter</filter-name>
		<filter-class>package.SessionTimeoutFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>SessionTimeoutFilter</filter-name>
		<servlet-name>Faces Servlet</servlet-name>
	</filter-mapping>
in my test.xhtml to do the ajax-redirect or normal redirect (over navigation from links in the top-bar, comes from the template.xhtml)

Code: Select all

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:s="http://jboss.com/products/seam/taglib"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.prime.com.tr/ui"
	template="layout/template.xhtml">
	<ui:define name="head">
		<script type="text/javascript">
/* <![CDATA[ */
              new PrimeFaces.widget.AjaxStatus('uniqueIdentifier0815').bindCallback('ajaxComplete',function(event,request,settings){

		          alert("debug: " + request.getResponseHeader('GOTO_TIMEOUT_PAGE'));
		          if (request.getResponseHeader('GOTO_TIMEOUT_PAGE') != null) {

		        	  window.location = request.getResponseHeader('GOTO_TIMEOUT_PAGE');
			      }
		      });
/* ]]> */
		</script>
	</ui:define>
	<ui:define name="body">
		<p:growl id="growl" showDetail="true" />
		<h:form id="mainForm">
			<p:commandButton ajax="true" value="TestAjax"
							update="growl" action="#{backingBean.serverAction}" />
		</h:form>
	</ui:define>
</ui:composition>
the behaviour is the following:
if i do (in SessionTimeoutFilter) only the following:

Code: Select all

...
httpServletResponse.addHeader("GOTO_TIMEOUT_PAGE",timeoutUrl);
...
and wait the minute so the session expires.. then press the button "Test" on the page the

Code: Select all

 new PrimeFaces.widget.AjaxStatus('uniqueIdentifier0815').bindCallback('ajaxComplete',function(event,request,settings){

		          alert("debug: " + request.getResponseHeader('GOTO_TIMEOUT_PAGE'));
		          if (request.getResponseHeader('GOTO_TIMEOUT_PAGE') != null) {

		        	  window.location = request.getResponseHeader('GOTO_TIMEOUT_PAGE');
			      }
		      });
responseheader is set and i get redirected correctly

but if i do normal (non ajax action involved) navigation in the topbar.. nothing happens (why should.. i only added a response header ;) )

so i add (in SessionTimeoutFilter) the

Code: Select all

...
httpServletResponse.sendRedirect(timeoutUrl);
httpServletResponse.addHeader("GOTO_TIMEOUT_PAGE",timeoutUrl);
...
line. now if i do normal (non ajax action involved) navigation in the topbar.. i get redirected correctly
BUT if i press the "Test" button on the page nothing happens.. the ajax callback function is not called at all
so i can only
1) do redirect in case of ajax calls
2) do redirect in case of non-ajax calls
but not the combination of both..

another problem is that i only know the

Code: Select all

new PrimeFaces.widget.AjaxStatus('uniqueIdentifier0815').bindCallback('ajaxComplete',function(...
place for hooking up ajax callbacks.. wich is not always triggered
in the case of

Code: Select all

<p:commandButton global="false" ...
the ajaxStatus is not called (as defined.. ;) )
so if the combination problem of 1) AND 2) together is solved.. there would stand the question "how to hook up ANY ajax request?"

the questions now are:
how to combine the way 1) AND 2), not only 1) XOR 2)?
how to hook up ANY ajax request on client-side?
is there another way get the sessiontimeout redirect working for normal navigation and ajax-requests with jsf 1.2 (except switch to jsf 2.0 *gg* )?

thank you

vetler
Posts: 9
Joined: 27 Aug 2010, 12:37

01 Dec 2010, 16:23

how to hook up ANY ajax request on client-side?
You can do this by hooking onto ajaxError (or one of the other global Ajax events: http://docs.jquery.com/Ajax_Events), like this:

Code: Select all

jQuery('body').bind('ajaxError', function(event, xhr) {
  // Do stuff
});
We ended up setting the redirect url as a response header, and redirecting like this:

Code: Select all

jQuery('body').bind('ajaxError', function(event, xhr){
    var status = xhr.status;
    console.log("Global ajaxError: "+ xhr + ", "+ status);
    if (status == 500) {
        console.log("Redirecting to error servlet: " + xhr.getResponseHeader('X-ERROR-PAGE'));
        window.location = xhr.getResponseHeader('X-ERROR-PAGE');
    }
});
A custom exception handler sets the response header, and also adds status information to the HttpSession.
It seems to work. Not very pretty, perhaps. Would be nice if Primefaces could be extended to more elegantly handling Ajax errors of all kinds.

User avatar
pitutos
Posts: 52
Joined: 23 Jul 2010, 01:28

13 Apr 2011, 19:52

Hi all! I simply use the p:idleMonitor configure with the value of session timeout and a redirect on "onactive" event, and it's works for now!
NetBeans 7.1
Mojarra-2.1.7
PrimeFaces-3.0.1
Tomcat 7.0.22

seycsx
Posts: 18
Joined: 04 Dec 2010, 04:31
Location: Jacksonville, FL, USA

13 Jul 2011, 20:44

I would like some help with the redirect for Primefaces 2.2.1 and Mojarra 2.0.6. Ajax actions on p:dataTable are my issue, such as paging and sorting.

I've got the ViewExpiredExceptionExceptionHandler in place, and it is catching the ViewExpiredException when attempting to sort a datatable after the view has expired. But I can't seem to get the redirect to work. My page doesn't even blink - as far as the user can tell, it just doesn't work.

But on the server, my ViewExpiredExceptionExceptionHandler is catching the exception. I have tried the code posted above, modified to make it compile. Even tried changing FacesContext to indicate it is NOT a partial view request, and then get a new response writer. I haven't hit the magic combination to make it work, though.

I'm having trouble with the code to make the browser redirect to the Timeout page, from the exception handler. Has anybody conquered this with Primefaces 2.2.1? Or even 3.0?
IBM Websphere App Server v7.0.0.19
Mojarra 2.1.9 (SNAPSHOT 20120531-1326)
Primefaces 3.3.1 - experimenting 3.4

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 18 guests