javax.las caras.aplicación.ViewExpiredException: la Vista no podía ser restaurado

He escrito sencilla aplicación con gestionada por contenedor de seguridad. El problema es cuando inicio sesión y abrir otra página en la que yo cierre de sesión, luego vuelvo a la primera página y hago clic en cualquier enlace, etc o actualizar la página puedo conseguir esta excepción. Supongo que es normal (o tal vez no:)) porque la sesión y sesión se destruye. ¿Qué debo hacer para redirigir el usuario a, por ejemplo, del índice.xhtml o de inicio de sesión.xhtml y salvarlo de ver que la página de error/mensaje?

En otras palabras ¿cómo puedo redirigir automáticamente a otras páginas de índice/página de inicio de sesión después de salir?

Aquí es:

javax.faces.application.ViewExpiredException: viewId:/index.xhtml - View /index.xhtml could not be restored.
    at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:212)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:110)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
    at filter.HttpHttpsFilter.doFilter(HttpHttpsFilter.java:66)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
    at java.lang.Thread.run(Thread.java:619)

OriginalEl autor l245c4l | 2010-09-04

10 Kommentare

  1. 315

    Introducción

    La ViewExpiredException será lanzado cada vez que el javax.faces.STATE_SAVING_METHOD se establece en server (predeterminado) y el usuario final envía una solicitud HTTP POST en una vista a través de <h:form> con <h:commandLink>, <h:commandButton> o <f:ajax>, mientras que los asociados del estado de la vista no está disponible en la sesión más.

    El estado de vista se identifica como el valor de una oculta campo de entrada javax.faces.ViewState de la <h:form>. Con el estado de ahorro de método establecido para server, este contiene sólo el punto de vista de IDENTIFICACIÓN del estado, que hace referencia a un serializado estado de vista en la sesión. Así, cuando la sesión ha caducado, por alguna razón (ya sea programada en el servidor o en el lado del cliente, o la cookie de sesión no se mantiene ya por alguna razón en el navegador, o llamando HttpSession#invalidate() en el servidor, o a causa de un servidor de error específico con las cookies de sesión como se conoce en WildFly), entonces el serializada del estado de la vista, ya no está disponible en la sesión y el usuario final recibirá esta excepción. Para entender el trabajo de la sesión, consulte también ¿Cómo servlets trabajo? La creación de instancias, las sesiones, las variables compartidas y multithreading.

    También existe un límite en la cantidad de puntos de vista JSF va a almacenar en la sesión. Cuando el límite es alcanzado, el menos usado recientemente vista se dará por vencido. Véase también com.sol.las caras.numberOfViewsInSession vs com.sol.las caras.numberOfLogicalViews.

    Con el estado de ahorro de método establecido para client, el javax.faces.ViewState oculto campo de entrada contiene en lugar de toda serializada del estado de la vista, por lo que el usuario final no tendrá una ViewExpiredException cuando caduca la sesión. No obstante, puede suceder en un entorno de clúster («ERROR: MAC no verificar» es sintomático) y/o cuando hay una aplicación específica de tiempo de espera en el lado del cliente estado configurado y/o cuando el servidor re-genera la clave AES durante el reinicio, ver también Llegar ViewExpiredException en el entorno de clúster, mientras que el estado de ahorro de método está definido del cliente y del usuario de la sesión es válida cómo resolverlo.

    Independientemente de la solución, asegúrese de que usted haga no uso enableRestoreView11Compatibility. no en todos restaurar el original del estado de la vista. Básicamente se recrea la vista y todos los asociados de vista del ámbito de frijoles desde cero y por medio de la presente perdiendo así todos los datos originales (estado). Como la aplicación se comporte de una manera confusa («Hey, ¿dónde están mis valores de entrada..??»), esto es muy malo para la experiencia del usuario. Mejor uso de los apátridas vistas o <o:enableRestorableView> lugar, de modo que usted puede administrar en una vista específica sólo que en lugar de en todas las vistas.

    Como a la por qué JSF necesita para salvar a la vista del estado, de la cabeza a esta respuesta: Por qué JSF guarda el estado de los componentes de interfaz de usuario en el servidor?

    Evitar ViewExpiredException en la página de navegación

    Con el fin de evitar ViewExpiredException cuando, por ejemplo, navegar de vuelta después de cerrar la sesión cuando el estado de ahorro se establece en server, sólo redirigir la petición POST después de cerrar la sesión no es suficiente. También es necesario indicar al navegador para no caché de la dinámica de páginas JSF, de lo contrario el navegador puede mostrar de la caché en lugar de solicitar uno nuevo desde el servidor al enviar una solicitud GET (por ejemplo, mediante el botón «atrás»).

    La javax.faces.ViewState campo oculto de la página en caché puede contener un estado de vista de IDENTIFICACIÓN de valor que ya no es válido en el actual período de sesiones. Si eres (ab)uso de POST (comando de enlaces/botones) en lugar de OBTENER (regular enlaces/botones) de la página a la navegación de la página y haga clic en un comando de enlace/botón en la página almacenada en caché, entonces esta en su error con un ViewExpiredException.

    A fuego una redirección después de cerrar la sesión en JSF 2.0, agregar <redirect /> a la <navigation-case> en cuestión (si lo hubiere), o añadir ?faces-redirect=true a la outcome valor.

    <h:commandButton value="Logout" action="logout?faces-redirect=true" />

    o

    public String logout() {
        //...
        return "index?faces-redirect=true";
    }

    Para indicar al navegador para no almacenar en caché la dinámica de páginas JSF, crear un Filter que se asigna en el servlet nombre de la FacesServlet y añade la necesaria encabezados de respuesta para deshabilitar la caché del navegador. E. g.

    @WebFilter(servletNames={"Faces Servlet"}) //Must match <servlet-name> of your FacesServlet.
    public class NoCacheFilter implements Filter {
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse res = (HttpServletResponse) response;
    
            if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { //Skip JSF resources (CSS/JS/Images/etc)
                res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); //HTTP 1.1.
                res.setHeader("Pragma", "no-cache"); //HTTP 1.0.
                res.setDateHeader("Expires", 0); //Proxies.
            }
    
            chain.doFilter(request, response);
        }
    
        //...
    }

    Evitar ViewExpiredException en la página de actualización de

    Con el fin de evitar ViewExpiredException al refrescar la página actual cuando el estado de ahorro se establece en server, no sólo se necesita para asegurarse de que usted está realizando la página a la página de navegación exclusivamente por GET (regular enlaces/botones), pero usted también necesita asegurarse de que usted es exclusivamente el uso de ajax para enviar los formularios. Si vas a enviar el formulario de forma sincrónica (no-ajax) de todos modos, entonces sería mejor hacer la vista apátridas (consulte la sección posterior), o para enviar una redirección después de la POST (ver sección anterior).

    Tener un ViewExpiredException en la actualización de la página es en la configuración predeterminada de un caso muy raro. No sólo puede ocurrir cuando el límite en la cantidad de puntos de vista JSF va a almacenar en la sesión de golpe. Así, sólo será posible cuando haya manualmente establece que el límite demasiado bajo, o que está continuamente creando nuevos puntos de vista en el fondo (por ejemplo, por un mal aplicadas encuesta). Véase también com.sol.las caras.numberOfViewsInSession vs com.sol.las caras.numberOfLogicalViews. Otra causa es tener duplicados JSF las bibliotecas en tiempo de ejecución classpath en conflicto el uno al otro. El procedimiento correcto para instalar JSF se describe en nuestro JSF página de la wiki.

    Manejo ViewExpiredException

    Cuando se desea controlar un inevitable ViewExpiredException después de la acción en cualquier página que ya estaba abierto en algunos navegador pestaña/ventana mientras estás conectado a cabo en otra pestaña/ventana, a continuación, desea especificar un error-page para que en web.xml que va a un «Tu sesión está agotado» de la página. E. g.

    <error-page>
        <exception-type>javax.faces.application.ViewExpiredException</exception-type>
        <location>/WEB-INF/errorpages/expired.xhtml</location>
    </error-page>

    Utilizar si es necesario un meta refresh encabezado en la página de error en caso de que usted tiene la intención de realmente redirigir más a home o página de inicio de sesión.

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <title>Session expired</title>
            <meta http-equiv="refresh" content="0;url=#{request.contextPath}/login.xhtml" />
        </head>
        <body>
            <h1>Session expired</h1>
            <h3>You will be redirected to login page</h3>
            <p><a href="#{request.contextPath}/login.xhtml">Click here if redirect didn't work or when you're impatient</a>.</p>
        </body>
    </html>

    (el 0 en content representa la cantidad de segundos antes de redirigir, 0 significa, por tanto, de redireccionamiento «de inmediato», puede usarse, por ejemplo, 3 para que el navegador espera 3 segundos con la redirección)

    Tenga en cuenta que el manejo de excepciones, durante peticiones ajax requiere de una especial ExceptionHandler. Véase también Tiempo de espera de sesión y ViewExpiredException manejo en JSF/PrimeFaces petición ajax. Usted puede encontrar un ejemplo en vivo en OmniFaces FullAjaxExceptionHandler página showcase (esto abarca también los no-peticiones ajax).

    También tenga en cuenta que su «general» de la página de error debe ser asignado en <error-code> de 500 en lugar de un <exception-type> de, por ejemplo, java.lang.Exception o java.lang.Throwable, de lo contrario, todas las excepciones envuelto en ServletException como ViewExpiredException iba a terminar en la general de la página de error. Véase también ViewExpiredException se muestra en java.lang.Arrojar errores en la página web.xml.

    <error-page>
        <error-code>500</error-code>
        <location>/WEB-INF/errorpages/general.xhtml</location>
    </error-page>

    Apátridas vistas

    Una completamente diferente alternativa es ejecutar JSF vistas en modo apátrida. De esta manera nada de JSF estado serán salvos y los puntos de vista no caduca, pero sólo para ser reconstruido a partir de cero en cada solicitud. Usted puede convertirse en apátridas vistas por la configuración de la transient atributo de <f:view> a true:

    <f:view transient="true">
    
    </f:view>

    De esta manera el javax.faces.ViewState campo oculto obtendrá un valor fijo de "stateless" en Mojarra (lo he comprobado MyFaces en este punto). Tenga en cuenta que esta característica se introducido en Mojarra 2.1.19 y 2.2.0 y no está disponible en las versiones anteriores.

    La consecuencia es que no se puede utilizar la vista ámbito de granos de más. Ahora se comportan como un ámbito de petición de frijoles. Una de las desventajas es que usted tiene que rastrear el estado a sí mismo por juguetear con ocultos de los insumos y/o sueltos los parámetros de solicitud. Principalmente los formularios con campos de entrada con rendered, readonly o disabled atributos, los cuales son controlados por ajax eventos serán afectados.

    Tenga en cuenta que el <f:view> no necesariamente tiene que ser único en la vista y/o residir en la plantilla maestra única. Además es completamente de fiar para volver a declarar y anidar en una plantilla de cliente. Básicamente se «extiende» el padre <f:view> entonces. E. g. en la plantilla maestra:

    <f:view contentType="text/html">
        <ui:insert name="content" />
    </f:view>

    y en plantilla de cliente:

    <ui:define name="content">
        <f:view transient="true">
            <h:form>...</h:form>
        </f:view>
    </f:view>

    Incluso puede envolver el <f:view> en un <c:if> hacer es condicional. Tenga en cuenta que se aplicaría en el toda la vista, no sólo en el anidado de contenidos, tales como el <h:form> en el ejemplo anterior.

    Ver también


    No relacionados para el problema concreto, mediante HTTP POST para puro de la página a la página de navegación no es muy user/SEO friendly. En JSF 2.0 que realmente debería preferir <h:link> o <h:button> sobre el <h:commandXxx> para plain vanilla página a la página de navegación.

    Así que en lugar de, por ejemplo,

    <h:form id="menu">
        <h:commandLink value="Foo" action="foo?faces-redirect=true" />
        <h:commandLink value="Bar" action="bar?faces-redirect=true" />
        <h:commandLink value="Baz" action="baz?faces-redirect=true" />
    </h:form>

    mejor hacer

    <h:link value="Foo" outcome="foo" />
    <h:link value="Bar" outcome="bar" />
    <h:link value="Baz" outcome="baz" />

    Véase también

    ¿Cómo puedo hacerlo con el implícito de navegación en java ee 6? Yo no uso la faces-config.
    Oh, estás usando JSF 2.0? Usted debe tener mencionó que en tu pregunta! Agregar ?faces-redirect=true a la outcome. He actualizado la respuesta en consecuencia.
    Sí, acabo de empezar con java ee:) y estoy usando caras-redirect=true en todos mis navegaciones. Yo use h:commandLink sólo cuando tengo acciones assosciated con ella. Por ejemplo el enlace de Desconexión… he Cadena de acción logout() donde puedo invalidar la sesión y redirigir a la de inicio de sesión, pero no funciona en la página de donde yo estaba conectado y estar en el momento de la sesión y lanza con excepción de 🙁
    Gracias de nuevo y lo siento por eso:) pero al menos conseguí rápido y la respuesta profesional en ningún momento :p
    El filtro es, sin embargo, aún obligatorio para el caso cuando uno presiona el botón atrás después de expirado el POST e intenta llamar a otra solicitud POST. Esto sería lo contrario unintuitively resultado en esta excepción.

    OriginalEl autor BalusC

  2. 51

    Has intentado añadir las líneas siguientes para su web.xml?

    <context-param>
       <param-name>com.sun.faces.enableRestoreView11Compatibility</param-name>
       <param-value>true</param-value>
    </context-param>

    He encontrado esto para ser muy eficaz cuando me encontré con este problema.

    a mí me funcionó demasiado. Gracias por la respuesta. ¿Cuál es el propósito de esto?
    No recuerdo exactamente, pero he encontrado esta solución en ICEFaces sitio web.
    yo puede que sea un poco tarde a la fiesta, pero esto funcionó para mí. gracias!
    Es esta definido solo para JSF 1.2 o JSF 2 también?
    Esto va a dejar de lanzar la excepción cuando la vista está caducado y simplemente continuar con la petición, pero JSF todavía no será capaz de restaurar el estado de vista ni encontrar cualquier vista asociada ámbito de frijoles. Esta transacción se comportan como apátridas JSF y tienes que restaurar el estado de vista a sí mismo basado en el POST de solicitud de parámetros para evitar «wtf?» experiencia de usuario final cuando el procesamiento de la forma de presentar respondió inesperadamente. Si desea aplicar este en específico JSF páginas solamente, entonces en lugar de usar OmniFaces <o:enableRestorableView> en lugar de una aplicación amplia parámetro de contexto.

    OriginalEl autor Mike GH

  3. 5

    Primero lo que tienes que hacer, antes de cambiar de web.xml es para asegurarse de que su ManagedBean implements Serializable:

    @ManagedBean
    @ViewScoped
    public class Login implements Serializable {
    }

    Especialmente si usted usa MyFaces

    OriginalEl autor ZuzEL

  4. 3

    Evitar de varias formas en Richfaces:

    <h:form enctype="multipart/form-data">
        <a4j:poll id="poll" interval="10000"/>
    </h:form>

    Si usted está usando Richfaces, he encontrado que las peticiones ajax en el interior de varias formas de volver de un nuevo punto de Vista de IDENTIFICACIÓN en cada solicitud.

    Cómo depurar:

    En cada petición ajax en una Vista de ID se devuelve, que está bien siempre y cuando el punto de Vista de IDENTIFICACIÓN es siempre la misma. Si usted consigue un nuevo punto de Vista de IDENTIFICACIÓN en cada petición, entonces hay un problema y debe ser corregido.

    OriginalEl autor tak3shi

  5. 0

    Que coud utilizar su propio personalizado AjaxExceptionHandler o primefaces-extensiones de

    Actualización de su faces-config.xml

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

    Agregar el siguiente código en su página jsf

    ...
    <pe:ajaxErrorHandler />
    ...

    OriginalEl autor myset

  6. 0

    Estaba recibiendo este error : javax.las caras.aplicación.ViewExpiredException.Cuando yo utilizando diferentes peticiones, me encontré con aquellos que tienen la misma JsessionId, incluso después de reiniciar el servidor.
    Así que esto es debido a la caché del navegador. Cierre el navegador y vuelva, va a trabajar.

    Esto ya está cubierto por el actual superior de la respuesta.

    OriginalEl autor rahul

  7. 0

    Cuando nuestra página está inactivo durante x cantidad de tiempo de la vista de caducará y tirar javax.las caras.aplicación.ViewExpiredException para evitar que esto suceda
    una solución es crear CustomViewHandler que se extiende ViewHandler
    y reemplazar restoreView método de todos los otros métodos son los que se delega el Padre

    import java.io.IOException;
    import javax.faces.FacesException;
    import javax.faces.application.ViewHandler;
    import javax.faces.component.UIViewRoot;
    import javax.faces.context.FacesContext;
    import javax.servlet.http.HttpServletRequest;
    
    public class CustomViewHandler extends ViewHandler {
        private ViewHandler parent;
    
        public CustomViewHandler(ViewHandler parent) {
            //System.out.println("CustomViewHandler.CustomViewHandler():Parent View Handler:"+parent.getClass());
            this.parent = parent;
        }
    
        @Override 
        public UIViewRoot restoreView(FacesContext facesContext, String viewId) {
        /**
         * {@link javax.faces.application.ViewExpiredException}. This happens only  when we try to logout from timed out pages.
         */
            UIViewRoot root = null;
            root = parent.restoreView(facesContext, viewId);
            if(root == null) {
                root = createView(facesContext, viewId);
            }
            return root;
        }
    
        @Override
        public Locale calculateLocale(FacesContext facesContext) {
            return parent.calculateLocale(facesContext);
        }
    
        @Override
        public String calculateRenderKitId(FacesContext facesContext) {
            String renderKitId = parent.calculateRenderKitId(facesContext);
            //System.out.println("CustomViewHandler.calculateRenderKitId():RenderKitId: "+renderKitId);
            return renderKitId;
        }
    
        @Override
        public UIViewRoot createView(FacesContext facesContext, String viewId) {
            return parent.createView(facesContext, viewId);
        }
    
        @Override
        public String getActionURL(FacesContext facesContext, String actionId) {
            return parent.getActionURL(facesContext, actionId);
        }
    
        @Override
        public String getResourceURL(FacesContext facesContext, String resId) {
            return parent.getResourceURL(facesContext, resId);
        }
    
        @Override
        public void renderView(FacesContext facesContext, UIViewRoot viewId) throws IOException, FacesException {
            parent.renderView(facesContext, viewId);
        }
    
        @Override
        public void writeState(FacesContext facesContext) throws IOException {
            parent.writeState(facesContext);
        }
    
        public ViewHandler getParent() {
            return parent;
        }
    
    }   

    Entonces usted necesita para agregar a su faces-config.xml

    <application>
        <view-handler>com.demo.CustomViewHandler</view-handler>
    </application>

    Gracias por la respuesta original en el enlace de abajo:
    http://www.gregbugaj.com/?p=164

    Este enfoque no recupera la vista ámbito de frijoles.

    OriginalEl autor user4924157

  8. -2

    Por favor agregue esta línea en su web.xml
    A mí me funciona

    <context-param>
            <param-name>org.ajax4jsf.handleViewExpiredOnClient</param-name> 
            <param-value>true</param-value>     
        </context-param>
    Su respuesta será más útil si se incluye la explicación y contexto sobre lo que está haciendo el código.
    Incluso si esta es la correcta respuesta de StackOverflow desalienta respuestas como esta, sin una explicación. Sería de gran ayuda a la comunidad para agregar más información acerca de por qué funciona.

    OriginalEl autor harshal

  9. -2

    Me encontré con este problema de mi y me di cuenta de que era debido a un efecto secundario de un Filtro que he creado que fue el filtrado de todas las solicitudes en el appliation. Tan pronto como he modificado el filtro para recoger sólo ciertas solicitudes, este problema no se produce. Tal vez sea bueno para comprobar dichos filtros en la aplicación y ver cómo se comportan.

    OriginalEl autor javshak

  10. -3

    Puedo agregar la siguiente configuración para web.xml y lo tengo resuelto.

    <context-param>
        <param-name>com.sun.faces.numberOfViewsInSession</param-name>
        <param-value>500</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.numberOfLogicalViews</param-name>
        <param-value>500</param-value>
    </context-param>
    Terrible consejo. Sólo hacer esto cuando usted tiene un montón de memoria y sus usuarios finales realmente siempre han de hasta 500 pestañas del navegador abiertas y pulse botón atrás del navegador hasta 500 veces anteriores sincrónica de las devoluciones de datos.

    OriginalEl autor Mohamed Ali

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea