2010-04-22 8 views
5

Ho creato un semplice esempio con le annotazioni @Singleton, @Schedule e @Timeout per provare se avrebbero risolto il mio problema.Servizio timer in ejb 3.1 - problema di timeout delle chiamate di pianificazione

Lo scenario è questo: EJB chiama la funzione di "controllo" ogni 5 secondi e, se vengono soddisfatte determinate condizioni, creerà un singolo timer di azione che invocherà alcuni processi a esecuzione prolungata in modo asincrono. (è una sorta di tipo di implementazione della coda di cose). Continua quindi a controllare, ma mentre il processo di lunga durata è lì, non ne avvierà un altro.

Di seguito è riportato il codice che ho elaborato, ma questa soluzione non funziona, perché sembra che la chiamata asincrona che sto effettuando stia effettivamente bloccando il mio metodo @Schedule.

@Singleton 
@Startup 
public class GenerationQueue { 

    private Logger logger = Logger.getLogger(GenerationQueue.class.getName()); 

    private List<String> queue = new ArrayList<String>(); 

    private boolean available = true; 

    @Resource 
    TimerService timerService; 

    @Schedule(persistent=true, minute="*", second="*/5", hour="*") 
    public void checkQueueState() { 

     logger.log(Level.INFO,"Queue state check: "+available+" size: "+queue.size()+", "+new Date()); 

     if (available) { 

      timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false)); 
     } 

    } 

    @Timeout 
    private void generateReport(Timer timer) { 

     logger.info("!!--timeout invoked here "+new Date()); 

     available = false; 

     try { 

      Thread.sleep(1000*60*2); // something that lasts for a bit 

     } catch (Exception e) {} 

     available = true; 

     logger.info("New report generation complete"); 

    } 

Cosa mi manca o dovrei provare un diverso approccio? Tutte le idee più graditi :)

test con Glassfish 3.0.1 build più recente - dimenticato di citare

risposta

11

Il @ConcurrencyManagement predefinito per single è ConcurrencyManagementType.CONTAINER con predefinito @Lock di LockType.WRITE. Fondamentalmente, ciò significa che ogni metodo (incluso generateReports) viene effettivamente contrassegnato con la parola chiave sincronizzata, il che significa che checkQueueState si bloccherà mentre viene eseguito generateReport.

Prendere in considerazione l'utilizzo di ConcurrencyManagement (ConcurrencyManagementType.BEAN) o @Lock (LockType.READ). Se nessun suggerimento aiuta, ho il sospetto che tu abbia trovato un insetto Glassfish.

Per inciso, probabilmente si desidera persistent = false poiché probabilmente non è necessario garantire che il metodo checkQueueState venga attivato ogni 5 secondi anche quando il server non è in linea. In altre parole, probabilmente non è necessario che il contenitore attivi "catch up" quando si riporta in linea il server.

+0

Grazie mille, il problema è stato risolto cambiando la concurrenza in ConcurrencyManagementType.BEAN e sì, cambierò persistente in falso :) Grazie per l'aiuto. – Greg

+1

Bella risposta, ho imparato qualcosa di nuovo. Grazie! –

Problemi correlati