EJB3 + Jpa + Transactions

17 respostas
F

Boa tarde pessoal, salve a sexta feira

Pessoal, estou com um problema com as minhas transactions

Tenho um EJB
EmpresaDao

@Stateless
public class EmpresaDao extends AbstractCrudTrilhaAuditoriaDao<Empresa, EmpresaSearch, Integer> {

	public EmpresaDao() {
		super(Empresa.class);
	}
	
}

a classe abstrata AbstractCrudTrilhaAuditoriaDao, esta criando uma linha de log, em outra entidade do sistema,

Mas estou tentando abrir uma transação nesse caso, pois se der o erro na geração da linha de LOG, deve dar rollback em tudo, ja testei varias solucoes que estao na web e nenhuma funcionou, devo ter esquecido algo

public abstract class AbstractCrudTrilhaAuditoriaDao<T extends AbstractEntity, S extends AbstractSearchEntity, ID extends Serializable>
		extends GenericDao<T, S, ID> {

	public AbstractCrudTrilhaAuditoriaDao(Class<T> clazz) {
		super(clazz);
	}

	@EJB
	private TrilhaAuditoriaDao trilhaAuditoriaDao;

	private static final long serialVersionUID = 1L;

	@Override
	public T save(T entity) throws MetaException {

		try {
			
			TipoOperacaoEnum tipoOperacaoEnum = TipoOperacaoEnum.INCLUSAO;
			if (entity.getId() != null) {
				tipoOperacaoEnum = TipoOperacaoEnum.ALTERACAO;
			}

			T t = super.save(entity);

			TrilhaAuditoria trilhaAuditoria = new TrilhaAuditoria();
			trilhaAuditoria.setDataHoraOpracao(new Date());
			trilhaAuditoria.setNomeTabela(this.getClass().getName());
			trilhaAuditoria.setTipoOperacao(tipoOperacaoEnum);
			trilhaAuditoria.setUsuario((Usuario) UsuarioSession.getInstance().getUsuarioLogado());
			trilhaAuditoria.setNumeroLinhaTabela(t.getId());
			trilhaAuditoriaDao.save(trilhaAuditoria);

			return t;
		} catch (Exception e) {
			throw new RuntimeException("erro");
		}
	}

	@Override
	public void delete(T t) throws MetaException {
		Integer id = t.getId();
		super.delete(t);

		TrilhaAuditoria trilhaAuditoria = new TrilhaAuditoria();
		trilhaAuditoria.setDataHoraOpracao(new Date());
		trilhaAuditoria.setNomeTabela(this.getClass().getName());
		trilhaAuditoria.setTipoOperacao(TipoOperacaoEnum.EXCLUSAO);
		trilhaAuditoria.setUsuario((Usuario) UsuarioSession.getInstance().getUsuarioLogado());
		trilhaAuditoria.setNumeroLinhaTabela(id);

		trilhaAuditoriaDao.save(trilhaAuditoria);
	}
}

Assim, como coloquei, nao possui nenhum dos meus testes, se alguem ajudar, ja utilizei tudo que eh maneira de anotar, como vcs estao utilizando?

17 Respostas

H

super.save fazer o que?

Você ta querendo que tudo dê rollback né?

F

Isso quero dar rollback em tudo, segue a outra classe

public abstract class GenericBasicDao<T extends AbstractEntity, ID extends Serializable> extends GenericListDao<T, ID> {

	private static final long serialVersionUID = 1L;

	public GenericBasicDao(Class<T> clazz) {
		this.setEntityClass(clazz);
	}

	public void delete(ID id) throws MetaException {
		delete(this.getEntityManager().getReference(this.getEntityClass(), id));
	}

	public void delete(T[] selectedItems) throws MetaException {
		for (T t : selectedItems) {
			delete(this.getEntityManager().getReference(this.getEntityClass(), t.getId()));
		}
	}

	public void delete(T t) throws MetaException {
		try {
			this.getEntityManager().remove(t);
		} catch (Exception ex) {
			if (ex.getCause() instanceof ConstraintViolationException) {
				throw new ConstraintException(ex, "erro de contraint violada");
			}
			throw new MetaException(ex, "Erro ao excluir");
		}
	}
	public T save(T entity) throws MetaException {
		try {
			
			triggerPreSave(entity);

			entity = this.getEntityManager().merge(entity);

			triggerPreSave(entity);
			return entity;
		} catch (Exception ex) {
			if (ex.getCause() instanceof ConstraintViolationException) {
				throw new ConstraintException(ex, "erro de contraint violada");
			}
			throw new MetaException(ex, "erro ao salvar");
		}
	}
}
H

A classe AbstractCrudTrilhaAuditoriaDao é um EJB também?

O que o método triggerPreSave(entity); faz?

F

Hebert Coelho:
A classe AbstractCrudTrilhaAuditoriaDao é um EJB também?

O que o método triggerPreSave(entity); faz?

Nao, ela nao é um EJB, ela é uma classe abstrata igual a GenericBasicDao, os metodos que iniciam com trigger, estao vazios, eu ia fazer um teste, e acabei ainda nao tirando a chamada do metodo, ignore ele

H

felipef:
Hebert Coelho:
A classe AbstractCrudTrilhaAuditoriaDao é um EJB também?

O que o método triggerPreSave(entity); faz?

Nao, ela nao é um EJB, ela é uma classe abstrata igual a GenericBasicDao, os metodos que iniciam com trigger, estao vazios, eu ia fazer um teste, e acabei ainda nao tirando a chamada do metodo, ignore ele

Para funcionar, essa classe deve ser um EJB, assim todas as classes irão usar a mesma transação or default.

Caso você não queria que ela seja um EJB, você precisaria utilizar a transação na mão com UsertTransaction.

F

Hebert Coelho:
felipef:
Hebert Coelho:
A classe AbstractCrudTrilhaAuditoriaDao é um EJB também?

O que o método triggerPreSave(entity); faz?

Nao, ela nao é um EJB, ela é uma classe abstrata igual a GenericBasicDao, os metodos que iniciam com trigger, estao vazios, eu ia fazer um teste, e acabei ainda nao tirando a chamada do metodo, ignore ele

Para funcionar, essa classe deve ser um EJB, assim todas as classes irão usar a mesma transação or default.

Caso você não queria que ela seja um EJB, você precisaria utilizar a transação na mão com UsertTransaction.

É Hebert ate ja tinha testado dessa maneira

@TransactionManagement(TransactionManagementType.BEAN)
public abstract class AbstractCrudTrilhaAuditoriaDao<T extends AbstractEntity, S extends AbstractSearchEntity, ID extends Serializable>
		extends GenericDao<T, S, ID> {

	@Resource
	private EJBContext context;

	public AbstractCrudTrilhaAuditoriaDao(Class<T> clazz) {
		super(clazz);
	}

	@EJB
	private TrilhaAuditoriaDao trilhaAuditoriaDao;

	private static final long serialVersionUID = 1L;

	@Override
	public T save(T entity) throws MetaException {

		UserTransaction utx = context.getUserTransaction();

		try {
			utx.begin();

			TipoOperacaoEnum tipoOperacaoEnum = TipoOperacaoEnum.INCLUSAO;
			if (entity.getId() != null) {
				tipoOperacaoEnum = TipoOperacaoEnum.ALTERACAO;
			}

			T t = super.save(entity);

			TrilhaAuditoria trilhaAuditoria = new TrilhaAuditoria();
			trilhaAuditoria.setDataHoraOpracao(new Date());
			trilhaAuditoria.setNomeTabela(this.getClass().getName());
			trilhaAuditoria.setTipoOperacao(tipoOperacaoEnum);
			trilhaAuditoria.setUsuario((Usuario) UsuarioSession.getInstance().getUsuarioLogado());
			trilhaAuditoria.setNumeroLinhaTabela(t.getId());
			trilhaAuditoriaDao.save(trilhaAuditoria);

			utx.commit();
			
			return t;
		} catch (Throwable t) {
			try {
				utx.rollback();
			} catch (Exception e) {
				throw new MetaException(e, t.getMessage());
			} 
		}
		return null;
	}

	@Override
	public void delete(T t) throws MetaException {
		Integer id = t.getId();
		super.delete(t);

		TrilhaAuditoria trilhaAuditoria = new TrilhaAuditoria();
		trilhaAuditoria.setDataHoraOpracao(new Date());
		trilhaAuditoria.setNomeTabela(this.getClass().getName());
		trilhaAuditoria.setTipoOperacao(TipoOperacaoEnum.EXCLUSAO);
		trilhaAuditoria.setUsuario((Usuario) UsuarioSession.getInstance().getUsuarioLogado());
		trilhaAuditoria.setNumeroLinhaTabela(id);

		trilhaAuditoriaDao.save(trilhaAuditoria);
	}
}

Só que no momento que executo a linha

Seguinte exception é lançada

Caused by: java.lang.IllegalStateException: JBAS014308: EJB 3.1 FR 4.3.3 & 5.4.5 Only beans with bean-managed transaction demarcation can use this method. at org.jboss.as.ejb3.component.EJBComponent.getUserTransaction(EJBComponent.java:325) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final] at org.jboss.as.ejb3.context.SessionContextImpl.getUserTransaction(SessionContextImpl.java:119) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final] at br.com.auttar.model.dao.util.AbstractCrudTrilhaAuditoriaDao.save(AbstractCrudTrilhaAuditoriaDao.java:43) [SceWebEJB.jar:]

H

É possível utilizar @TransactionManagement(TransactionManagementType.BEAN) em uma classe que não seja EJB (EJB ou MDB)?

F

Cara, sinceramente nao tenho certeza, mas eu acho q não, mas eu tambem não sei onde colocar

H

Cara, sinceramente nao tenho certeza, mas eu acho q não, mas eu tambem não sei onde colocarEm um EJB.

F

Bom, dai eu fiz o seguinte

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class EmpresaDao extends AbstractCrudTrilhaAuditoriaDao<Empresa, EmpresaSearch, Integer> {

	public EmpresaDao() {
		super(Empresa.class);
	}
}

E no AbstractCrudTrilhaAuditoriaDao.save, deixei como estava, mas ai ele grava, e nao da rollback

H

felipef:
Bom, dai eu fiz o seguinte

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class EmpresaDao extends AbstractCrudTrilhaAuditoriaDao<Empresa, EmpresaSearch, Integer> {

	public EmpresaDao() {
		super(Empresa.class);
	}
}

E no AbstractCrudTrilhaAuditoriaDao.save, deixei como estava, mas ai ele grava, e nao da rollback

Ele chamou o método que dá rollback?

F

Eu tinha trocado utx.rollback(); por utx.setRollbackOnly()

E ai nao tinha funcionado, entao voltei para soh o metodo rollback, e funcionou, pelo menos eu acho q sim, ehhhe, vou fazer mais uns testes, mas agora acho q ta resolvido,

Valeu Hebert, por mais uma vez me ajudar

H

felipef:
Eu tinha trocado utx.rollback(); por utx.setRollbackOnly()

E ai nao tinha funcionado, entao voltei para soh o metodo rollback, e funcionou, pelo menos eu acho q sim, ehhhe, vou fazer mais uns testes, mas agora acho q ta resolvido,

Valeu Hebert, por mais uma vez me ajudar

Precisando é só postar. [=

C

@felipef,

poderia colocar o código fonte da classe “TrilhaAuditoriaDao” e em qual App Server está rodando a aplicação ?

[]'s

F

chienh:
@felipef,

poderia colocar o código fonte da classe “TrilhaAuditoriaDao” e em qual App Server está rodando a aplicação ?

[]'s


mas ele eh um EJB igual ao ProgramaDao

Obrigado, mas ja foi resolvido conforme descrito acima, obrigado

F

Hebert Coelho:
felipef:
Eu tinha trocado utx.rollback(); por utx.setRollbackOnly()

E ai nao tinha funcionado, entao voltei para soh o metodo rollback, e funcionou, pelo menos eu acho q sim, ehhhe, vou fazer mais uns testes, mas agora acho q ta resolvido,

Valeu Hebert, por mais uma vez me ajudar

Precisando é só postar. [=

Opa cara, lembra que ia fazer um teste, nao sei pq aquela hora funcionou, pq agora nao ta mais rolando, ficou assim

persistence.xml

<persistence-unit name="pu" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
package br.com.auttar.model.dao;

import java.util.List;

import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;

import br.com.auttar.model.dao.util.AbstractCrudTrilhaAuditoriaDao;
import br.com.auttar.model.entities.Programa;
import br.com.auttar.model.search.ProgramaSearch;
import br.com.meta.commons.exception.MetaException;
import br.com.meta.commons.util.QueryUtil;

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class ProgramaDao extends AbstractCrudTrilhaAuditoriaDao<Programa, ProgramaSearch, Integer> {

	public ProgramaDao() {
		super(Programa.class);
	}

	private static final long serialVersionUID = 1L;

	@PersistenceContext(unitName = "pu", type=PersistenceContextType.TRANSACTION)
	private EntityManager em;
....
@Stateless 
@TransactionManagement(TransactionManagementType.BEAN)
public class TrilhaAuditoriaDao extends GenericDao<TrilhaAuditoria, TrilhaAuditoriaSearch, Integer> {

	public TrilhaAuditoriaDao() {
		super(TrilhaAuditoria.class);
	}
public abstract class AbstractCrudTrilhaAuditoriaDao<T extends AbstractEntity<ID>, S extends AbstractSearchEntity, ID extends Serializable>
		extends GenericDao<T, S, ID> {

	public AbstractCrudTrilhaAuditoriaDao(Class<T> clazz) {
		super(clazz);
	}

	@Resource
	private EJBContext context;
	
	@EJB
	private TrilhaAuditoriaDao trilhaAuditoriaDao;

	private static final long serialVersionUID = 1L;

	@Override
	public T save(T entity) throws MetaException {

		UserTransaction utx = context.getUserTransaction();
		try {
			utx.begin();

			TipoOperacaoEnum tipoOperacaoEnum = TipoOperacaoEnum.INCLUSAO;
			if (entity.getId() != null) {
				tipoOperacaoEnum = TipoOperacaoEnum.ALTERACAO;
			}

			T t = super.save(entity);

			TrilhaAuditoria trilhaAuditoria = new TrilhaAuditoria();
			trilhaAuditoria.setDataHoraOpracao(new Date());
			trilhaAuditoria.setNomeTabela(t.getClass().getName());
			trilhaAuditoria.setTipoOperacao(tipoOperacaoEnum);
			trilhaAuditoria.setUsuario((Usuario) UsuarioSession.getInstance().getUsuarioLogado());
			trilhaAuditoria.setEmpresa((Empresa)SessionUtil.getParam(UsuarioSession.EMPRESA_LOGADA));
			trilhaAuditoria.setNumeroLinhaTabela((Integer) t.getId());
			trilhaAuditoriaDao.save(trilhaAuditoria);
			utx.commit();
			return t;
		} catch (Exception t) {
			try {
				utx.rollback();
			} catch (Exception e) {
				throw new MetaException(e, e.getMessage());
			}
			throw new MetaException(t, t.getMessage());
		}
	}
....

Tu acha que estou fazendo algo errado?

F

Sera que não é por causa do Sql Server???

Criado 30 de novembro de 2012
Ultima resposta 7 de dez. de 2012
Respostas 17
Participantes 3