Visualizzazione dei risultati da 1 a 4 su 4
  1. #1

    [Jsp - Servlet] Esecuzione Servlet in "background"

    Ciao ragazzi,

    ho un piccolo problemino con una servlet, cerco di illustrarvi al meglio la situazione.
    Il problema è questo: da una pagina jsp, clicco su un bottone, il quale fa partire una servlet che svolge determinate operazioni.

    Una volta eseguite e terminate tutte le operazioni, invia in automatico una mail con il risultato ed effettua il redirect su una nuova pagina jsp.

    Ora: siccome queste operazioni sono "bloccanti" (nel senso che al momento l'esecuzione della servlet impiega circa 10 secondi, ma è possibile anche che ci impieghi molti minuti, per es 30 o addirittura un'ora), c'è il rischio che la pagina web mi vada in timeout interrompendo quindi l'esecuzione della servlet. (non posso stimare a priori il tempo impiegato, visto che devo leggere dei dati da DB, confrontarli con dati presenti in un file txt, generare un excel e inviare tale file via mail)

    Quello che vorrei e che non riesco a fare è questo: dalla pagina jsp faccio partire la servlet che mi rimanda immediatamente alla "pagina di conferma" ma che nel frattempo svolga tutte le operazioni mentre io posso fare altro.

    Vi riporto un estratto del codice della servlet:
    codice:
    .....
    do.something();            //interrogazione DB, creazione file xls, invio mail
    
    out.println("<script>window.location=\"http://localhost:8080/myproject/result.jsp");
    out.println("alert (\"Servlet ok\");</script>");
    Ho provato ad invertire le righe di codice scritte sopra, cioè, prima effettuavo il redirect sulla pagina result.jsp e poi eseguivo il "do.something", ma come potete immaginare, non cambiava nulla: prima eseguiva tutte le operazioni, poi effettuava il redirect.

    Come potrei fare per risolvere il mio problema?
    Qualche idea?
    Avevo pensato all'utilizzo dei Thread, ma non sono sicuro di quello che dico e se può essere una soluzione.

    Ringrazio tutti per l'attenzione!!

    Ciao ciao

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,326
    La quetione è spinosa. Lavori molto lunghi (addirittura che impiegano ORE) non devono essere fatti all'interno del metodo service() della servlet. La Servlet dovrebbe sempre compiere lavori snelli (poco pesanti) e/o quantomeno rimanere entro il termine "universale" dei 60 secondi.

    Invertire le istruzioni non ha alcun senso: l'output della servlet viene inviato al client quando termina il metodo service().

    La cosa va fatta in modo molto ponderato tramite l'uso di thread (cosa che nelle web-application è altamente sconsigliata).

    Esiste la possibilità di appoggiarsi a librerie già fatte per questo genere di cose: una delle più famose è Quartz (mai usata in vita mia, non la conosco).

    Se si vuole si può anche fare tutto a mano, ma è necessario prestare molta attenzione a quel che si fa.

    Esempio:

    Nel metodo init() della Servlet è possibile istanziare un Executor (vedi classe Executors) con un pool fisso di thread (in modo da evitare che vengano generati troppi thread).

    Nel metodo service() della Servlet, si sottomette un Task che verrà eseguito dalla JVM non appena possibile.

    Nel metodo destroy() della Servlet ci si deve preoccupare di far terminare tutti i thread ed il thread-pool executor.


    Con un po' di codice:


    codice:
    // Siamo nella Servlet
    private ExecutorService executor;
    
    @Override
    public void init() {
       ...
       executor = Executors.newFixedThreadPool( 20 );   // Al massimo 20 thread
       ...
    }
    
    @Override
    public void destroy() {
       executor.shutdownNow();   // IMPORTANTE: deallochiamo tutto
    
       // E' possibile chiamare in alternativa "shutdown()" se si vuole ATTENDERE che i task
       // precedentemente sottomessi vengano eseguiti... ma questo può causare problemi
       // di responsività nel Servlet Container
    }
    
    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
       ...
       // X è il tipo di ritorno previsto dall'elaborazione
       // TuoLavoro è la tua classe (che implementa Callable<X>), che effettua il lavoro pesante
       Future<X> risultatoElaborazione = executor.submit( new TuoLavoro(...) );
       ...
       // Mandiamo subito in output la response al client
       out.println("<script>window.location=\"http://localhost:8080/myproject/result.jsp");
       out.println("alert (\"Servlet ok\");</script>");
    }

    Ciao.
    Ultima modifica di LeleFT; 09-09-2014 a 17:27
    "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

  3. #3
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,326
    Per inciso, io ho fatto riferimento al metodo service() poichè è lui che viene eseguito quando arriva una richiesta. Solitamente, il codice operativo della Servlet viene scritto nei metodi doGet() / doPost(), che vengono chiamati dal metodo service() a seconda del tipo di richiesta... chiaramente il codice che nell'esempio io ho posto nel metodo service() va messo nel metodo corretto in base alla propria implementazione.


    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

  4. #4
    Ciao!!
    E grazie per la brillante e chiara risposta che mi hai dato!
    Immaginavo che quello che avrei dovuto fare era un po' "complesso" e da trattare con i guanti!!
    Ti ringrazio per il suggerimento e per l'ulteriore spiegazione approfondita (avevo comunque capito di cosa tu stessi parlando).
    Appena avrò un po' di tempo proverò a seguire la tua soluzione e vi terrò aggiornati!

    Grazie ancora!
    Ciaooo

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.