[JSF/Ajax] Le chiamate Ajax in situazioni di session timeout

Faces-2.0-JSF-AjaxChi lavora con JSF (Java Server Faces)  e sfrutta i meccanismi di AJAX, sicuramente si è imbattuto nel problema delle richieste asincrone “parziali” (partial ajax) effettuate quando la sessione utente è andata in timeout. Come è ovvio in tale situazione, le richieste non vanno a buon fine, ma poiché non vi è un “refresh” di tutta la pagina (ma solo di sue porzioni precise), le risposte non vengono propriamente trattate come tali lato client e non “ci si accorge” del session timeout, rimanendo “piantati” sulla stessa pagina senza veder accadere nulla (nemmeno sui log applicativi viene stampato nulla)  

Si potrebbe pensare di effettuare una redirect ad una pagina di login, chiedendo all’utente di riloggarsi. A tale scopo, tra i tanti metodi che si trovano online (WebFilter, Interceptorecc.), propongo qui quello che utilizza un PhaseListener, che si interpone tra tutte le richieste HTTP effettuate (siano essere normali request o, appunto, partial ajax request), in modo da controllare se la sessione è valida e, in caso negativo, rimandare l’utente su una pagina definita.

Ecco la classe che occorre inserire nel vostro progetto JSF:

/* Classe SessionExpirationPhaseListener */

import javax.faces.application.ConfigurableNavigationHandler;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletRequest;

/**
 * 
 * listener per il controllo della session timeout per le chiamate AJAX
 *
 */
public class SessionExpirationPhaseListener implements PhaseListener {

    /**
	 * 
	 */
	private static final long serialVersionUID = 257760346127143382L;

	@Override

    public PhaseId getPhaseId() {
        return PhaseId.RESTORE_VIEW;
    }

    @Override
    public void beforePhase(PhaseEvent event) {

    }

    @Override
    public void afterPhase(PhaseEvent event) {

        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest httpRequest = (HttpServletRequest) context.getExternalContext().getRequest();

        if (httpRequest.getRequestedSessionId() != null && !httpRequest.isRequestedSessionIdValid()) {
            String facesRequestHeader = httpRequest.getHeader("Faces-Request");
            boolean isAjaxRequest = facesRequestHeader != null && facesRequestHeader.equals("partial/ajax");

            if (isAjaxRequest) {
                ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) context.getApplication().getNavigationHandler();
                handler.performNavigation("session-expired");
            }
        }
    }
}

 

Occorre poi inserire il seguente mapping nel file faces-config.xml :

<lifecycle>
    <phase-listener>it.francescoficetola.web.filter.SessionExpirationPhaseListener</phase-listener>
</lifecycle>

Così facendo tutte le richieste HTTP, comprese quelle di tipo partial/ajax, verranno intercettate dal listener.

[DWR] Direct Web Remoting: Easy AJAX for Java

DWR (Direct Web Remoting) è una libreria Java open-source (Apache Software License v2) che permette a Java (lato back-end) e JavaScript (lato front-end) di interagire e chiamarsi a vicenda nel modo più semplice possibile.
DWR si integra con Spring, Struts, Hibernate e altri framework.

 

Ecco lo slogan di DWR: “DWR is Easy Ajax for Java“.

Ecco il sito ufficiale di DWR: http://directwebremoting.org

Cosa fa DWR? DWR permette di generare codice JavaScript che permetta ai web browser di chiamare in sicurezza codice Java come se venisse eseguito localmente. Effettua una operazione di marshalling virtuale che include collections, POJOs, XML e binary data (come immagini e file PDF).
Mette a disposizione anche una funzionalità di Reverse Ajax, che permette a codice Java in esecuzione sul server di utilizzare/richiamare API lato client per pubblicare aggiornamenti su determinati gruppi di browser.

Questo tipo di interazione è, dunque, bidirezionale – browser che chiama il server e server che chiama il browser.
DWR supporta Comet, Polling e PiggyBack (spedendo i dati in una normale request) come modalità per la notifica da server a browser.

Come funziona? Il meccanismo di interazione bidirezionale avviene tramite chiamate RPC (Remote Procedure Call).
Nella seguente figura, viene mostrato un primo diagramma che rappresenta come DWR altera il contenuto di una select HTML con il risultato di un evento JavaScript (il client chiama il server per farsi restituire i risultati):


Il Reverse Ajax di DWR (disponibile dalla versione 2.0) permette a codice Java in esecuzione sul server di intercettare quali client stanno visualizzando determinate pagine, in modo da inviare loro (tramite JavaScript) dei risultati (meccanismo di comunicazione inverso – da server a client):


DWR è composto da due parti principali:

  • una servlet Java in esecuzione sul server che processa le richieste e manda le risposte indietro al browser
  • JavaScript in esecuzione sul browser che manda le richieste e può dinamicamente aggiornare il contenuto della pagina

DWR genera dinamicamente codice JavaScript da classi Java ed effettua il marshalling dei dati scambiati in modo bidirezionale, eseguendo il tutto lato server.
Il metodo di remoting functions (Reverse Ajax) da Java a JavaScript fornisce un meccanismo RPC molto simile a RMI o SOAP, con il vantaggio che l’esecuzione avviene su un browser senza necessità di plugin addizionali.

Download di DWR: http://directwebremoting.org/dwr/downloads/index.html

Installazione di DWR: http://directwebremoting.org/dwr/introduction/getting-started.html#fiveSteps

Continua la lettura