Vraptor e thread + JPA [RESOLVIDO]

Boa tarde, eu ejeto automáticamente o EntityManger com o vraptor:

	private final EntityManagerFactory factory;
	private EntityManager manager;

	public CriadorDeEntityManager(EntityManagerFactory factory) {
		this.factory = factory;
	}

	@PostConstruct
	public void abre() {
		this.manager = factory.createEntityManager();
	}

	public EntityManager getInstance() {
		return this.manager;
	}

	@PreDestroy
	public void fecha() {
		this.manager.close();
	}

e eu preciso fazer uma thread para executar em um determinhado horário, que vai chamar uma função no banco:

porém quando eu chamo ele diz que esta fechado, porque o vraptor abre e fecha automático.

a pergunta é como eu faço para resolver isso?

public void teste(){
		repositoryCliente.atualizaCliente();
	}
	
	public class VerificaSituacaoCliente extends Thread{
		public void run() {
			
			while (true) {
				LocalDateTime agora = new LocalDateTime();
				if (agora.getHourOfDay() == 16) {
					teste();
				}
				try {
					Integer tempoMill = 50 * 60000;
					Thread.sleep(tempoMill);
				} catch (Exception e) {
					IndexController.logger
							.warn(MessageException.persistenceException
									+ e.getMessage() + "), <b>Causa: </b> "
									+ e.getCause());
				}
			}
		}
	}


......


public void atualizaCliente() {
		
		String hql = " select coliseusys.bloqueia_cliente_data()";
		//String hql = " from Cliente";
		//manager = fac
		//manager.getTransaction().begin();
		try {
			Query query = manager.createQuery(hql);
			//query.executeUpdate();
			//manager.getTransaction().commit();
			query.getResultList();
			//manager.close();
		} catch (PersistenceException e) {
			IndexController.logger.warn(MessageException.persistenceException
					+ e.getMessage() + "), <b>Causa: </b> " + e.getCause());
		}
		
	}

Obrigado!

o melhor é essa task receber um entityManagerFactory e abrir e fechar o entityManager e as transações quando for apropriado.

Ok!, eu faço isso para criar a fábrica, como eu faço para passar essa factory para o meu metodo;


@Component
public class CriadorDeEntityManager implements ComponentFactory<EntityManager> {

	private final EntityManagerFactory factory;
	private EntityManager manager;

	public CriadorDeEntityManager(EntityManagerFactory factory) {
		this.factory = factory;
	}

	@PostConstruct
	public void abre() {
		this.manager = factory.createEntityManager();
	}

	public EntityManager getInstance() {
		return this.manager;
	}

	@PreDestroy
	public void fecha() {
		this.manager.close();
	}

}

eu tentei fazer isso: é assim:

public class VerificaSituacaoCliente extends Thread{
	
	CriadorDeEntityManagerFactory factoryMng;		
	
	EntityManagerFactory factory = factoryMng.getInstance();
	
	EntityManager manager = factory.createEntityManager();
	public void run() {
		
		while (true) {
			LocalDateTime agora = new LocalDateTime();
			if (agora.getHourOfDay() == 17) {
				System.out.println("teste");
				String hql = " select coliseusys.bloqueia_cliente_data()";
				
				manager.getTransaction().begin();
				try {
					Query query = manager.createQuery(hql);
					query.getResultList();
					manager.close();
				} catch (PersistenceException e) {
					IndexController.logger.warn(MessageException.persistenceException
							+ e.getMessage() + "), <b>Causa: </b> " + e.getCause());
				}
			}
			try {
				Integer tempoMill = 50 * 60000;
				Thread.sleep(tempoMill);
			} catch (Exception e) {
				IndexController.logger
						.warn(MessageException.persistenceException
								+ e.getMessage() + "), <b>Causa: </b> "
								+ e.getCause());
			}
		}
	}
}

e o que acontece?

Da nulo.


java.lang.NullPointerException
	br.com.coliseu.thread.VerificaSituacaoCliente.<init>(VerificaSituacaoCliente.java:20)
	br.com.coliseu.controller.IndexController.index(IndexController.java:31)

provavelmente é pq ninguém preenche esse objeto:

CriadorDeEntityManagerFactory factoryMng;  

eu tenho essa classe:

package br.com.coliseu.resources;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.ComponentFactory;

@Component
@ApplicationScoped
public class CriadorDeEntityManagerFactory implements
		ComponentFactory<EntityManagerFactory> {

	private EntityManagerFactory factory;
	/**
	 * A variavel boolean verificaStatusCliente, foi colocado no CriadorDeEntityManagerFactory,
	 * porque deve ser armazenada quando o servidor e reincioado, e utilizada para a execucao da thread
	 * que verifica a data de vencimento do cliente.
	 * */
	public static boolean verificaStatusCliente;

	@PostConstruct
	public void abre() {
		factory = Persistence.createEntityManagerFactory("Coliseu");
	}

	public EntityManagerFactory getInstance() {
		return factory;
	}

	@PreDestroy
	public void fecha() {
		this.factory.close();
	}

}

que é o VRaptor que instancia… mas a sua classe que estende Thread é você mesmo que instancia, então vc deveria passar pra ela um EntityManagerFactory no construtor (e vc pode receber esse EntityManagerFactory no construtor da classe que instancia a thread).

eu fiz isso:

	private final EntityManagerFactory factory;
	
	
	public IndexController(EntityManagerFactory factory) {
		this.factory = factory;
	}

	@Restrito
	@Get
	@Path("/")
	public void index() {
		if(!CriadorDeEntityManagerFactory.verificaStatusCliente){
			CriadorDeEntityManagerFactory.verificaStatusCliente = true;
			VerificaSituacaoCliente verifica = new VerificaSituacaoCliente(factory);
			verifica.start();
		}
	}

public class VerificaSituacaoCliente extends Thread{
	
	private EntityManagerFactory factory;
	
	//CriadorDeEntityManagerFactory factoryMng;	
	
	
	
	//EntityManagerFactory factory = Persistence.createEntityManagerFactory("Coliseu");
	
	
	public VerificaSituacaoCliente(EntityManagerFactory factory) {		
		this.factory = factory;
	}
	
	EntityManager manager = factory.createEntityManager();
	public void run() {
		
		while (true) {
			LocalDateTime agora = new LocalDateTime();
			if (agora.getHourOfDay() == 17) {
				System.out.println("teste");
				String hql = " select coliseusys.bloqueia_cliente_data()";
				
				manager.getTransaction().begin();
				try {
					Query query = manager.createQuery(hql);
					query.getResultList();
					manager.close();
				} catch (PersistenceException e) {
					IndexController.logger.warn(MessageException.persistenceException
							+ e.getMessage() + "), <b>Causa: </b> " + e.getCause());
				}
			}
			try {
				Integer tempoMill = 50 * 60000;
				Thread.sleep(tempoMill);
			} catch (Exception e) {
				IndexController.logger
						.warn(MessageException.persistenceException
								+ e.getMessage() + "), <b>Causa: </b> "
								+ e.getCause());
			}
		}
	}
}

e deu null ainda.

essa linha:

EntityManager manager = factory.createEntityManager();  

tem que estar dentro do construtor… do jeito que está ela roda antes do construtor, portanto factory tá null.

Deu certo valeu Lucas.