# Sessiontimeout Exception bei Weiterleitung



## DerEwigeGaast (17. Nov 2012)

Hallo,

ich habe Folgendes in meiner web.xml definiert:
[XML]<error-page>
        <exception-type>javax.faces.application.ViewExpiredException</exception-type>
        <location>/public/sessiontimeout.xhtml</location>
    </error-page>[/XML]
Den Pfad zu sessiontimeout.xhtml habe ich schon geprüft
Wenn jetzt nach einer Minute (auch in der web.xml definiert) die Session abläuft, sollte bei der nächsten Interaktion eigentlich der Benutzer (dieser muss sich vorher angemeldet haben) zur jenen sessiontimeout.xhtml weitergeleitet werden. Allerdings fliegt auf meinem Glassfish folgende Exception:

```
WARNING: ApplicationDispatcher[/Zulassung] PWC1231: Servlet.service() for servlet Faces Servlet threw exception
javax.faces.application.ViewExpiredException: viewId:/public/login.xhtml - Ansicht /public/login.xhtml konnte nicht wiederhergestellt werden.
	at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:205)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:116)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
	at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
	at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:809)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:671)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:505)
	at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:476)
	at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:355)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:305)
	at org.apache.catalina.authenticator.FormAuthenticator.forwardToLoginPage(FormAuthenticator.java:464)
	at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:253)
	at com.sun.web.security.RealmAdapter.invokeAuthenticateDelegate(RealmAdapter.java:1333)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:551)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:623)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
	at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
	at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
	at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
	at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
	at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
	at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
	at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
	at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
	at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
	at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
	at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
	at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
	at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
	at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
	at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
	at java.lang.Thread.run(Thread.java:722)

WARNING: Unexpected error forwarding or redirecting to login page
javax.servlet.ServletException: viewId:/public/login.xhtml - Ansicht /public/login.xhtml konnte nicht wiederhergestellt werden.
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:606)
	at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
	at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:809)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:671)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:505)
	at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:476)
	at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:355)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:305)
	at org.apache.catalina.authenticator.FormAuthenticator.forwardToLoginPage(FormAuthenticator.java:464)
	at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:253)
	at com.sun.web.security.RealmAdapter.invokeAuthenticateDelegate(RealmAdapter.java:1333)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:551)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:623)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
	at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
	at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
	at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
	at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
	at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
	at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
	at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
	at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
	at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
	at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
	at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
	at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
	at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
	at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
	at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
	at java.lang.Thread.run(Thread.java:722)
Caused by: javax.faces.application.ViewExpiredException: viewId:/public/login.xhtml - Ansicht /public/login.xhtml konnte nicht wiederhergestellt werden.
	at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:205)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:116)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
	... 32 more
```

Die Fehlermeldung besagt also, dass der Server versucht, einen Redirect auf die login.xhtml (Pfad stimmt auch) durchzuführen. Ist das ein normales Verhalten (Redirect zur login-Page geht vor Redirect zur sessiontimeout-Page)?
Und zweite Frage: Wiso funktioniert das dann nicht? Die login.xhtml ist ja frei zugänglich...

Auf der Seite des Benutzers zeigt der Webbrowser nur einen Fehler in der übertragenen xhtml-Seite an, da diese komplett leer und ohne Inhalt ist.

Ich bin leider noch nicht so erfahren (mache das nicht beruflich und vermutlich auch nicht sehr professionel / effektiv) und hoffe, mir kann geholfen werden.

Wenn noch weitere Anregungen oder Verbesserungswünsche vorhanden sind, nehme ich mir diese gern zu Herzen und versuche, diese umzusetzen.

Schoneinmal vielen Dank an alle, die mir helfen können


----------



## sence (18. Nov 2012)

schau dir mal die Antwort von Balusc an (#2)
java - JSF: Cannot catch ViewExpiredException - Stack Overflow


----------



## DerEwigeGaast (18. Nov 2012)

sence hat gesagt.:


> schau dir mal die Antwort von Balusc an (#2)
> java - JSF: Cannot catch ViewExpiredException - Stack Overflow



Hallo, 

danke dir für deine Antwort, leider hilft mir dies aber nicht weiter. Das Problem besteht weiterhin. 
Ich habe das Ganze jetzt auch mal versucht einzugrenzen: Anscheinend tritt dieser Fehler nur auf, wenn die Session abgelaufen ist und der Benutzer versucht, ein POST-Request an den Server zu schicken.

Hat vlt. noch jemand anderes eine Idee?


----------



## Sym (18. Nov 2012)

Du könntest einen Phaselistener implementieren und schauen, in welcher Phase die Exception fliegt. Du könntest dort auch direkt auf den Sessiontimeout reagieren.


----------



## DerEwigeGaast (19. Nov 2012)

Sym hat gesagt.:


> Du könntest einen Phaselistener implementieren und schauen, in welcher Phase die Exception fliegt. Du könntest dort auch direkt auf den Sessiontimeout reagieren.



Hi,

ich habe das mal gemacht und auch gleich einen HTTPSessionListener implementiert, um zu sehen, wann die Sessions beendet werden.
Ich rufe also eine Seite auf und warte bis auf dem Server

```
INFO: Session(8ce23531a8fc02e2bc850815d27c) wurde entfernt
```
erscheint.
Dann versuche ich auf der zuvor aufgerufenen Seite zu Speichern, was mir dann wieder mit dem o.g. Fehler quitiert wird und der Browser wieder einen Parse-Error anzeigt. Der Server hat folgende Logs vor der Exception (danach logischerweise keine mehr):

```
INFO: Session(8d13de31d6ccb0a0acff09d63df5) wurde erstellt
INFO: BeforePhase RESTORE_VIEW 1 com.sun.faces.lifecycle.LifecycleImpl@589f46
INFO: AfterPhase RESTORE_VIEW 1 com.sun.faces.lifecycle.LifecycleImpl@589f46
```

D.h. wie der Fehler sagte, fliegt die Exception nach der RESTORE_VIEW-Phase.

Wie könnte ich dort in meinem PhaseListener auf die Exception reagieren? Die bekomme ich doch garnicht zu gesicht?

```
public class PagePhaseListener implements PhaseListener{
    private static final Logger LOG = Logger.getLogger(PagePhaseListener.class.getName());

    @Override
    public void afterPhase(PhaseEvent event) {
        LOG.info("AfterPhase " + event.getPhaseId() + " " + event.getSource());
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        LOG.info("BeforePhase " + event.getPhaseId() + " " + event.getSource());
    }

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }
}
```


----------



## freez (20. Nov 2012)

ganz spontaner Gedanke: Kann es sein, dass du versehentlich die SessionTimout Seite mit einem Benutzerlogin abgesichert hast. Durch die neue Session leitet er auf deine Login Seite um.

Vielleicht ist ein Platzhalter '*' an einer etwas ungünstigen Stelle, oder du hast nur bestimmte /public/* Seiten abgesichert und er rausch in ein "deny all" rein.


----------



## Sym (20. Nov 2012)

@freez: das könnte natürlich auch sein.

@DerEwigeGaast: Du könntest in dem Phaselistener doch einen redirect machen, wenn die Session weg ist. Auch in "Any"-Phase.


----------



## JimPanse (20. Nov 2012)

jsf-problem-session-abgelaufen


----------



## DerEwigeGaast (20. Nov 2012)

Hallo und danke schonmal, für die neuen Antworten!



freez hat gesagt.:


> ganz spontaner Gedanke: Kann es sein, dass du versehentlich die SessionTimout Seite mit einem Benutzerlogin abgesichert hast. Durch die neue Session leitet er auf deine Login Seite um.
> 
> Vielleicht ist ein Platzhalter '*' an einer etwas ungünstigen Stelle, oder du hast nur bestimmte /public/* Seiten abgesichert und er rausch in ein "deny all" rein.



Das kam mir auch als erstes in den Sinn, habe allerdings jetzt nochmals nachgesehen und die Seiten im Unterverzeichnis /public/ sind definitiv ALLE freigegeben und auch manuell erreichbar.



			
				Sym hat gesagt.:
			
		

> @DerEwigeGaast: Du könntest in dem Phaselistener doch einen redirect machen, wenn die Session weg ist. Auch in "Any"-Phase.



Darauf bin ich dann auch gekommen, habe nur deinen vorherigen Kommentar mit dem Reagieren auf den SessionTimeout falsch gelesen / interpretiert.

```
@Override
    public void afterPhase(PhaseEvent event) {
        LOG.info("AfterPhase " + event.getPhaseId() + " " + event.getSource());


        HttpSession session = (HttpSession) event.getFacesContext().getExternalContext().getSession(false);
        if (session != null) {
            if (session.isNew()) {
                LOG.info("Session ist neu");
                FacesContext c = event.getFacesContext();
                NavigationHandler nav = c.getApplication().getNavigationHandler();
                nav.handleNavigation(c, null, "/public/sessiontimeout.xhtml");
            }
        }
    }
@Override
    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }
```
Leider ist das Problem, dass sobald die Session abgelaufen ist und ich einen Post durchführe eine neue Session automatisch erstellt wird, sodass eine Abfrage auf session == null keinen Erfolg bringt. Obiges funktioniert allerdings auch nicht und mein Webbrowser bleibt immer noch beim Parse-Error und intern fliegt weiterhin eine ViewExpiredException.
Log (nach dem Login):

```
INFO: Session(eb8274e10a27004210a422a9200b) wurde erstellt
INFO: BeforePhase RESTORE_VIEW 1 com.sun.faces.lifecycle.LifecycleImpl@1d7de67
INFO: AfterPhase RESTORE_VIEW 1 com.sun.faces.lifecycle.LifecycleImpl@1d7de67
INFO: BeforePhase RENDER_RESPONSE 6 com.sun.faces.lifecycle.LifecycleImpl@1d7de67
INFO: AfterPhase RENDER_RESPONSE 6 com.sun.faces.lifecycle.LifecycleImpl@1d7de67
```

Dann warte ich wieder, bis die Session abgelaufen ist, und versuche einen Post durchzuführen:

```
INFO: Session(eb8274e10a27004210a422a9200b) wurde entfernt
INFO: Session(eb994141b0d138a867299dfb1775) wurde erstellt
INFO: BeforePhase RESTORE_VIEW 1 com.sun.faces.lifecycle.LifecycleImpl@1d7de67
INFO: AfterPhase RESTORE_VIEW 1 com.sun.faces.lifecycle.LifecycleImpl@1d7de67
INFO: Session ist neu
```

@JimPanse: Die erste Variante brachte mir nur noch weitere Schwierigkeiten und die zweite Variante funktionierte leider auch nicht.


----------



## mario87b (21. Nov 2012)

Alles nur Vermutungen, aber prüfe folgendes.


```
<location>/faces/public/sessiontimeout.xhtml</location>
```


----------



## DerEwigeGaast (21. Nov 2012)

mario87b hat gesagt.:


> Alles nur Vermutungen, aber prüfe folgendes.
> 
> 
> ```
> ...



Danke dir, für den Hinweis, allerdings stimmten meine Pfade.
Ich habe mitlerweile auch mal einen ExceptionHandler samt Factory gebaut, und siehe da, es geht. Leigt vmtl. daran, dass die Exception-Konfiguration in der web.xml nicht mit AJAX zusammenarbeitet, bzw. dort keine Exceptions fangen kann. Mache ich einen Post ohne AJAX, geht es 

Trotzdem vielen Dank an alle, wart eine super Hilfe!


----------

