2010-06-05 7 views
8

Я разрабатываю приложение JSF 2.0 на Glassfish v3, и я пытаюсь обрабатывать ViewExpiredException. Но что бы я ни делал, я всегда получаю отчет об ошибке Glassfish вместо моей собственной страницы ошибок.JSF: Не удается поймать ViewExpiredException

Чтобы смоделировать возникновение VEE, я вставил следующую функцию в свой фоновый бэк, который запускает VEE. Я запускаю эту функцию с моей страницы JSF через commandLink. Кодекс:

@Named 
public class PersonHome { 
    (...) 
    public void throwVEE() { 
    throw new ViewExpiredException(); 
    } 
} 

Сначала я попробовал это, просто добавляя ошибки-страницу в моей web.xml:

<error-page> 
    <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
    <location>/error.xhtml</location> 
</error-page> 

Но это не работает, я не перенаправляются ошибки но я показал errorpage GlassFish, которая показывает HTTP Status 500 страницу со следующим содержанием:

description:The server encountered an internal error() that prevented it from fulfilling this request. 
exception: javax.servlet.ServletException: javax.faces.application.ViewExpiredException 
root cause: javax.faces.el.EvaluationException:javax.faces.application.ViewExpiredException 
root cause:javax.faces.application.ViewExpiredException 

Следующая вещь, которую я попытался было написать ExceptionHandlerFactory и CustomExceptionHandler, а дез cribed in JavaServerFaces 2.0 - Полное справочное руководство. Таким образом, я вставил следующий тег в лица-config.xml:

<factory> 
    <exception-handler-factory> 
    exceptions.ExceptionHandlerFactory 
    </exception-handler-factory> 
</factory> 

И добавили эти классы: Фабрика:

package exceptions; 

import javax.faces.context.ExceptionHandler; 

public class ExceptionHandlerFactory extends javax.faces.context.ExceptionHandlerFactory { 

    private javax.faces.context.ExceptionHandlerFactory parent; 

    public ExceptionHandlerFactory(javax.faces.context.ExceptionHandlerFactory parent) { 
     this.parent = parent; 
    } 

    @Override 
    public ExceptionHandler getExceptionHandler() { 
     ExceptionHandler result = parent.getExceptionHandler(); 
     result = new CustomExceptionHandler(result); 
     return result; 
    } 

} 

Обработчик пользовательских исключений:

package exceptions; 

import java.util.Iterator; 

import javax.faces.FacesException; 
import javax.faces.application.NavigationHandler; 
import javax.faces.application.ViewExpiredException; 
import javax.faces.context.ExceptionHandler; 
import javax.faces.context.ExceptionHandlerWrapper; 
import javax.faces.context.FacesContext; 
import javax.faces.event.ExceptionQueuedEvent; 
import javax.faces.event.ExceptionQueuedEventContext; 

class CustomExceptionHandler extends ExceptionHandlerWrapper { 

    private ExceptionHandler parent; 

    public CustomExceptionHandler(ExceptionHandler parent) { 
     this.parent = parent; 
    } 

    @Override 
    public ExceptionHandler getWrapped() { 
     return this.parent; 
    } 

    @Override 
    public void handle() throws FacesException { 
     for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) { 
      ExceptionQueuedEvent event = i.next(); 
      System.out.println("Iterating over ExceptionQueuedEvents. Current:" + event.toString()); 
      ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource(); 
      Throwable t = context.getException(); 
      if (t instanceof ViewExpiredException) { 
       ViewExpiredException vee = (ViewExpiredException) t; 
       FacesContext fc = FacesContext.getCurrentInstance(); 

       NavigationHandler nav = 
         fc.getApplication().getNavigationHandler(); 
       try { 
        // Push some useful stuff to the flash scope for 
        // use in the page 
        fc.getExternalContext().getFlash().put("expiredViewId", vee.getViewId()); 

        nav.handleNavigation(fc, null, "/login?faces-redirect=true"); 
        fc.renderResponse(); 

       } finally { 
        i.remove(); 
       } 
      } 
     } 
     // At this point, the queue will not contain any ViewExpiredEvents. 
     // Therefore, let the parent handle them. 
     getWrapped().handle(); 
    } 
} 

Но все-таки Я НЕ перенаправлен на страницу с ошибкой - я получаю такую ​​же ошибку HTTP 500, как и выше. Что я делаю неправильно, что может отсутствовать в моей реализации, что исключение обрабатывается неправильно? Любые помощь очень ценится!

EDIT

Хорошо, я честен. Фактически, мой код фактически написан в Scala, но это длинная история. Я думал, что это проблема Java все время. РЕАЛЬНАЯ ошибка в этом случае была моей собственной глупостью. В моем (Scala) коде, в CustomExceptionHandler, я забыл добавить строку с «i.remove();» Таким образом, представление ViewExpiredException оставалось в UnhandledExceptionsQueue после его обработки, и оно «закручивалось». И когда он пузырится вверх, он становится исключением ServletException.

Мне очень жаль, что вы сбиваете с толку вас обоих!

+0

* «Таким образом, вы можете бросить ViewExpiredException в ЛЮБОМ JSF-фазы» *: по умолчанию, когда вы делаете это внутри боба, как в вашем примере 1, это будет вставлено в 'FacesException' и он будет не заканчивается на ожидаемой странице ошибки. – BalusC

+0

Спасибо. Вы правы, я удалил инструкцию any-jsf-phase из моего последнего редактирования. – ifischer

+0

Ваш последний отредактированный пост заставляет его работать? Мне нужно установить ту же переадресацию на ViewExpired error, а также –

ответ

14

Этот чехол является фиктивным.ViewExpiredException обычно вызывается только при восстановлении представления (потому что в сеансе отсутствует), а не при рендеринге ответа или создании экземпляра компонента. В вашем случае это исключение возникает при создании экземпляра компонента, и это исключение обернуто в ServletException.

действительныйViewExpiredException обычно выдается только при отправке HTTP-запроса POST на сервер, в то время как время HTTP-сессии истекло. Таким образом, есть два основных способа воспроизвести это надежно:

  1. открыть JSF страницу с формой POST (h:form по умолчанию уже POST) в WebBrowser, выключит сервер и очистить свой рабочий каталог (важно, потому что большинство серверов будут сериализовать открытые сеансы на диске при выключении и unserialize их при запуске), перезапустить сервер и отправить уже открытую форму. A ViewExpiredException будет выброшен.

  2. Установите <session-timeout> в web.xml на 1 минуту и ​​отправить форму через 1 минуту после открытия страницы JSF с формой POST. Это также выкинет ViewExpiredException.

+0

Спасибо BalusC. Но почему это неправильно перенаправлено на страницу с ошибкой? – gekrish

+2

Потому что выбрано 'ServletException'. – BalusC

2

Я не эксперт. Это просто дикие догадки или предложения.

1) Попробуйте перенаправление стандартного HTML страницы, чтобы увидеть, если это работает 2) Based on this, он должен работать с самим первым подходом, попробуйте писать JSF PhaseListener и бросить то же самое исключение в RESTORE VIEW Phase.Right Теперь , вы бросаете либо в фазу INVOKE APPLICATION или UPDATE MODEL. 3) С помощью sysout убедитесь, что страница с ошибкой настроена - с использованием контекста сервлета (я не пробовал это, но это должно быть возможно)

Даже мне любопытно, в чем может быть проблема !!!

+0

спасибо за ваши мысли! Раньше я никогда не использовал PhaseListeners, хорошо знал их. Я только что реализовал один, который выдает исключение в фазе RESTORE_VIEW - и теперь он действительно перенаправляет правильно! Мое исключение выбрано на этапе InvokeApplication. Интересно, почему исключения, выброшенные на этой фазе, не пойманы правильно? – ifischer

+0

Хмм, это не фаза, почему это не сработало, я также получаю статус-500, когда я бросаю исключение в фазу RESTORE_VIEW (один раз, когда он работал, но не больше). Необходимо продолжить исследование ... – ifischer

Смежные вопросы