Страница ошибки ViewExpiredException не отображается

Я оставляю некоторые вкладки открытыми с формами, и когда я нажимаю кнопки команд (через некоторое время, когда сеанс заканчивается), я получаю предупреждение java-скрипта, говорящее:

serverError: класс javax.faces.application.ViewExpiredException viewId: /register.xhtml - представление /register.xhtml не может быть восстановлено.

На Firefox (Glassfish 4 локально)

Я добавил:

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/index.xhtml?faces-redirect=true</location>
</error-page>

в моем web.xml но я не перенаправлен на мой индекс. Это почему?

Изменить: образец кнопки

<h:commandButton value="Register" action="#{userController.register}">
    <f:ajax execute="@form" render="@form" />
</h:commandButton>

UserController является ViewScoped

2 ответа

Решение

Это ожидаемое поведение, если вы посмотрите на разделы 13.3.6.3 и 13.3.6.4 спецификации JSF-2.2, по крайней мере, если у вас есть

<context-param>
  <param-name>javax.faces.PROJECT_STAGE</param-name>
  <param-value>Development</param-value>
</context-param>

в вашем web.xml (он молча игнорирует ошибку в производственном режиме). Код JSF на стороне клиента отправляет запрос AJAX при нажатии этой кнопки и получает

<error>
    <error-name>...</error-name>
    <error-message>...</error-message>
</error>

с вашим ViewExpiredException в ответ. Ожидается, что клиентский код будет реагировать на эту информацию об ошибке. Зарегистрировать функцию с onerror (на f:ajax тег) или addOnError (на jsf.ajax объект), чтобы справиться с ошибкой самостоятельно.

Поскольку многие люди ожидают, что сервер направит клиента на такую ​​проблему, omnifaces включает в себя FullAjaxExceptionHandler, который в основном сбрасывает ваш ответ и отправляет указанную вами страницу ошибки.

Смотрите также:

Тайм-аут сеанса и обработка ViewExpiredException при запросе JJF/PrimeFaces ajax

Попробуйте этот подход для обработки истечения срока действия представления: создайте следующие 2 класса в своем проекте

import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerFactory;

public class ViewExpiredExceptionExceptionHandlerFactory extends
        ExceptionHandlerFactory {

    private ExceptionHandlerFactory parent;

    public ViewExpiredExceptionExceptionHandlerFactory(
            ExceptionHandlerFactory parent) {
        this.parent = parent;
    }

    @Override
    public ExceptionHandler getExceptionHandler() {
        return new ViewExpiredExceptionExceptionHandler(
            parent.getExceptionHandler());
    }
}

а также

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 {
        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 facesContext = FacesContext.getCurrentInstance();
                Map<String, Object> requestMap = facesContext
                    .getExternalContext().getRequestMap();
                NavigationHandler navigationHandler = facesContext
                    .getApplication().getNavigationHandler();
                try {
                    // Push some useful stuff to the request scope for use in
                    // the page
                    requestMap.put("currentViewId", vee.getViewId());
                    navigationHandler.handleNavigation(facesContext, null,
                        "/index");
                    facesContext.renderResponse();
                } finally {
                    i.remove();
                }
            }
        }
        // At this point, the queue will not contain any ViewExpiredEvents.
        // Therefore, let the parent handle them.
        getWrapped().handle();
    }
}

В Face-config.xml добавить следующие строки:

<factory>
    <exception-handler-factory>path.to.class.ViewExpiredExceptionExceptionHandlerFactory</exception-handler-factory>

И все, ты идешь в путь.

РЕДАКТИРОВАТЬ

Хорошо, я забыл о способе Omnifaces сделать это, я не использую это, потому что, как только вы установите страницу для ошибки, она предупреждает вас сделать страницы для 404 и еще один, который я сейчас не помню. Вы должны добавить в ваши лица-config.xml следующее:

<factory>
<exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>

и ваш код будет работать. Для получения дополнительной информации см. Демонстрацию FullAjaxExceptionHandlerFactory с веб-сайта omnifaces http://showcase.omnifaces.org/exceptionhandlers/FullAjaxExceptionHandler;jsessionid=sOwX0FVqcY-InUhvDWEMksfQ.

Не забудьте добавить в свой проект необходимую банку.

Другие вопросы по тегам