Execução de método assincrono (sem agendamento de tasks)

119 views
Skip to first unread message

Rafael Viana

unread,
Apr 8, 2016, 5:07:47 PM4/8/16
to caelum-vraptor
Boa Tarde,

Tenho um método no controller que tem um processamento muito demorado, dependendo do tamanho do arquivo pode levar até 40 minutos.
Gostaria de deixar esse método executando no servidor, mas liberar a interface para o usuário (encerrar o request). Já que quando o processamento termina envio um e-mail para o cliente com o resultado do processamento.

Para executar a tarefa assíncrona achei trechos que achei que pudessem ajudar no plugin vraptor-simplemail, que faz o envio de e-mails assincronamente pelo ExecutorService.

Que tem o envio assíncrono através deste código:

Callable<Void> task = new Callable<Void>() {
@Override
public Void call() {
try {
DefaultAsyncMailer.this.mailer.send(email);
} catch (EmailException e) {
LOGGER.error(
"Error while sending async email "
+ email.getSubject() + " to "
+ email.getToAddresses(), e);
}
return null;
}
};
return this.executor.submit(task);

Estou fazendo o envio desta maneira:

Callable<Void> task = new Callable<Void>() {
@Override
public Void call()  {
AtualizarProdutosEPrecosTask atualizarTask = new AtualizarProdutosEPrecosTask(usuarioLogado.getTenantId(), emailDestino, lista);
atualizarTask.run();
return null;
}
};

executorService.submit(task);

Implementei o ExecutorServiceProvider:
@ApplicationScoped
public class ExecutorServiceProvider {

	private ExecutorService pool;

	@PostConstruct
	public void initialize() {
		this.pool = Executors.newCachedThreadPool();
	}

	@Produces
	public ExecutorService getInstance() {
		return this.pool;
	}

	@PreDestroy
	public void close(ExecutorService pool) {
		this.pool.shutdown();
	}

}

Só que a tarefa não é executada. O que estou fazendo de errado? Existe outra maneira de resolver este problema?

Lucas Cavalcanti

unread,
Apr 11, 2016, 7:43:56 AM4/11/16
to caelum-vraptor
this.executor.submit(task) retorna um Future<...>, tenta debugar o retorno desse future, e ver se tá dando alguma exception dentro dele.

--
Você recebeu essa mensagem porque está inscrito no grupo "caelum-vraptor" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para caelum-vrapto...@googlegroups.com.
Para postar nesse grupo, envie um e-mail para caelum-...@googlegroups.com.
Acesse esse grupo em https://groups.google.com/group/caelum-vraptor.
Para mais opções, acesse https://groups.google.com/d/optout.

Rafael Viana

unread,
Apr 13, 2016, 2:46:11 PM4/13/16
to caelum-vraptor
É... realmente tem um erro.

org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped


Essa task usa um DAO, por isso não está funcionando. Se retiro o DAO, ela funciona. Porém, eu preciso deste DAO para o processamento da operação.
Consegui resolver.

O Plugin Vraptor-JPA produz o EntityManager no @RequestScope (boa prática). Para solucionar este caso do DAO em @RequestScope, injetei o EntityManagerFactory (que é @ApplicationScoped) e faço a criação e instanciação dos objetos DAO manualmente.


EntityManager entityManager = factory.createEntityManager();

MeuDAO dao = new MeuDAO(entityManager);


Lembrando que como está fora do contexto da aplicação, o JPATransactionInterpector do VRaptor-JPA plugin não funciona aqui. Por isso, tive que gerenciar o transaction "manualmente" (foi um tempo até achar porque não salvava! haha)


Ficou assim:


//Iniciar transação com o banco de dados manualmente

EntityManager entityManager = factory.createEntityManager();

EntityTransaction entityTransaction = entityManager.getTransaction();

entityTransaction.begin();


... lógica com os dados


//Commit de alterações

if(entityTransaction != null && entityTransaction.isActive()) {

entityTransaction.commit();

}


Acho que agora está tudo ok! Obrigado.


Att,
Reply all
Reply to author
Forward
0 new messages