I 've written a single page app with only navigation from login page through app and vice versa.
The only problem I faced is the view expired exception (session timeout).
When this happens I want to redirect to the login page (if possible with a message for the user)
but I can't get it implemented.
I've tried to extend the FacesServlet, to add a SessionListener, to use the onerror of <p:ajaxStatus>, ...
Any help is appreciated very much
ajax ppr redirect on error
Do you use JSF2? I have a solution for JSF2 with a special phase listener and default error handler.michiel wrote:I 've written a single page app with only navigation from login page through app and vice versa.
The only problem I faced is the view expired exception (session timeout).
When this happens I want to redirect to the login page (if possible with a message for the user)
but I can't get it implemented.
I've tried to extend the FacesServlet, to add a SessionListener, to use the onerror of <p:ajaxStatus>, ...
Any help is appreciated very much
PrimeFaces Cookbook (2. edition): http://ova2.github.io/primefaces-cookbook/ Learning Angular UI Development with PrimeNG: https://github.com/ova2/angular-develop ... th-primeng Blog: https://medium.com/@OlegVaraksin
-
- Prime
- Posts: 18616
- Joined: 05 Jan 2009, 00:21
- Location: Cybertron
- Contact:
Check out Ed's blog to handle viewExpiredExceptions;
http://weblogs.java.net/blog/edburns/ar ... ption-jsf2
http://weblogs.java.net/blog/edburns/ar ... ption-jsf2
I do use JSF-2.0, mojarra-2.0.2-FCS and PrimeFaces-2.0.3-SNAPSHOT on GlassFishv3.
I'll try to http://weblogs.java.net/blog/edburns/ar ... ption-jsf2
Thanks
I'll try to http://weblogs.java.net/blog/edburns/ar ... ption-jsf2
Thanks
JSF-2.0, mojarra-2.0.2-FCS and PrimeFaces-2.1 on GlassFish v3.0.1 (build 22)
Hello,
For Ajax redirects you needs a little bit more code than in Ed's blog. I'm going to post here my solution (just three centric classes to show the idea). I hope it will help you.
DefaultExceptionHandlerFactory
DefaultExceptionHandler
SecurityPhaseListener with redirect functionality (unfortunately with a little workaround for PrimeFaces, Cagatay? )
Configuration
For Ajax redirects you needs a little bit more code than in Ed's blog. I'm going to post here my solution (just three centric classes to show the idea). I hope it will help you.
DefaultExceptionHandlerFactory
Code: Select all
/**
* This is a factory class that creates (if needed) and returns a new {@link DefaultExceptionHandler} instance.
*
* <p>Using this functionality requires the following section in the faces-config.xml:</p>
*
* <pre>
<factory>
<exception-handler-factory>ip.client.jsftoolkit.exceptions.DefaultExceptionHandlerFactory</exception-handler-factory>
</factory>
* </pre>
*/
public class DefaultExceptionHandlerFactory extends ExceptionHandlerFactory
{
//~ Instance fields --------------------------------------------------------
private ExceptionHandlerFactory parent;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new DefaultExceptionHandlerFactory object.
*
* @param parent parent instance of {@link ExceptionHandlerFactory}
*/
public DefaultExceptionHandlerFactory(ExceptionHandlerFactory parent)
{
this.parent = parent;
}
//~ Methods ----------------------------------------------------------------
/**
* @see javax.faces.context.ExceptionHandlerFactory#getExceptionHandler()
*/
@Override
public ExceptionHandler getExceptionHandler()
{
ExceptionHandler eh = parent.getExceptionHandler();
eh = new DefaultExceptionHandler(eh);
return eh;
}
}
Code: Select all
/**
* Default implementation of exception handler to catch unchecked / unexpected exceptions in order to proper display.
* The method {@link #handleUnexpected(FacesContext, Throwable)} can be overwritten in derived class in order to
* customization. Handling of various unexpected exceptions can be done there. Example of using:
*
* <pre>
protected String handleUnexpected(FacesContext facesContext, final Throwable t)
{
if (t instanceof IllegalStateException) {
// some special handling here
...
return "key.exception.IllegalStateException";
} else {
return super.handleUnexpected(facesContext, t);
}
}
</pre>
*/
public class DefaultExceptionHandler extends ExceptionHandlerWrapper
{
//~ Static fields/initializers ---------------------------------------------
/** logger */
private static final Log LOG = LogFactory.getLog(DefaultExceptionHandler.class);
/** key for session scoped message detail */
public static final String MESSAGE_DETAIL_KEY = "ip.client.jsftoolkit.messageDetail";
//~ Instance fields --------------------------------------------------------
private ExceptionHandler wrapped;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new DefaultExceptionHandler object.
*
* @param wrapped wrapped exception handler instance
*/
public DefaultExceptionHandler(ExceptionHandler wrapped)
{
this.wrapped = wrapped;
}
//~ Methods ----------------------------------------------------------------
/**
* @see javax.faces.context.ExceptionHandlerWrapper#getWrapped()
*/
@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();
String redirectPage = null;
FacesContext fc = FacesContext.getCurrentInstance();
Throwable t = context.getException();
try {
if (t instanceof AbortProcessingException) {
// about AbortProcessingException see JSF 2 spec.
LOG.error("An unexpected exception has occurred by event listener(s)", t);
redirectPage = "/views/error.jsf?statusCode=jsftoolkit.exception.UncheckedException";
fc.getExternalContext().getSessionMap()
.put(DefaultExceptionHandler.MESSAGE_DETAIL_KEY, t.getLocalizedMessage());
} else if (t instanceof ViewExpiredException) {
if (LOG.isDebugEnabled()) {
LOG.debug("View '" + ((ViewExpiredException) t).getViewId() + "' is expired", t);
}
ApplicationConfiguration appConfiguration =
(ApplicationConfiguration) FacesAccessor.accessManagedBean(
fc, ApplicationConfiguration.BEAN_NAME_APPLICATION_CONFIGURATION);
HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);
if (session != null) {
// should not happen
session.invalidate();
}
if (appConfiguration.getBoolean(ConfigKeys.KEY_LOGOFF_2_LOGOUT_PAGE, false)) {
// redirect to the specified logout page
redirectPage = "/views/logout.jsf";
} else {
// redirect to the login page
redirectPage = "";
}
} else if (t instanceof ServiceNotAvailableException) {
LOG.error("'" + ((ServiceNotAvailableException) t).getServiceName() + "' is not available", t);
redirectPage = "/views/error.jsf?statusCode=jsftoolkit.exception.ServiceNotAvailableException";
} else {
// custom handling of unexpected exceptions can be done in the method handleUnexpected
String messageKey = handleUnexpected(fc, t);
redirectPage = "/views/error.jsf?statusCode=" + messageKey;
fc.getExternalContext().getSessionMap()
.put(DefaultExceptionHandler.MESSAGE_DETAIL_KEY, t.getLocalizedMessage());
}
} finally {
i.remove();
}
SecurityPhaseListener spl = new SecurityPhaseListener();
spl.doRedirect(fc, redirectPage);
break;
}
}
/**
* This method can be overwritten in derived classe in order to customization. Handling of various unexpected
* exceptions can be done here.
*
* @param facesContext current faces context {@link FacesContext}
* @param t Throwable exception
* @return String key for error message
*/
protected String handleUnexpected(FacesContext facesContext, final Throwable t)
{
LOG.error("An unexpected internal error has occurred", t);
return "jsftoolkit.exception.UncheckedException";
}
}
Code: Select all
/**
* Phase listener for the Restore View Phase which manages display of login page.
*/
public class SecurityPhaseListener implements PhaseListener
{
//~ Static fields/initializers ---------------------------------------------
/** logger */
private static final Log LOG = LogFactory.getLog(SecurityPhaseListener.class);
//~ Methods ----------------------------------------------------------------
public void afterPhase(PhaseEvent event)
{
;
}
public void beforePhase(PhaseEvent event)
{
FacesContext fc = event.getFacesContext();
String loginPage = (String) fc.getExternalContext().getRequestMap().get(Authenticator.SHOW_LOGIN_ATTRIBUTE);
if (StringUtils.isNotBlank(loginPage)) {
doRedirect(fc, loginPage);
}
}
public PhaseId getPhaseId()
{
return PhaseId.RESTORE_VIEW;
}
/**
* Does a regular or ajax redirect.
*
* @param fc current faces context
* @param loginPage context relative login page URL
* @throws FacesException if redirect failed
*/
public void doRedirect(FacesContext fc, String loginPage) throws FacesException
{
ExternalContext ec = fc.getExternalContext();
try {
// workaround for PrimeFaces
new RequestContextImpl(ec);
if (ec.getRequestParameterMap().containsKey(Constants.PARTIAL_PROCESS_PARAM)
&& !ec.getRequestParameterMap().get(Constants.PARTIAL_PROCESS_PARAM).equals("@all")) {
fc.setViewRoot(new PartialViewRoot(new UIViewRoot()));
}
// fix for renderer kit (Mojarra's and PrimeFaces's ajax redirect)
if ((RequestContext.getCurrentInstance().isAjaxRequest()
|| fc.getPartialViewContext().isPartialRequest())
&& fc.getResponseWriter() == null
&& fc.getRenderKit() == null) {
ServletResponse response = (ServletResponse) ec.getResponse();
ServletRequest request = (ServletRequest) ec.getRequest();
response.setCharacterEncoding(request.getCharacterEncoding());
RenderKitFactory factory =
(RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
//RenderKit renderKit = factory.getRenderKit(fc, RenderKitFactory.HTML_BASIC_RENDER_KIT);
RenderKit renderKit =
factory.getRenderKit(fc, fc.getApplication().getViewHandler().calculateRenderKitId(fc));
ResponseWriter responseWriter =
renderKit.createResponseWriter(response.getWriter(), null, request.getCharacterEncoding());
fc.setResponseWriter(responseWriter);
}
ec.redirect(ec.getRequestContextPath() + (loginPage != null ? loginPage : ""));
} catch (IOException e) {
LOG.error("Redirect to the specified page '" + loginPage + "' failed");
throw new FacesException(e);
}
}
}
Code: Select all
<?xml version="1.0"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<absolute-ordering>
<others />
<name>jsftoolkit</name>
</absolute-ordering>
<factory>
<exception-handler-factory>
ip.client.jsftoolkit.commons.DefaultExceptionHandlerFactory
</exception-handler-factory>
</factory>
<lifecycle>
<phase-listener>
ip.client.jsftoolkit.commons.SecurityPhaseListener
</phase-listener>
</lifecycle>
.....
</faces-config>
PrimeFaces Cookbook (2. edition): http://ova2.github.io/primefaces-cookbook/ Learning Angular UI Development with PrimeNG: https://github.com/ova2/angular-develop ... th-primeng Blog: https://medium.com/@OlegVaraksin
with your help I finally figured it out.
I took the the solution from Ed Burns blog as base and fixed it with Oleg's response.
Here is the code.
ViewExpiredExceptionExceptionHandlerFactory
ViewExpiredExceptionExceptionHandler
faces-config.xml
Hope this might help someone else.
Thanks for al the help
I took the the solution from Ed Burns blog as base and fixed it with Oleg's response.
Here is the code.
ViewExpiredExceptionExceptionHandlerFactory
Code: Select all
public class ViewExpiredExceptionExceptionHandlerFactory extends ExceptionHandlerFactory {
private ExceptionHandlerFactory parent;
public ViewExpiredExceptionExceptionHandlerFactory(ExceptionHandlerFactory parent) {
this.parent = parent;
}
@Override
public ExceptionHandler getExceptionHandler() {
ExceptionHandler result = parent.getExceptionHandler();
result = new ViewExpiredExceptionExceptionHandler(result);
return result;
}
}
Code: Select all
public class ViewExpiredExceptionExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler wrapped;
public ViewExpiredExceptionExceptionHandler(ExceptionHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public ExceptionHandler getWrapped() {
return this.wrapped;
}
@Override
public void handle() throws FacesException {
String redirectPage = null;
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();
HttpSession session = (HttpSession) fc.getExternalContext().getSession(true);
try {
// Push some useful stuff to the request scope for use in the page
session.setAttribute("currentViewId", vee.getViewId());
System.out.println("currentViewId to put = " + vee.getViewId());
redirectPage = "/viewExpired.caw";
} finally {
i.remove();
}
doRedirect(fc, redirectPage);
}
}
// At this point, the queue will not contain any ViewExpiredEvents.
// Therefore, let the parent handle them.
getWrapped().handle();
}
public void doRedirect(FacesContext fc, String redirectPage) throws FacesException{
ExternalContext ec = fc.getExternalContext();
try {
// workaround for PrimeFaces
new RequestContextImpl(ec);
if (ec.getRequestParameterMap().containsKey(Constants.PARTIAL_PROCESS_PARAM)
&& !ec.getRequestParameterMap().get(Constants.PARTIAL_PROCESS_PARAM).equals("@all")) {
fc.setViewRoot(new PartialViewRoot(new UIViewRoot()));
}
// fix for renderer kit (Mojarra's and PrimeFaces's ajax redirect)
if ((RequestContext.getCurrentInstance().isAjaxRequest()
|| fc.getPartialViewContext().isPartialRequest())
&& fc.getResponseWriter() == null
&& fc.getRenderKit() == null) {
ServletResponse response = (ServletResponse) ec.getResponse();
ServletRequest request = (ServletRequest) ec.getRequest();
response.setCharacterEncoding(request.getCharacterEncoding());
RenderKitFactory factory =
(RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
RenderKit renderKit =
factory.getRenderKit(fc, fc.getApplication().getViewHandler().calculateRenderKitId(fc));
ResponseWriter responseWriter =
renderKit.createResponseWriter(response.getWriter(), null, request.getCharacterEncoding());
fc.setResponseWriter(responseWriter);
}
ec.redirect(ec.getRequestContextPath() + (redirectPage != null ? redirectPage : ""));
} catch (IOException e) {
System.out.println("Redirect to the specified page '" + redirectPage + "' failed");
throw new FacesException(e);
}
}
}
Code: Select all
<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<!-- NAVIGATION RULES -->
<!-- ViewExpiration Handler -->
<factory>
<exception-handler-factory>be.oac.caw.web.utils.ViewExpiredExceptionExceptionHandlerFactory</exception-handler-factory>
</factory>
</faces-config>
Thanks for al the help
-
- Prime
- Posts: 18616
- Joined: 05 Jan 2009, 00:21
- Location: Cybertron
- Contact:
Thanks for sharing your solution with other users Michiel.
- bumble.bee
- Posts: 723
- Joined: 29 Sep 2010, 21:39
- Location: United States
I'm not seeing any problems with the PrimeFaces AJAX redirect in PrimeFaces 2.2. I assume this issue was resolved and the workaround is no longer needed?
The workaround no longer would compile in its current form because the RequestContextImpl appears to have been replaced with DefaultRequestContext among other changes.
The workaround no longer would compile in its current form because the RequestContextImpl appears to have been replaced with DefaultRequestContext among other changes.
i have the same problem but using
jsf 1.2 (mojarra)
jboss seam 2.2
primefaces 1.2 snapshot
tomcat 6
i want to do a page-redirect after session timeout (@topic -> the observed error is: ViewExpiredException). so i installed a sessionlistener + sessiontimeoutfilter. next step is to send a redirect like:
to send the user to the default loginpage after timeout.
everything is triggered well and works, except i use ajax.
i got a <p:commandButton ...> for example. if it is triggered after sessiontimeout the code above is executed, but since the button got ajax support, there is no redirect made.
if i explicit say <p:commandButton ajax="false" ...> then the redirect works (but.. ajax would be nice to have )
in the filter i have no access to the FacesContext so i cant go the way described for jsf 2.0
i also can't use the <exception-handler-factory> (not available in jsf 1.2)
so... is there a way to use the benefits of ajax support + get propperly redirected using jsf 1.2?
(i found a "hack" here.. http://stackoverflow.com/questions/1990 ... -ajax-call but (still? i try to look into that deeper) don't know where to apply it )
thanks in advance
jsf 1.2 (mojarra)
jboss seam 2.2
primefaces 1.2 snapshot
tomcat 6
i want to do a page-redirect after session timeout (@topic -> the observed error is: ViewExpiredException). so i installed a sessionlistener + sessiontimeoutfilter. next step is to send a redirect like:
Code: Select all
...
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/home.seam");
...
everything is triggered well and works, except i use ajax.
i got a <p:commandButton ...> for example. if it is triggered after sessiontimeout the code above is executed, but since the button got ajax support, there is no redirect made.
if i explicit say <p:commandButton ajax="false" ...> then the redirect works (but.. ajax would be nice to have )
in the filter i have no access to the FacesContext so i cant go the way described for jsf 2.0
i also can't use the <exception-handler-factory> (not available in jsf 1.2)
so... is there a way to use the benefits of ajax support + get propperly redirected using jsf 1.2?
(i found a "hack" here.. http://stackoverflow.com/questions/1990 ... -ajax-call but (still? i try to look into that deeper) don't know where to apply it )
thanks in advance
-
- Information
-
Who is online
Users browsing this forum: No registered users and 63 guests