Criando Cronômetros Usando o Serviço de Cronômetro EJB para Enterprise Beans
É possível usar enterprise beans para obter vantagem do serviço de cronômetro EJB para planejar eventos baseados em tempo.
Sobre Esta Tarefa
No suporte da especificação EJB 3.1, é possível criar cronômetros EJB não persistentes. Esse produto também suporta a API TimerService expandida para a criação de cronômetro programática. Além disso, é possível configurar o contêiner EJB para criar automaticamente um cronômetro quando o aplicativo for iniciado.
O WebSphere Application Server implementa o serviço de cronômetro do Enterprise JavaBeans(EJB). Com base nas necessidades comerciais, é possível usar os cronômetros persistentes ou cronômetros não-persistentes. Cronômetros persistentes são úteis se você estiver criando um cronômetro para um evento baseado em tempo que necessita de garantia da existência do cronômetro além do ciclo de vida do servidor. Cronômetros persistentes iniciados previamente automaticamente iniciam quando o seu servidor inicia e persiste através de encerramentos e reinicializações do servidor. Por exemplo, é possível usar cronômetros persistentes para iniciar um aplicativo de sistema ou enviar uma notificação de status sobre a expiração de um cronômetro. Cronômetros não persistentes são úteis em situações não críticas nas quais as ações do cronômetro são ignoradas ou refeitas sem impactos negativos aos negócios, como a verificação de uma temperatura.
É possível criar cronômetros programaticamente. Também é possível criar cronômetros automaticamente usando a anotação @Schedule na classe de bean ou ao usar o elemento de cronômetro no descritor de implementação ejb-jar.xml. Ao criar automaticamente os cronômetros, poderá planejar um cronômetro sem depender da chamada do enterprise bean ao iniciar programaticamente um método de criação de serviço de cronômetro EJB.
- Cronômetros persistentes
-
Cronômetros persistentes são implementados como uma tarefa de serviço do planejador. Por padrão, uma instância do planejador interna (ou pré-configurada) é usada para gerenciar essas tarefas e elas são persistidas para um banco de dados Apache Derby associado ao processo do servidor.
É possível executar customizações básicas para a instância do planejador interna Para obter informações sobre a customização da instância do planejador, consulte as informações sobre como configurar um serviço de cronômetro.
A criação e o cancelamento de objetos de Cronômetros são transacionais e persistentes. Se um Cronômetro for criado dentro de uma transação e essa transação for revertida mais tarde, a criação do Cronômetro também será revertida. Regras semelhantes aplicam-se ao cancelamento de um Cronômetro. Cronômetros iniciados previamente são mantidos nos encerramentos e reinicializações do servidor.
- Cronômetros não persistentes
-
O EJB 3.1 aumenta o serviço de cronômetro EJB para ativar cronômetros EJB não persistentes, além dos cronômetros persistentes. Cronômetros não persistentes possuem muito da mesma semântica e comportamento dos cronômetros persistentes, mas sem o gasto adicional de um armazenamento de dados. Cronômetros não persistentes possuem um ciclo de vida diferente dos cronômetros persistentes. Quando cronômetros persistentes são mantidos em encerramentos e reinicializações de servidor de aplicativos, os cronômetros não persistentes estão ativos apenas quando o servidor de aplicativos está ativo. Diferentemente dos cronômetros persistentes, não há nenhum comando para localizar ou cancelar cronômetros não persistentes. Cronômetros não persistentes são cancelados quando o servidor de aplicativos é interrompido ou falha em permanecer em um estado ativo.
Assim como com os cronômetros persistentes, a criação e o cancelamento de cronômetros não persistentes são transacionais. Se um cronômetro for criado dentro de uma transação e essa transação for revertida mais tarde, a criação do cronômetro também será revertida. Regras semelhantes aplicam-se ao cancelamento de um cronômetro.
É possível configurar cronômetros não persistentes para compartilhar um conjunto de encadeamentos com cronômetros persistentes, ou ter um único conjunto de encadeamentos que não seja compartilhado com cronômetros persistentes.
- Cronômetros criados programaticamente
-
Um cronômetro persistente criado programaticamente é mantido nos encerramentos e reinicializações do servidor de aplicativos, a menos que seja cancelado. É responsabilidade do código do aplicativo ou do administrador do sistema excluir um cronômetro criado programaticamente que não seja mais desejado.
Para criar programaticamente um cronômetro que esteja associado ao seu enterprise bean, o bean chama o método getTimerService() na instância do contexto aplicável para obter uma referência ao objeto TimerService. O bean também chama um dos métodos TimerService, como createTimer, para especificar o cronômetro para o bean. Essa instância do Cronômetro agora está associada ao seu bean. Os métodos TimerService são descritos na especificação EJB 3.1. Agora é possível passar a instância do Cronômetro para outro código Java™ como um objeto local. Após o código Java obter a instância do Cronômetro, o código pode usar qualquer um dos métodos definidos pela interface javax.ejb.Timer, como os métodos cancel() ou getTimeRemaining().
Em um ambiente em cluster, um cronômetro persistente criado programaticamente pode ser executado em qualquer membro de cluster, mas um cronômetro não persistente criado programaticamente é executado apenas na mesma JVM na qual ele foi criado.
- Cronômetros criados automaticamente
- A especificação EJB 3.1 aumenta o serviço de cronômetro EJB para ativar a criação automática de um cronômetro quando o aplicativo for iniciado sem depender de uma chamada de bean para iniciar programaticamente um dos métodos de criação do cronômetro do serviço de cronômetro. Use a anotação @Schedule ou o elemento do descritor de implementação de método de tempo limite para criar cronômetros automaticamente. Cronômetros criados automaticamente são criados pelo contêiner como um resultado de implementação de aplicativo.
Evitar Problemas: O comando CancelEJBTimers também cancela cronômetros criados automaticamente. Quando cronômetros automaticamente criados são cancelados, a única maneira de recriá-los é desinstalar o aplicativo e reinstalá-los novamente.gotcha
- Cronômetros em um ambiente em cluster
-
Em um ambiente em cluster, um cronômetro persistente é executado apenas em um membro de cluster que pode não necessariamente ser o mesmo membro de cluster no qual ele foi criado. Um cronômetro não persistente executa em cada membro de cluster no qual foi criado - cronômetros não persistentes automáticos executam em cada membro de cluster que contém o EJB.
Cronômetros persistentes automáticos são removidos de seu armazenamento persistente quando seu módulo ou aplicativo de contenção é desinstalado. Portanto, não atualize aplicativos que usam cronômetros persistentes automáticos com o recurso Atualização de Lançamento. Fazer isso, desinstala e reinstala o aplicativo enquanto o cluster ainda está operacional, o que pode causar falha nos seguintes casos:
- Se um cronômetro que executa em outro membro de cluster for ativado após a entrada de banco de dados ser removida e antes que a entrada de banco de dados seja recriada, ele falha. Nesse caso, uma exceção com.ibm.websphere.scheduler.TaskPending é gravada no First Failure Data Capture (FFDC), juntamente com a mensagem SCHD0057W, indicando que as informações da tarefa no banco de dados foi mudada ou cancelada.
- Se o cronômetro for ativado em um membro de cluster que não foi atualizado após os dados do cronômetro no banco de dados terem sido atualizados, então o cronômetro pode falhar ou causar outras falha se as novas informações do cronômetro não forem compatíveis com o antigo código do aplicativo que ainda está executando no membro de cluster.
Quando usar o servidor proxy no produto, não defina um planejador no nível de célula se o planejador estiver configurado para uso para o serviço de cronômetro EJB. Fazer isso impede que cronômetros persistentes sejam executados. Isso pode ocorrer se o servidor proxy obter o lease do planejador. Como nenhum aplicativo é executado no servidor de proxy, não há nenhum código do aplicativo para manipular os eventos de timer que são enviados pelo planejador.
- Novas tentativas e tempos limites ausentes
-
Se usar cronômetros EJB, você deve entender os conceitos de falhar, novas tentativas e tempos limites ausentes.
- Uma falha é uma execução de tempo limite que é tentada, mas não obtém êxito.
- Uma nova tentativa é uma tentativa adicional de executar com êxito um tempo limite que foi previamente tentado, mas falhou.
- Uma execução ausente é um tempo limite que deveria ter sido tentado, mas não foi, porque o servidor estava indisponível ou ocupado tentando novamente um tempo limite que falhou previamente.
O comportamento da nova tentativa reflete:- Número de vezes adicionais que o servidor tentou novamente o tempo limite com falha
- Intervalo entre essas novas tentativas do servidor
O comportamento do tempo limite ausente reflete:- Se o servidor eventualmente tenta tempos limites ausentes, ou não
- Se tempos limites ausentes são tentados eventualmente, quando essas tentativas ocorrem
- Intervalo entre as tentativas de tempo limite ausente
Tabela 1. Comportamento de Nova Tentativa e Tempo Limite Ausente. O comportamento de nova tentativa e tempo limite ausente para ambos os cronômetros, persistentes e não persistentes. Característica Comportamento Padrão Configurável Número de novas tentativas Quantas forem necessárias para obter êxito. Os cronômetros persistentes são desativados temporariamente se seu limite de falha do planejador for atingido em um servidor. Para obter mais informações, consulte o tópico sobre como parar tarefas que estão falhando.
Sim, para cronômetros não persistentes Intervalo entre novas tentativas Primeiro, a nova tentativa é imediata. Novas tentativas subsequentes ocorrem no intervalo de pesquisa do planejador configurado para cronômetros persistentes e no intervalo de nova tentativa configurado para cronômetros não persistentes.
Sim Recuperação de tempo limite ausente Todos os tempos limites ausentes são recuperados. NÃO Quando os tempos limites ausentes são recuperados Ambos os cronômetros, persistentes e não persistentes, recuperam tempos limites ausentes quando as novas tentativas de bloqueio param. Além disso, cronômetros persistentes recuperam tempos limites quando um servidor indisponível reinicia. NÃO Próximo tempo limite, após o êxito das novas tentativas e a recuperação dos tempos limites No próximo tempo originalmente planejado. Não As características configuráveis são configuradas na instância do planejador para cronômetros persistentes e na configuração do cronômetro não persistente para cronômetros não persistentes.
Os cenários a seguir ilustram como o comportamento de nova tentativa e tempo limite ausente influencia os tempos limites para ambos os cronômetros, persistentes e não persistentes.
Cenários de cronômetro persistente:
Um cronômetro persistente é criado e configurado para executar pela primeira vez às 10h00 e, a partir de então, de hora em hora. O planejador que suporta o cronômetro é configurado com um intervalo de pesquisa de 30 segundos.
O cronômetro executa às 10h00 e falha porque um banco de dados está indisponível. Uma nova tentativa do cronômetro é feita imediatamente e, a cada 30 segundos, uma nova tentativa é feita quando o planejador é pesquisado, e continua falhando até 12h30. Nesse momento, uma nova tentativa é bem-sucedida porque o banco de dados agora está on-line novamente e, portanto, o servidor para de tentar novamente a tentativa que falhou previamente.
Agora, o servidor começa a trabalhar por meio dos tempos limites ausentes. Primeiro, ele tenta o tempo limite que deve ter executado às 11h00, que obteve êxito às 12h31. Quando o planejador é pesquisado novamente 30 segundos depois, ele tenta o tempo limite que deve ter executado às 12h00, que obteve êxito às 12h32. O servidor agora é atual e o próximo tempo limite ocorrerá no horário planejado originalmente às 13h, ao contrário de uma hora após o último sucesso, que teria sido às 13h32. Na sequência, o planejamento original é mantido. O planejamento não é atualizado com base no horário do último tempo limite bem-sucedido.
Cenário de cronômetro não persistente:
Um cronômetro não persistente é criado e configurado para executar pela primeira vez às 10h00 e, a partir de então, de hora em hora. Esse cronômetro não persistente está configurado para ter uma contagem de nova tentativa de 5, e um intervalo de nova tentativa de 30 minutos.
O cronômetro executa às 10h00 e falha porque um banco de dados está indisponível. Uma nova tentativa do cronômetro é feita imediatamente e falha novamente. Agora, tendo executado a nova tentativa imediata inicial, o servidor aguarda pelo intervalo de nova tentativa configurado de 30 minutos entre a próxima nova tentativa. As novas tentativas ocorrem às 10h30 e 11h00, e ambas falham. Finalmente, a quarta nova tentativa ocorre às 11h30 e é bem-sucedida porque o banco de dados agora está novamente on-line.
Agora, o servidor começa a trabalhar por meio dos tempos limites ausentes. O tempo limite que foi originalmente planejado para 11h00 é imediatamente executado e obtém êxito às 11h31. O servidor agora é atual e o próximo tempo limite ocorrerá no horário planejado originalmente às 12h, ao contrário de uma hora após o último sucesso, que seria às 12h32.
- Comportamento dos métodos getNextTimeout e getTimeRemaining
-
Para ambos os cronômetros, persistente e não persistente, o método Timer.getNextTimeout retorna um objeto java.util.Date object que indica a próxima vez que o cronômetro está planejado para executar. Ao chamar o método getNextTimeout a partir de um método de retorno de chamada de tempo limite para um intervalo ou cronômetro baseado em calendário, o método retorna o próximo horário planejado; para cronômetros baseados em calendário sem tempos limites futuros, o métodos lança a exceção NoMoreTimeoutsException conforme requerido pela especificação EJB 3.1. Ao chamar o método getNextTimeout a partir de um método de retorno de chamada de tempo limite para um cronômetro de única ação, o método retorna o horário originalmente planejado. Se um método de retorno de chamada de tempo limite falha e novas tentativas estão sendo efetuadas, o método getNextTimeout continua a retornar o horário originalmente planejado como se a execução com falha não tivesse ocorrido. Em todos os casos, o método Timer.getTimeRemaining retorna a diferença em milissegundos entre o valor retornado getNextTimeout e o tempo do sistema atual, que pode resultar em um número negativo, se o tempo de execução planejado estava no passado.
- Comportamento de herança dos cronômetros criados automaticamente
-
Métodos de cronômetro automáticos em uma hierarquia de classes de bean causam a criação de diversos cronômetros. O número de cronômetros associados com um método de cronômetro não é determinado pelo número de ocorrências do método no código de origem. Em vez disso, o número de cronômetros associados com um método de cronômetro é determinado pelo número de beans com visibilidade para esse método. Por exemplo:
@Stateless public class Abean { @Schedule(hour=”1”) public void timerMethod1() @Stateless public class Bbean extends Abean { @Schedule(hour=”2”) public void timerMethod2() @Stateless public class Cbean extends Bbean { @Schedule(hour=”2”) public void timerMethod2()
Na hierarquia de classe de bean anterior, três cronômetros automáticos com método de retorno de chamada Abean.timerMethod1 são criados, um para cada instância de bean com visibilidade para esse método. Um cronômetro com método de retorno de chamada Bbean.timerMethod2 é criado, e como esse método é substituído pelo bean Cbean, apenas um cronômetro com método de retorno de chamada Cbean.timerMethod2 é criado.
No exemplo anterior, quando o bean Abean é processado pelo contêiner, um único cronômetro automático é criado, com método de retorno de chamada Abean.timerMethod1.
Quando o bean Bbean é processado pelo contêiner, um cronômetro automático é criado com método de retorno de chamada Bbean.timerMethod2, e outro cronômetro automático é criado com método de retorno de chamada Abean.timerMethod1.
Quando o bean Cbean é processado pelo contêiner, um cronômetro automático é criado com método de retorno de chamada CBean.timerMethod2. Outro cronômetro automático é criado com método de retorno de chamada Abean.timerMethod1. Um cronômetro para Bbean.timerMethod2 não é criado quando processar o Cbean do bean. Bbean.timerMethod2 não está visível na hierarquia de classes de Cbean porque ele é substituído pelo método Cbean.timerMethod2.
Considere outro exemplo como o exemplo anterior, se a anotação @Stateless foi removida das classes Abean e Bbean, de modo que a classe Cbean seja apenas EJB. Nesse caso, os únicos cronômetros automáticos criados seriam aqueles visíveis para Cbean - um com método de retorno de chamada Abean.timerMethod1, um com método de retorno de chamada Cbean.timerMethod2.
Embora os beans possam compartilhar código idêntico em um método de retorno de chamada de bean herdado, o comportamento de tempo de execução pode ser polimórfico. Por exemplo:
public class Employee { @Schedule(hour=”1”, dayOfMonth=”-1”, info = "payroll timer") public void getSalaryIncrease() { printChecks(salary * rate()); } protected float rate() { return (float)1.01; } } public class Manager extends Employee { protected float rate() { return (float)1.15; } } public class Executive extends Manager { protected float rate() { return (float)1.30; } }
No exemplo anterior, cada instância de bean tem um cronômetro automático com o método de retorno de chamada getSalaryIncrease(). Apesar do mesmo código de retorno de chamada ser compartilhado por cada cronômetro, observe que a taxa usada no cálculo do aumento de salário por cada bean é diferente, devido ao polimorfismo. Isto é, os métodos de retorno de chamada do cronômetro podem ser polimórficos, da mesma forma que quaisquer métodos Java podem ser.
Procedimento
Resultados
Você configurou programaticamente ou automaticamente um cronômetro EJB que seja persistente ou não persistente.