Страница ошибки 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, но я не перенаправляюсь на свой index. Почему это ?

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

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

UserController имеет ViewScoped


person Mr_and_Mrs_D    schedule 15.02.2014    source источник
comment
Вы пробовали без faces-redirect=true?   -  person Petr Mensik    schedule 15.02.2014
comment
@PetrMensik: без разницы, подтверждено   -  person Mr_and_Mrs_D    schedule 16.02.2014
comment
Используете ли вы какой-либо компонентный фреймворк, например IceFaces? Потому что обычно эта ошибка отображается как содержимое на странице ошибок сервера приложений, а не через javascript.   -  person unwichtich    schedule 17.02.2014
comment
@unwichtich: стеклянная рыба4   -  person Mr_and_Mrs_D    schedule 17.02.2014


Ответы (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 в запросе JSF/PrimeFaces ajax< /а>

person mabi    schedule 18.02.2014
comment
Ага - да, у меня есть javax.faces.PROJECT_STAGE - я рассмотрю ваш ответ, когда буду на моей машине разработки. Спасибо ! Что такое объект jsf.ajax? - person Mr_and_Mrs_D; 18.02.2014
comment
@Mr_and_Mrs_D это объект javascript, который содержит функции, связанные с ajax, в вашей реализации JSF. Таким образом, вы добавляете обработчик ошибок, вызывая jsf.ajax.addOnError(function() { /* your stuff */ }); - person mabi; 18.02.2014
comment
Я реализовал и зарегистрировал обработчик исключений - person Mr_and_Mrs_D; 21.02.2014

Попробуйте этот подход для обработки срока действия представления: создайте следующие 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();
    }
}

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

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

И все, вы готовы идти.

ИЗМЕНИТЬ

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

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

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

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

person Alex Dutescu    schedule 17.02.2014
comment
Плагиат здесь не приветствуется. Пожалуйста, укажите источник, откуда вы сорвали этот код. Также было бы уважительно, если бы вы могли объяснить простым языком, как именно все это решает конкретную проблему ОП. Прямо сейчас это действительно не более чем невежественный BAM, вот некоторый код для копирования. Попробуйте, возможно, это решит проблему! - person BalusC; 17.02.2014
comment
Код взят из одного из моих существующих проектов. Если я хорошо помню, когда я впервые начал изучать jsf, в какой-то момент я попытался интегрировать Spring с Spring Roo. Сгенерированный проект имел такой подход для разрешения просроченных представлений, и с тех пор я использую его без проблем. - person Alex Dutescu; 17.02.2014
comment
@AlexDutescu: простите, омнифейсы? - person Mr_and_Mrs_D; 18.02.2014
comment
@Mr_and_Mrs_D Я не собираюсь сейчас рассказывать вам, что такое омнифейс, я дал вам ссылку на это. Я не знаю, почему ваш код не работает, только из предоставленной вами информации, поэтому я дал вам 2 альтернативы, которые помогут вам решить проблему. Это все, что я могу сделать, может быть, кто-то другой ответит лучше. - person Alex Dutescu; 18.02.2014
comment
@AlexDutescu: когда я сказал, извините, омнифейсы? Я имел в виду когда я упоминал омнифейсы в вопросе, а не что такое омнифейсы. Перечитайте первый комментарий в этом ответе. Я не хочу, чтобы это работало - я хочу получить ответ на свой вопрос. Я могу заставить это работать - программирование не в том, чтобы заставить это работать, а в том, чтобы заставить это работать правильно. Программисты, которые заставили его работать, заполнили мир наполовину сломанными программами. надеюсь ты не из их числа - person Mr_and_Mrs_D; 18.02.2014