Page 1 of 2

Primefaces AjaxErrorHandler

Posted: 10 Oct 2012, 12:52
by Nozi
Hello, im using AjaxErrorHandler with CAS ( Central Authentication Service ). Application is on JBoss 7.1, and CAS is on Tomcat. My problem is that i get "Http 302 moved temporarily" when on jboss session expires and i do ajax request. How do i need to solve this??

Re: Primefaces AjaxErrorHandler

Posted: 10 Oct 2012, 14:24
by Oleg
Have you put AjaxErrorHandler into the faces-config.xml? What version of PF Ext. do you use?

Re: Primefaces AjaxErrorHandler

Posted: 10 Oct 2012, 14:38
by Nozi
Yes, I have tried pe:AjaxErrorHandler and yes, I did put it in faces config. I also tried PhaseListener and my own ViewExceptionHandler. Both solutions don't work when Session on jboss expires. What is more importantly, pe:AjaxErrorHandler or my own ViewExceptionHandler are never actually be called when its AJAX request.

I am using Primefaces 3.4.1. and Ext is 0.6.0

Re: Primefaces AjaxErrorHandler

Posted: 10 Oct 2012, 14:46
by tandraschko
If Oleg doesn't have a answer, you should ask the jboss guys.

Re: Primefaces AjaxErrorHandler

Posted: 10 Oct 2012, 17:24
by Oleg
How did you configure both handlers in one web app - your own ViewExceptionHandler and PF Ext. AjaxErrorHandler? Just interesting.

I don't use pe:ajaxErrorHandler in my apps. I use error handler from OmniFaces. I will ping our team member that implemented pe:ajaxErrorHandler. Maybe he can tell you more than we.

Re: Primefaces AjaxErrorHandler

Posted: 11 Oct 2012, 08:12
by Nozi
faces-config.xml

Code: Select all

<factory>
        <exception-handler-factory>org.primefaces.extensions.component.ajaxerrorhandler.AjaxExceptionHandlerFactory</exception-handler-factory>
 </factory>

Code: Select all

public class EregionExceptionHandlerFactory extends ExceptionHandlerFactory{
	
	private ExceptionHandlerFactory base;
    
    public EregionExceptionHandlerFactory(ExceptionHandlerFactory base) {
        this.base = base;
    }
    
    @Override
    public ExceptionHandler getExceptionHandler() {
        return new EregionExceptionHandler(base.getExceptionHandler());
    }

}

Code: Select all

public class EregionExceptionHandler extends ExceptionHandlerWrapper{
	
	private ExceptionHandler wrapped;

    public EregionExceptionHandler(ExceptionHandler wrapped) {
        this.wrapped = wrapped;
    }
	
	@Override
	public ExceptionHandler getWrapped() {
		 return this.wrapped;
	}
	
	@Override
    public void handle() throws FacesException {
		 for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {
	            ExceptionQueuedEvent event = i.next();
	            ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
	            Throwable t = context.getException();
	            if (t instanceof ViewExpiredException) {
	                ViewExpiredException vee = (ViewExpiredException) t;
	                FacesContext fc = FacesContext.getCurrentInstance();
	                Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();
	                NavigationHandler nav =
	                        fc.getApplication().getNavigationHandler();
	                try {
	                    requestMap.put("currentViewId", vee.getViewId());
	 
	                    nav.handleNavigation(fc, null, "index?faces-redirect=true&expired=true");
	                    fc.renderResponse();
	 
	                } finally {
	                    i.remove();
	                }
	            }
	        }
	        getWrapped().handle();        
	}

}

Code: Select all

<h:form prependId="false">
		<p:confirmDialog header="Info" severity="alert" appendToBody="true"
	                         visible="#{not empty param['expired']}" 
	                         message="Session expired" widgetVar="confirmDlg" >
	    	<p:commandButton type="button" value="OK" onclick="confirmDlg.hide()"/>
	    </p:confirmDialog>	
	</h:form>

<pe:ajaxErrorHandler />

Re: Primefaces AjaxErrorHandler

Posted: 11 Oct 2012, 09:25
by Oleg
I can not see any AjaxErrorHandler from PrimeFaces Extensions in your code. You haven't registered it in faces-config.xml at all. And if you didn't do this, it can not disturb you :-)

Re: Primefaces AjaxErrorHandler

Posted: 11 Oct 2012, 10:12
by Nozi
I have added this to faces-config.xml

Code: Select all

<factory>
        <exception-handler-factory>org.primefaces.extensions.component.ajaxerrorhandler.AjaxExceptionHandlerFactory</exception-handler-factory>
</factory>
It doesn't change a thing ;]

Re: Primefaces AjaxErrorHandler

Posted: 15 Oct 2012, 23:59
by Pavol Slany
Hi Nozi,

I think If you use CAS on JBOSS and your session is expired, every next request is redirected to LOGIN (maybe error) page. JSF livecycle is not called in this case, because this request is redirected on SECURITY layer (maybe filter of SpringSecurity) of your application server. Phase Listeners, AjaxErrorHandler and other JSF features are not working if JSF livecycle is not called.

I think, your problem has only one resolution: For login use SSO or basic access authentication (without redirect to login page) and try disable all error-page in web.xml.

Because every AJAX request is POST type, you can try to disable redirecting POST requests only.

Please, if you use SpringSecurity, can you show your spring configuration and web.xml?

Re: Primefaces AjaxErrorHandler

Posted: 16 Oct 2012, 19:55
by alexrk6@gmail.com
if you use Spring Security you can add custom SessionManagmentFilter which will do JSF-correct redirect instead of "simple" redirect:

1. Spring Context:

Code: Select all

	<security:http>
			...
		<security:custom-filter ref="jsfAjaxRedirectSessionManagementFilter" before="SESSION_MANAGEMENT_FILTER"/>
	</security:http>
	
	<bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>
	
	<bean id="jsfAjaxRedirectSessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">

		<!-- default -->
		<constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" />

		<property name="invalidSessionStrategy" ref="jsfRedirectStrategy" />
	</bean>

	<bean id="jsfRedirectStrategy" class="ru.evosystems.aurix.surfbird.web.session.AjaxJSFRedirectStrategy">
		<constructor-arg name="invalidSessionUrl" value="/views/login.jsf" />
	</bean>
2. And add class AjaxJSFRedirectStrategy:

Code: Select all

public class AjaxJSFRedirectStrategy implements InvalidSessionStrategy{
	private static final Logger log = LoggerFactory.getLogger(AjaxJSFRedirectStrategy.class);

	private String invalidSessionUrl;

	public AjaxJSFRedirectStrategy(String invalidSessionUrl) {
		this.invalidSessionUrl = invalidSessionUrl;
	}

	@Override
	public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		log.debug("onInvalidSessionDetected()");

		String url = request.getContextPath() + invalidSessionUrl;
		if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {

			log.debug("call JSF redirect to url: " + url);

			sendJsfRedirect(response, url);
		}
		else{
			log.debug("call standart response redirect to url: " + url);

			response.sendRedirect(url);
		}
	}
	
	public void sendJsfRedirect(HttpServletResponse response, String url) throws IOException{
		String ajaxRedirectXml =
				"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
				"<partial-response><redirect url=\""+url+"\"></redirect></partial-response>";
		response.setContentType("text/xml");
		response.getWriter().write(ajaxRedirectXml);
	}
}