Newsgroup: it.comp.java
Titolo: Processi "batch"  in Java

Ciao a tutti,
ho una web application che deve lanciare un'elaborazione che dura parecchi 
minuti.
Poichè è impensabile fare asopettare l'utente davanti a una pagina web che 
dice "attendere prego" (per es l'utente potrebbe chiudere il browser e non 
sapere mai più se l'eleaborazione è terminata) pensavo di simulare quello 
che esiste da anni in ambiente mainframe, cioè sottomettere il prcesso in 
modalità "bacth" (lanciando un thread in modo asincrono), per poi fare una 
pagina web dalla quale l'utente possa controllare lo stato dei processi 
lanciati.
Mi chiedevo se esistono già delle librerie che permettono di monitorare 
agevolmente dei thread asincroni oppure mi devo sviluppare tutto in casa?
Grazie in anticipo,
D.

 ha scritto nel messaggio 
news:evo6bu$8ks$1...@newsreader.mailgate.org...

Sarei anch'io interessato alla cosa... per quel che mi ricordo, però, 
l'ambiente J2EE è alquanto "ostile" all'impiego
di thread "spuri" (avviati ad esempio all'interno di un metodo EJB o di una 
servlet), quindi personalmente non saprei come gestire la cosa, e, neppure, 
come realizzarla: con un Runtime.exec o con una stored proc. sono le uniche 
idee che mi vengono in mente...
Saluti,
    Scorpio.

 minuti.
CIAO!
discorso molto interessante...
secondo me bisogna definire il concetto di stato...
cioe, a runtime non puoi sapere quanto manca alla fine di un processo!
io  lancerei  un thread che scrive in una cartella un file del tipo
START_nomePRocesso
in questo file ci puoi far scrivere ad esempio dei log (ho fatto qusto
questo questo etc)
quando finisce fai rinominare il file in END_nomeProcesso
quando l'utetne visita la pagina di stato, gli fai selezionare il file
che vuole visionare
e quindi gli mostri il contenuto in una qualche forma.
Spero di averti dato uno spunto!


Inizialmente mi interesserebbe sapere solo se il "lavoro batch" è ancora 
attivo o è terminato; il discorso di gestirne lo "stato corrente"o potrebbe 
esserre una successiva evoluzione.
Mi sembra però assurdo che nessuno abbia questa esigenza (o sono l'unico a 
sviluppare programmi "gestionali" in java?).
D.


Si può fare e l'ho fatto: l'unica cosa su cui devi stare "attento" e
lavorare sono i tempi definiti sull'AS
Chiaramente, se invece non ti serve che il tutto parta ad un click,
allora puoi definire il Thread direttamente sulla macchina come
un'applicazione standalone

 controllare lo stato dei processi lanciati.
Ciao, 
tecnica brutale:
Il tuo "click", quello che dovrebbe lanciare il processo in batch,
inserisce semplicemente la richiesta in una tabella con una struttura dipo
questa
id, applicazione, parametri, stato
dove applicazione e' l'oggetto che devi eseguire, parametri gli eventuali
parametri che devi passare e stato indica in che modalita' e' quel
deeterminato processo(0:in attesa, 1:in corso, 2:finito)
Questa tabellina viene controllata da un serverino che gira ogni x secondi
e prende il primo record a 0 lo mette a 1 ed istanzia l'applicazione da
eseguire e inizia il lavoro, appena finito lo mette a 2
poi...sotto il prossimo con stato 0
In questo modo puoi avere con estrema facilita', una semplice query su
quella tabella, una pagina web dove sono presenti le applicazioni in batch
da processare, in corso o terminate.
Anche il serverino e' estremamente semplice da fare, ad esempio nella
colonna "applicazione" puoi mettere il nome diretto dell'oggetto tipo:
mia.applicazione.nel.package.LaClasse cosi da eseguirla, chesso', con le
reflection.
In questo modo puoi poi avere un sistema un po piu' "gestibile" inserendo
nella tabella datainizio e datatermine, rieseguire un processo
semplicemente rimettendo a 0 un record etc etc
Cmq, fatto cosi come l'ho descritto e' piu' facile a farsi che a dirsi ;)
Spero di esserti stato d'aiuto.
Ciao,
crx
 

 cioe, a runtime non puoi sapere quanto manca alla fine di un processo!
ah no?
allora tutte le barre di progressione che ci sono in qualsiasi
programma sono una farsa?

> manca alla fine di un processo!
J> ah no?  allora tutte le barre di progressione che ci sono in
J> qualsiasi programma sono una farsa?
No, sono coperte da brevetto...
[OT, ma serio]
-- 
 /\           ___
/___/\_|_|\_|__|___Gian Uberto Lauri_____
  //--\| | \|  |   Integralista GNUslamico
\/                 e coltivatore diretto di Software
A Cesare avrei detto di scrivermi a 
fn...@rat.vg

> 
p> Si può fare e l'ho fatto
Non ha  detto "non funziona",  ha detto che  J2EE é "ostile".   Il che
vuole dire  che NON è  una buona cosa  farlo (c'entra la  gestione dei
thread da  parte dello AS).  Anche se in  molti lo hanno  fatto quando
altra scelta non c'era.
Usare un Message Driven bean è più pulito.



Anche in alternativa ai Timer Services ? (non ho esperienze da condividere
in merito)
"EJB 2.1 The Timer Service"
http://www.theserverside.com/tt/articles/article.tss?l=MonsonHaefel-Column4
"EJB 3.0 Timer Services - Timer Services API"
http://www.javabeat.net/javabeat/ejb3/articles/timer_services_api_in_ejb_3_0_1.php
--
Marco
-- 
Posted via a free Usenet account from 
http://www.teranews.com

 programma sono una farsa?
Non tutte. Ma buona parte si. Non dirmi che da te sono sempre state
precise. 
D'altra parte l'importante non è essere *assolutamente* precisi. Ma dare
all'utente un feedback di progresso.
-- 
blog:  
http://www.akropolix.net/rik0/blogs
 | Uccidete i filosofi,
site:  
http://www.akropolix.net/rik0/
      | tenetevi riso e
forum: 
http://www.akropolix.net/forum/
     | bacchette per voi.

 minuti.
[...]
Per sviluppare "a mano" una soluzione del genere con poco sforzo,
seguirei una logica di questo tipo:
Un worker (potrebbe essere un singleton, per semplificare) e' sempre
attivo, ed e' capace di eseguire i tuoi lunghi processi secondo una
logica da te scelta (uno dopo l'altro, o piu' di uno
contemporaneamente).
Il worker attinge da un pool, eventualmente integrato nel worker
stesso (una qualche implementazione di Collection) che viene
alimentato direttamente dalle richieste web degli utenti.
Per quanto invece il "consumo" del pool da parte del worker, una
simpatica soluzione puo' essere quella di rendere il worker un
listener di processi, e basarsi su questo paradigma per ottimizzarne
l'esecuzione.
Un minimale (e migliorabile) implementazione puo' essere questa:
public interface ProcessListener{
  void onFinish();
}
public class Worker implements ProcessListener{
  public final static int MAX_CONCURRENT_PROCESSES = 5;
  /** I processi in attesa di essere eseguiti */
  private List<MyProcess> processPool = new ArrayList<MyProcess>();
  /** Il numero di processi attualmente in esecuzione */
  private int runningProcessCount;
  /** Accoda un nuovo processo */
  public synchronized void enqueue( MyProcess process ){
    processPool.add( process );
    startNextProcess();
  }
  /** Richiamato da MyProcess quando termina l'esecuzione del processo
*/
  synchronized void onFinish(){
    --runningProcessCount;
    startNextProcess();
  }
  /** Ritorna true quando il worker e' disponibile ad eseguire un
processo */
  private boolean readyToExecuteNextProcess(){
    return !processPool.isEmpty() && runningProcessCount <
MAX_CONCURRENT_PROCESSES;
  }
  /** Esegue un processo in un thread separato */
  private void startNextProcess(){
    if( readyToExecuteNextProcess() ){
      MyProcess process = processPool.remove( 0 );
      process.setListener( this );
      ++runningProcessCount;
      new Thread( process ).start();
    }
  }
}
public class MyProcess implements Runnable{
  private ProcessListener listener;
  public void setListener( ProcessListener listener ){
    this.listener = listener;
  }
  public void run(){
    //Esecuzione processo...
    listener.onFinish();
  }
}

 
Anche io avevo un problema simile ma ho risolto il tutto creando un 
listener che partendo allo startup della mia applicazione esegue 
periodicamente l'operazione richiesta. Questo listner non faceva altro 
che instanziare n thread ed attendere che tutti abbiano terminato la 
propria esecuzione. Il meccanismo funzionava alla grande ... se ti 
interessa posso postare il listener...
Let me know
-- 
Mess
http://www.mibmagazine.it