[RESOLVIDO] Executar tarefa segundo plano, sistema WEb + VRaptor: Quartz ou outra forma?

7 respostas
R

Estamos no desenvolvimento de um sistema WEB utilizando VRaptor + Hibernate.
Neste sistemas temos que gerar alguns relatorios ou arquivos txt, que demandam um certo tempo entre 10 a 40 minutos, dependendo da opção selecionada.
Para isto, estamos querendo fazer que esta tarefa trabalhe em forma de agendamento ou execução em segundo plano.
Exemplo: Usuário seleciona as informações e pede para gerar determinado relatorio. Esta solicitação lança uma requisição, que chamara a classe e metodo correspondete. e grava o mesmo numa pasta determinada na rede. Apos concluido gerá uma informação ao usuário que a solicitação foi concluida.
Qual seria a melhor forma de fazer isto utilizando-se VRaptor. Estamos em duvida como proceder. Seria o quartz?
Alguem poderia nos auxiliar. e dar um “norte” de como fazer, para que possamos seguir em frente.
Obrigado pela ajuda.

7 Respostas

Lucas_Cavalcanti

o quartz é bom quando você precisa executar uma tarefa periódica… se for um trabalho para ser feito uma vez só você pode usar a própria API de concorrência do java com o ExercutorService + runnables

procura por ThreadPoolExecutor e as classes do mesmo pacote

R

Lucas Cavalcanti:
o quartz é bom quando você precisa executar uma tarefa periódica… se for um trabalho para ser feito uma vez só você pode usar a própria API de concorrência do java com o ExercutorService + runnables

procura por ThreadPoolExecutor e as classes do mesmo pacote

Lucas fiz assim no meu SpedController:

@Resource
public class SpedController {

	private final GeradorSpedFiscal geradorSpedFiscal;

	public SpedController(GeradorSpedFiscal geradorSpedFiscal) {
		this.geradorSpedFiscal = geradorSpedFiscal;
	}
	
	public void gerar(){};
	
	public void gerarSped(String sufixoCNPJ, String periodo) {
		try {
			this.geradorSpedFiscal.GerarSped("01/04/2011");
			System.out.println("Teste");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
}

meu metodo geradorSpedFiscal da Classe GeradorSpedFiscal é assim:

public void GerarSped(String dataInicial) throws FileNotFoundException {
		this.periodo = CalculaPeriodo(dataInicial);
		
	    ThreadPoolExecutor tpe = new ThreadPoolExecutor(10, 10, 50000L, TimeUnit.MILLISECONDS,
	            new LinkedBlockingQueue<Runnable>());

	    tpe.execute(this);
	}
e o run...
public void run() {
		try {
			this.executarSPED();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

Ele até chama a execução em segundo plano… mais dentro do this.executarSPED() ele usa session e DAOS. dai ele chama. mas ele finaliza o controller. .dai da erro na execução que esta em segundo plano:

Exception in thread "pool-1-thread-1" org.hibernate.SessionException: Session is closed!
	at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:72)
	at org.hibernate.impl.SessionImpl.getActionQueue(SessionImpl.java:1948)
	at org.hibernate.engine.query.NativeSQLQueryPlan.coordinateSharedCacheCleanup(NativeSQLQueryPlan.java:179)
	at org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:189)
	at org.hibernate.impl.SessionImpl.executeNativeUpdate(SessionImpl.java:1310)
	at org.hibernate.impl.SQLQueryImpl.executeUpdate(SQLQueryImpl.java:396)
	at br.com.diplomata.infra.daos.LivroFiscalDAO.fabricaTemporariaParaAsMensagensDoLivroFiscal(LivroFiscalDAO.java:274)
	at br.com.diplomata.infra.daos.LivroFiscalDAO.CriaTabelasTemporarias(LivroFiscalDAO.java:67)
	at br.com.diplomata.infra.daos.LivroFiscalDAO.selecionaLivroFiscal(LivroFiscalDAO.java:33)
	at br.com.diplomata.sped.fiscal.GeradorSpedFiscal.selecionaInformacoesLivroFiscalParaSped(GeradorSpedFiscal.java:118)
	at br.com.diplomata.sped.fiscal.GeradorSpedFiscal.executarSPED(GeradorSpedFiscal.java:77)
	at br.com.diplomata.sped.fiscal.GeradorSpedFiscal.run(GeradorSpedFiscal.java:130)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)

Como fazer para que ele continue com a session do hibernate. só finalize depois que terminar o “Run()” chamado?

Obrigado

Lucas_Cavalcanti

vc vai precisar gerenciar as Sessions separadamente pra esssas tasks, não pode usar a mesma da requisição, pois não está na mesma thread e pode ser executado em qqer ponto

R

Acabei fazendo o JobScheduler, conforme mostra no vraptor.com.br. Pois tambem teria algumas rotinas que são chamadas em determinados momentos.

Agora uma duvida, posso mostrar o meu Pool de Task, e quais estão sendo executadas.

R

Grande Lucas, acabei mudando e fazendo como havia iniciado com ThreadPoolExecutor… A duvida anterior para saber quanto tem no pool consegui. usando this.executorFactory.getInstance().getTaskCount().

Preciso fazer o seguinte: Mostrar a lista de tarefas que estão no Pool… tem como identifcar uma task e listar.
Exemplo:
SPED 01 - Exec
SPED 02 - Exec
SPED 03 - Wait
SPED 04 - Wait

Minhas Classes são:
FabricadaThreadPool

@Component
@ApplicationScoped
public class FabricaDePoolThreadExecutor implements ComponentFactory<ThreadPoolExecutor>{

	private ThreadPoolExecutor pool;

	@PostConstruct
	public void abre() {
		pool = new ThreadPoolExecutor(10, 10, 50000L, TimeUnit.MILLISECONDS,
				new LinkedBlockingQueue<Runnable>()); 
		
	}
	
	public ThreadPoolExecutor getInstance() {
		return pool;
	}
	
    @PreDestroy
    public void destroy() {
        pool.shutdown();
    }		

}

Interface Tarefa:
public interface Tarefa extends Runnable {
	void execute(ThreadPoolExecutor poolExecutor);
}

@Component
@RequestScoped
public class TarefaGeradorDeSpedFiscal implements Tarefa {

	
	private Session session;
	private String data;

	public void run() {
		this.session = new CriadorDeSessionParaTarefas().getInstance();
		
		GeradorSpedFiscal geradorSpedFiscal = new GeradorSpedFiscal(session,new EmpresaFilialDAO(session),new LivroFiscalDAO(session),new MovimentoGIADAO(session), new CIAPParaSPEDDAO(session));
		try {
			geradorSpedFiscal.GerarSped(this.data);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}			
	}

	public void execute(ThreadPoolExecutor poolExecutor) {
		poolExecutor.execute(this);
	}

	public TarefaGeradorDeSpedFiscal paraData(String data) {
		this.data = data;
		return this;
	}	
}
Lucas_Cavalcanti

bom, vc pode sobrescrever o toString da task e imprimir a lista de tasks que não foram executadas assim (algum dos métodos do pool faz isso)

PS: coloque o código entre e

R

Lucas Cavalcanti:
bom, vc pode sobrescrever o toString da task e imprimir a lista de tasks que não foram executadas assim (algum dos métodos do pool faz isso)

PS: coloque o código entre e

Valeu lucas, e pode deixar que as proximas vão entre e .

Criado 26 de maio de 2011
Ultima resposta 29 de mai. de 2011
Respostas 7
Participantes 2