2010-04-22 16 views
5

He creado un ejemplo simple con anotaciones @Singleton, @Schedule y @Timeout para probar si iban a resolver mi problema.Servicio de temporizador en ejb 3.1 - programar el problema de tiempo de espera de llamada

El escenario es el siguiente: EJB llama a la función de 'comprobación' cada 5 segundos, y si se cumplen ciertas condiciones, creará un temporizador de acción simple que invocaría algún proceso de larga ejecución de manera asincrónica. (es una especie de tipo de implementación de cola). Luego continúa comprobando, pero mientras el proceso de larga ejecución está allí, no comenzará otro.

A continuación se muestra el código que se me ocurrió, pero esta solución no funciona, porque parece que la llamada asíncrona que realizo está bloqueando de hecho mi método @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"); 

    } 

¿Qué es lo que falta aquí o debería probar otro enfoque? Cualquier ideas más agradables :)

pruebas con Glassfish 3.0.1 versión más reciente - olvidó mencionar

Respuesta

11

El @ConcurrencyManagement predeterminada para conjuntos unitarios es ConcurrencyManagementType.CONTAINER con defecto de @Lock LockType.WRITE. Básicamente, eso significa que todos los métodos (incluido generateReports) se marcan de manera efectiva con la palabra clave synchronized, lo que significa que checkQueueState se bloqueará mientras se esté ejecutando generateReport.

Considere utilizar ConcurrencyManagement (ConcurrencyManagementType.BEAN) o @Lock (LockType.READ). Si ninguna sugerencia ayuda, sospecho que has encontrado un error de Glassfish.

Como comentario adicional, es probable que desee persistent = false ya que probablemente no necesite garantizar que el método checkQueueState se active cada 5 segundos incluso cuando el servidor esté desconectado. En otras palabras, es probable que no necesite el contenedor para disparar "catch ups" cuando vuelva a poner su servidor en línea.

+0

Muchas gracias, el problema se resolvió cambiando la concurencia a ConcurrencyManagementType.BEAN, y sí, voy a cambiar persistente a falso :) Gracias por su ayuda. – Greg

+1

Buena respuesta, aprendí algo nuevo. ¡Gracias! –

Cuestiones relacionadas