Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 16
  1. #1
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328

    [Servlet] Perdita di oggetti in sessione: dubbi sull'affidabilità di Tomcat 6

    Ho un dubbio che mi attanaglia da stamattina, quando, controllando i log di Tomcat, ho notato una cosa alquanto strana. Illustro prima la situazione, poi il problema che si è verificato.

    C'è una WebApplicazione che gira su Tomcat 6 in una macchina Win 2003 Server (presto, spero, verrà spostata).
    In particolare c'è una sezione che attua una procedura che permette all'utente di effettuare alcune scelte. La procedura si svolge in 3 passi:

    1) Carico una lista di oggetti (in un ArrayList) e visualizzo una pagina JSP in cui faccio scegliere all'utente uno degli oggetti caricati

    2) Quando l'utente effettua la scelta e conferma la form, carico una seconda lista di oggetti (dipendenti dalla prima) e visualizzo una seconda pagina JSP in cui faccio scegliere all'utente uno degli oggetti appena caricati

    3) Quando l'utente effettua la seconda scelta e conferma la form, carico una terza lista di oggetti e li visualizzo per l'utente in una nuova pagina JSP

    Lo scenario è classico: l'utente vede un elenco di marche; ne sceglie una; viene visualizzato un elenco di modelli per la marca scelta; l'utente ne sceglie uno e vengono visualizzati tutti i prodotti relativi al modello scelto.

    Tutto questo processo è gestito da un solo dispatcher che, in base al passo in cui ci si trova, effettua le operazioni richieste e visualizza la JSP corretta. Le JSP operano utilizzando gli oggetti in sessione.

    Ecco il dispatcher:

    codice:
    public void dispatch(HttpServletRequest request, HttpServletResponse response) throws ... {
       ...
       switch( step ) {
    
          case 0:   // Primo step. Carico le marche e le visualizzo
             caricaMarche( ... );
             view = ... // La JSP che si occupa del rendering per la scelta della marca
             break;
    
          case 1:   // Secondo step. L'utente ha scelto la marca: carico e visualizzo i relativi modelli
             caricaModelli( ... );
             view = ... // La JSP che si occupa del rendering per la scelta del modello
             break;
    
          case 2:   // Terzo step. L'utente ha scelto il modello: carico i prodotti e li visualizzo
             caricaProdotti( ... );
             view = ... // La JSP che visualizzerà i prodotti per la scelta dell'utente
       }
       ...
    }
    E questi sono i metodi caricaMarche() e caricaModelli(), ovvero i due incriminati nel problema:

    codice:
    private void caricaMarche( ... ) {
       Session s = ... ;
    
       ...
    
       ArrayList marche = new ArrayList()
    
       ...   // Carico le marche dal sistema e popolo l'ArrayList
    
       s.setAttribute("marche", marche);
    }
    
    private void caricaModelli( ... ) {
       Session s = ...;
       ...
       // Prelevo il codice della marca selezionata dall'utente
       String codiceMarca = request.getParameter("codiceMarca");
    
       // Carico i modelli per la marca selezionata
       ...
    
       // Prelevo dalla sessione l'ArrayList delle marche, caricato nello step precedente
       ArrayList listaMarche = (ArrayList) s.getAttribute("marche");
       if (listaMarche != null) {
          ...   // Effettuo altre considerazioni e operazioni
       } else {
          // Scrivo nel log di Tomcat le informazioni relative alla situazione anomala
          System.err.println("ArrayList marche nullo nel Dispatcher.");
          System.err.println("Codice marca: " + codiceMarca);
          System.err.println("Utente: " + utente.getUserID());
          System.err.println("Cliente: " + utente.getCodiceCliente());
          System.err.println("Situazione della sessione:");
          System.err.println("Creation-Time: " + s.getCreationTime());
          System.err.println("Last-Accessed-Time: " + s.getLastAccessedTime());
       }
    }
    Ed ecco cosa ho trovato nel log stamattina:

    codice:
    ArrayList marche nullo nel Dispatcher.
    Codice marca: 260
    Utente: 1242
    Cliente: 004489
    Situazione della sessione:
    Creation-Time: 1284645496234
    Last-Accessed-Time: 1284645511359
    Aggiungo una informazione utile: ho imposto un timeout di sessione di 3 ore per ciascun utente loggato. Ciò significa che la sessione scade dopo 3 ore di inattività.

    Da quello che c'è nel log si può evincere quanto segue:

    1) E' stato eseguito il codice del ramo "else" del metodo "caricaModelli()" postato sopra

    2) Dal punto 1) si desume che l'utente ha correttamente visualizzato la pagina delle marche ed ha effettuato una scelta (ha selezionato la marca classificata con codice 260)

    3) Dal punto 2) si desume che la JSP che visualizza l'elenco delle marche ha trovato in sessione l'ArrayList delle marche

    4) Dal punto 3) si desume che il metodo "caricaMarche()" ha effettuato correttamente il suo lavoro.

    5) Il punto 4) è in netta contraddizione con il log presente in Tomcat per i seguenti motivi:

    a) La sessione era stata creata solo 15 secondi prima che venisse a galla l'errore (quindi non poteva ancora essere scaduta)

    b) L'utente è riuscito ad effettuare una scelta (codice marca 260!), quindi l'ArrayList era in sessione al momento del rendering della JSP.

    Qualcuno ha qualche idea del motivo per cui possono accadere queste cose? Finché questo genere di cose capitano 1 volta ogni 7-8 mesi non è un grosso problema, ma tutto questo mi dà da pensare sull'affidabilità di Tomcat.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  2. #2
    Utente di HTML.it L'avatar di desa
    Registrato dal
    Oct 2008
    Messaggi
    569
    Quello che mi manca è come fai a impostare la variabile "step" e come gestisci la creazione (EDIT: il recupero) delle sessioni (cosa c'è al posto dei 3 puntini di "Session s = . . ." ?)

    La prima ipotesi che mi viene in mente è che l'utente abbia fatto una richiesta "mirata" alla pagina dei modelli passandogli nella request "marca=260".
    La seconda ipotesi, direttamente collegata a questa, è che l'utente sia rimasto "idle" sulla pagina delle marche per, che so, 4 ore e poi abbia effettuato la selezione della marca.

  3. #3
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Originariamente inviato da desa
    Quello che mi manca è come fai a impostare la variabile "step" e come gestisci la creazione (EDIT: il recupero) delle sessioni (cosa c'è al posto dei 3 puntini di "Session s = . . ." ?)
    Mi aspettavo questa domanda.
    La variabile "step" è passata alla JSP che la inserisce in un campo HIDDEN del form... quindi la recupero, semplicemente, dalla Request.

    La sessione viene recuperata in questo specifico modo:

    codice:
    HttpSession s = request.getSession( false );
    Questo mi garantisce che non viene creata alcuna "nuova" sessione; se la request non ha una sessione attiva, viene restituito null e questo io lo testo all'interno del dispatcher. Non l'ho mostrato nel codice per semplicità, ma avviene questo:

    codice:
    HttpSession s = request.getSession( false );
    
    if(s == null) {
       ...   // Qui visualizzo nel log altri errori ed il metodo termina
    } else {
       ... // Resto del corpo del metodo postato prima
    }
    La prima ipotesi che mi viene in mente è che l'utente abbia fatto una richiesta "mirata" alla pagina dei modelli passandogli nella request "marca=260".
    Ipotesi da scartare: tutti i form vengono passati in POST e gli utenti della WebApp non sono così evoluti da poter effettuare qualcosa del genere... Senza contare che dovrebbero essere passati altri parametri nella URL e che, comunque, vi sono controlli su altri oggetti in sessione.

    La seconda ipotesi, direttamente collegata a questa, è che l'utente sia rimasto "idle" sulla pagina delle marche per, che so, 4 ore e poi abbia effettuato la selezione della marca.
    Ipotesi contraddetta dalla stampa nel log: Creation-Time e Last-Accessed-Time differiscono di soli 15 secondi. Tutti gli altri attributi (come il codice dell'utente e del cliente) vengono creati e salvati in sessione dallo specifico Dispatcher che si occupa della Login e sono valorizzati (li si vede nel log).

    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  4. #4
    Utente di HTML.it L'avatar di desa
    Registrato dal
    Oct 2008
    Messaggi
    569
    E io mi aspettavo questa risposta, e sono già pronto a ri-risponderti

    A parte gli scherzi, ti spiego quale è stato il primo sospetto che ho avuto.
    Tra i possibili attributi della direttiva "page" della JSP ne esiste uno che si chiama "session":

    codice:
    <%@ page session = "true | false" %>
    Quello che fa è, in base al valore, rendere o meno disponibile l'oggetto implicito "session": se una pagina non usa la sessione lo puoi tranquillamente impostare a "false" e risparmiarti qualche ciclo di clock. Ma se invece ne imposti il valore a "true" (e, in caso di omissione della direttiva, per default lo è) il servlet container si premura (dovrebbe farlo) di renderti disponibile una sessione nel suddetto oggetto "session": se esiste già è quella associata alla richiesta del client, in caso contrario te ne crea una nuova fiammante. In ogni caso, non sarà null.

    Fai questa prova: crea una webapp di test e imposta sul descrittore dell'applicazione un timeout di sessione di 1 minuto (per praticità).
    Poi scrivi una pagina JSP con la sola linea di codice:

    codice:
    <% System.out.println(request.getSession(false).getCreationTime()); %>
    A questo punto, richiedendo la pagina se la getSession() ti ritorna null otterrai una NullPointerException; in caso contrario vedrai il timestamp di creazione sullo stdout.

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Garantisco che le JSP, in questo specifico caso, non c'entrano nulla.

    La valorizzazione degli oggetti relativi all'utente (l'oggetto "utente" da cui prelevo IDUtente e CodiceCliente) viene effettuata solo ed esclusivamente all'interno di uno specifico Dispatcher (quello che si occupa della login).

    Se venisse creasta una nuova sessione da una JSP, questo oggetto non solo non esisterebbe, ma non potrebbe contenere nemmeno dati validi.

    I dati stampati nel log, invece, riferiscono ad un IDUtente valido, associato al corretto CodiceCliente. Ergo, la valorizzazione di quell'oggetto Session è avvenuta correttamente in fase di Login.

    Tengo a precisare una cosa in più: al momento del primo accesso al sito, viene sempre creata una sessione. La login non crea nuove sessioni, ma effettua solamente una serie di valorizzazioni su oggetti già presenti in sessione e, al più, ne aggiunge altri.

    Quindi, anche se una JSP creasse una sessione "nuova fiammante", non sarebbe comunque in grado di valorizzare il bean "utente" in quel modo.


    Rimane il mistero...
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    Utente di HTML.it L'avatar di desa
    Registrato dal
    Oct 2008
    Messaggi
    569
    Ok, se l'oggetto "utente" è settato esclusivamente nella pagina di login non è questa la strada giusta. Ti propongo allora un nuovo scenario.
    Come nella seconda ipotesi che avevo fatto, diciamo che l'utente rimane in "idle" per 4 ore sulla pagina delle marche. A questo punto apre una nuova finestra/tab del browser e va sulla pagina di login, autenticandosi. Quindi, torna alla finestra/tab precedente ed effettua la selezione della marca.
    Lo scenario sembra poco probabile anche a me, ma te l'ho scritto perchè in realtà ho in mente un'altra cosa. Ma prima ti chiedo: diciamo che l'utente seleziona una marca con sessione scaduta (solita storia dell'idle)... cosa fai? Lo redirezioni sulla pagina di login?

  7. #7
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Sono apertissimo a tutte le ipotesi immaginabili perchè, davvero, mi piacerebbe andare a fondo della questione e trovare l'inghippo.

    La questione delle tab sarebbe da approfondire (sono curioso di capire quale scenario mi stai aprendo), anche se con alcuni test effettuati in passato mi pare non vi fossero grossi problemi.

    Rispondo alla tua domanda:

    Ma prima ti chiedo: diciamo che l'utente seleziona una marca con sessione scaduta (solita storia dell'idle)... cosa fai? Lo redirezioni sulla pagina di login?
    No: l'utente viene rediretto ad una pagina in cui lo si informa della scadenza della sessione e lo si invita a chiudere il browser e ad accedere nuovamente (in soldoni).
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  8. #8
    Utente di HTML.it L'avatar di desa
    Registrato dal
    Oct 2008
    Messaggi
    569
    Quello che avevo in mente è in realtà strettamente correlato allo scenario di prima... anzi, diciamo pure che in linea di principio il meccanismo è proprio lo stesso. In pratica si basa sul bisogno compulsivo dell'utente di cliccare sul pulsante "indietro" del browser ogni volta che gli è possibile. Provo a ri-delineare:
    - la sessione scade mentre l'utente ha ancora la pagina delle marche aperta sul browser;
    - l'utente fa la sua selezione di una marca;
    - durante il processing della pagina, il bean "utente" non viene trovato e il servlet container risponde al client con il messaggio di sessione scaduta che mi hai indicato;
    - l'utente non ci pensa neanche a chiudere il browser: va sulla pagina di login e si autentica nuovamente;
    - il servlet container esegue tutte le normali operazioni di autenticazione e restituisce la home page;
    - l'utente clicca sul pulsante "indietro" del browser fino a tornare alla pagina delle marche;
    - l'utente esegue nuovamente la selezione precedentemente fallita.

    Oh, poi non voglio fare l'avvocato del diavolo: magari hai beccato per davvero un bug di Tomcat!

  9. #9
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328

    Moderazione

    Scenario interessante e da provare.
    Effettuerò qualche test in proposito e controllerò anche il log dell'utente per verificare se sia plausibile uno scenario come questo. In effetti, l'utente classico non è portato a leggere ciò che gli viene scritto a video quindi non escludo affatto che abbia semplicemente ignorato i suggerimenti e fatto la cosa più stupida.

    Ciao e grazie.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  10. #10
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157
    non ve lo voglio dire, ma è una cosa succede sul forum di html.
    mi è successo, per un motivo o per un altro, di "perdere" parecchio tempo per scrivere il mex, sessione scaduta, ergo ricollegati. Di questo me ne accorgo premendo "invia risposta", rifaccio il login che mi redireziona in una pagina di "errore" e mi chiede di contattare l'admin.
    Per tornare a quello che scrivevo inizia il click compulsivo del pulsante indietro (eheh sono una user rompi), premo invia e l'invio è ok.

    Non so a dire dove è hostato questo forum e non sono ai vostri livelli, ma su alcune cose (come questa) penso sia un comportamento "generale" e non solo di Tomcat...poi non so

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.