JobMonitor: mudanças entre as edições
Linha 87: | Linha 87: | ||
// Código para lêr o conteúdo do JobStatus e atualizar qualquer sistema | // Código para lêr o conteúdo do JobStatus e atualizar qualquer sistema | ||
// Abaixo um código exemplo para atualizar o conteúdo da tela do Vaadin. É necessário obter a UI do usuário e criar uma classe de acesso primeiro | // Abaixo um código exemplo para atualizar o conteúdo da tela do Vaadin. | ||
// É necessário obter a UI do usuário e criar uma classe de acesso primeiro | |||
ui.access(new Runnable() { | ui.access(new Runnable() { | ||
@Override | @Override | ||
Linha 106: | Linha 107: | ||
Caso esse método não seja chamado, no momento em que este documento é escrito, o JobMonitor tem um tempo limite de 6h para manter o Job em memória desde o momento em que a instância do Job é criado. Quando o job é removido de forma forçada, um logImprovement() é chamado com o título do Job. | Caso esse método não seja chamado, no momento em que este documento é escrito, o JobMonitor tem um tempo limite de 6h para manter o Job em memória desde o momento em que a instância do Job é criado. Quando o job é removido de forma forçada, um logImprovement() é chamado com o título do Job. | ||
= Job & SessionManager = | = Job & SessionManager = |
Edição das 14h23min de 30 de outubro de 2020
O JobMonitor é o serviço do BISFW que permite que tarefas sejam executar em uma Thread paralela para que a thread principal não fique bloqueada esperando. Esse recurso é extremamente útil para tarefas demoradas, uma vez que permite retornar status sobre a execução da tarefa enquanto ela acontece, mesmo que seja pela interface WEB.
Criando o Job em Segundo Plano
Para colocar uma tarefa em background basta implementar a classe Job e iniciar a execução dentro do método runJob().
![]() |
Exemplo Tarefa em Execução em Background
Job job = new Job("Título da Tarefa") { //O título da tarefa é colocado no título da thread, o que ajuda no DEV.
@Override
public Object runJob(Job job, JobStatus jobStatus) throws Throwable {
//Código para execução da tarefa...
}
@Override
public void jobFinished(Job job, JobStatus jobStatus) {
// Quando a tarefa é finalizada, o serviço JobMonitor chama este método para notificar
}
};
job.start(); //inicia a tarefa
|
Quando a tarefa finalizar o JobMonitor chama o método jobFinished() para notificar o fim da execução da tarefa. Embora não faça muito sentido quando implementado como no modelo acima (em innerclasses) o método jobFinished() tem maior utilidade para implementações mais genéricas da interface.
Ambos os métodos recebem dois parâmetros:
- job - referência da própria instância do Job criado.
- jobStatus - Instância do objeto de status do job. Dentro desse objeto a tarefa deve atualizar as propriedades como "mensagens", percentual de tarefa realizada, etc..
![]() |
|
Interrompendo o Job
O cancelamento do Job em segundo plano pode ser solicitado pelo usuário. Para que isso ocorra a interface deve chamar o método interrupt() do JobStatus. Ao chamar esse método o JobStatus ficará marcado que a tarefa obteve a solicitação de cancelamento de sua execução.
Note que depende do Job Implementado verificar se essa solicitação foi realizada e parar a execução da tarefa tomando as providências necessárias (como dar rollback em tarefas pela metade ou concluí-las e cancelar depois, etc.). Há duas maneiras do Job verificar esse cancelamento:
- Verificação Manual - Na verificação manual o desenvolvedor pode utilizar o método getInterruptResquested() e obter o valor do atributo. Caso true, indica que a solicitação de cancelamento foi realizada e deste ponto em diante direcionar o método para os procedimentos de cancelamento, e lançar a exception.
- Recomendado lançar a exception:
throw new BISValidationException("FW_ERROR_000004");
Este Código de exception é utilizado para identificar que a operação foi cancelada pelo usuário.
- Recomendado lançar a exception:
- Verificação Automática - Neste modo basta o desenvolvedor incluir a chamada do método checkInterrupt() do JonMonitor. Este método verifica o status do atributo e se tiver em true já lança a exception como citada acima (Validation com o código 'FW_ERROR_000004'). Só é preciso tomar cuidado para que o próprio código do Job não trate a exception e deixe que ela vaze para fora do método do Job.
- Note que neste método a exception é lançada diretamente, assim, o método que verifica o status deve ser bem posicionado. Ou realizar as tratativas no catch/finally.
JobMonitor
O JobMonitor é uma classe estática que controla e mantém todos os Jobs do Sistema. Ao criar uma instância de Job ele automaticamente se registra no JobMonitor. Mesmo antes de iniciar a tarefa o JobMonitor já tem a referência da classe e monitora seu status.
Quando o Job é criado, ela cria também sua classe JobStatus, e dentro dela é possível encontrar seu identificador único (UUID). Com este UUID é possível solicitar informações do Job no JobMonitor. Assim, caso o JobMonitor esteja sendo executado em uma VM e o objeto que queira saber o status esteja em outra, ele pode solicitar o objeto JobStatus utilizando dessa UUID. Exemplo:
![]() |
Exemplo Tarefa em Execução em Background
//Implementação do Job
Job job = new Job("Título da Tarefa") { ... };
//Recuepra o objeto que mantém o status de progresso diretamente da tarefa
JobStatus status = job.getStatus();
//Obtemos e salvamos para referência futura o UUID do Job
String uuid = status.getUuid();
//Obtendo o JobStatus a partir do JobMonitor com o UUID do job.
JobStatus status2 = JobMonitor.getJobStatus(uuid);
|
Note que no exemplo acima o start() do job pode ser dado a qualquer momento. O job não precisa estar sendo executado para que todo o restante funcione. Porém normalmete o job já é inicializado assim que que a instância é criada.
![]() |
|
JobChecker
JobChecker é a implementação de uma Thread que verifica periodicamente a tarefa sem segundo plano e notifica conforme atualização do objeto de status.
Para criar o JobChecker basta passar o UUID do job na sua construção:
![]() |
JobChecker verificando o progresso da tarefa
JobChecker jobChecker = new JobChecker(uuid, true) {
@Override
public void updateStatus(JobStatus jobStatus) {
// Código para lêr o conteúdo do JobStatus e atualizar qualquer sistema
// Abaixo um código exemplo para atualizar o conteúdo da tela do Vaadin.
// É necessário obter a UI do usuário e criar uma classe de acesso primeiro
ui.access(new Runnable() {
@Override
public void run() {
// Código do Vaadin para atualizar a UI do usuário
}
});
}
};
|
Note que no construtor foi passado além da UUID um booleano 'true'. Esse boleano indica se quando o JobChecker detectar que a tarefa finalizou ele mesmo se encarrega de avisar o JobMonitor que ele pode descartar a tarefa e seu status.
Isso é importante porque mesmo que o Job termine, o JobMonitor não sabe até quando deve guardar a referência do JobStatus para ser consultado, assim é importante que o descarte seja autorizado para economizar recursos.
Para forçar esse descarte manualmente, caso não se use o JobChecker ou se passe o atributo como false, deve ser chamado o método:
JobMonitor.cleanJob(uuid);
Caso esse método não seja chamado, no momento em que este documento é escrito, o JobMonitor tem um tempo limite de 6h para manter o Job em memória desde o momento em que a instância do Job é criado. Quando o job é removido de forma forçada, um logImprovement() é chamado com o título do Job.
Job & SessionManager
Ao criar um novo objeto Job, ele mesmo tenta detectar se estamos em um ambiente com uma Session associada a Thread atual. Se encontrar ele automaticamente transfere a sessão de autenticação atual para a nova Thread do Job. A vantagem dessa operação é que o método SessionManager.getSession() passará a funcionar dentro do método run() do Job, bem como permitirá que outros serviços como FWLogger encontre a sessão do usuário.
![]() |
|