Serviço de Timer no ejb 3.1 – problema de tempo limite de chamada de programação

Eu criei um exemplo simples com as annotations @Singleton, @Schedule e @Timeout para tentar resolver o problema.

O cenário é o seguinte: o EJB chama a function ‘check’ a cada 5 segundos e, se determinadas condições forem atendidas, ele criará o timer de ação única que invocaria algum processo de execução longa de maneira assíncrona. (é uma espécie de tipo de implementação de fila). Em seguida, ele continua a verificar, mas enquanto o longo processo está lá, ele não iniciará outro.

Abaixo está o código que eu criei, mas esta solução não funciona, porque parece que a chamada assíncrona que estou fazendo está, de fato, bloqueando o meu método @Schedule.

@Singleton @Startup public class GenerationQueue { private Logger logger = Logger.getLogger(GenerationQueue.class.getName()); private List queue = new ArrayList(); 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"); } 

O que estou faltando aqui ou devo tentar abordagem diferente? Qualquer idéias mais bem vindas 🙂

Teste com a última compilation do Glassfish 3.0.1 – esqueci de mencionar

O @ConcurrencyManagement padrão para singletons é ConcurrencyManagementType.CONTAINER com @Lock padrão de LockType.WRITE. Basicamente, isso significa que cada método (incluindo generateReports) é efetivamente marcado com a palavra-chave sincronizada, o que significa que checkQueueState irá bloquear enquanto generateReport estiver sendo executado.

Considere o uso de ConcurrencyManagement (ConcurrencyManagementType.BEAN) ou @Lock (LockType.READ). Se nenhuma sugestão ajudar, suspeito que você encontrou um bug Glassfish.

Como um aparte, você provavelmente deseja persistent = false, já que provavelmente não precisa garantir que o método checkQueueState seja acionado a cada 5 segundos, mesmo quando o servidor estiver offline. Em outras palavras, você provavelmente não precisará do contêiner para triggersr “catch ups” quando voltar seu servidor online.

    Intereting Posts