Muito obrigado pelo ajuda galera.
Nao tive tempo nenhum de fazer alguns testes depois que postei essa mensagem, entao hoje que tive um tempinho acho que entendi o problema.
Fiz alguns testes com esse codigo, um pouco adaptado.
Interfaces:
package test;
import javax.ejb.Remote;
@Remote
public interface TestTransactionRemote {
public static final String NEW_STATE = "New";
public Test metodo1();
public Test metodo2();
public Test metodo3();
//public Test metodo4();
public Test metodo5();
public Test metodo6();
}
package test;
import javax.ejb.Local;
@Local
public interface TestTransactionLocal {
public static final String NEW_STATE = "New";
public Test metodo1();
public Test metodo2();
public Test metodo3();
//public Test metodo4();
public Test metodo5();
public Test metodo6();
}
Implementaçao:
package test;
import javax.annotation.Resource;
// import javax.ejb.EJB;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.jboss.logging.Logger;
/**
-
Session Bean implementation class TestTransaction
*/
@Stateless
public class TestTransaction implements TestTransactionRemote, TestTransactionLocal {
@Resource
private SessionContext context;
@PersistenceContext(unitName=“TestTransaction”)
EntityManager entityManager;
Logger log = Logger.getLogger(getClass());
//@EJB
//private TestTransactionLocal selfRefr;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Test metodo1() {
Test test = metodo6();
return test;
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Test metodo2() {
Test test = metodo6();
context.setRollbackOnly();
return test;
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Test metodo3() {
Test test = ((TestTransactionRemote) this).metodo6();
context.setRollbackOnly();
return test;
}
//@TransactionAttribute(TransactionAttributeType.REQUIRED)
//public Test metodo4() {
//Test test = selfRefr.metodo6();
<a href="//context.setRollbackOnly">//context.setRollbackOnly</a>();
//return test;
//}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Test metodo5() {
TestTransactionLocal selfRefr = (TestTransactionLocal) context.lookup(“TestTransaction/local”);
Test test = selfRefr.metodo6();
context.setRollbackOnly();
return test;
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public Test metodo6() {
Test test = new Test(TestTransactionRemote.NEW_STATE);
entityManager.persist(test);
return test;
}
}
Resultados:
Metodo 1: Grava a instancia no banco sem problemas.
Olhando o stack trace metodo 1 é chamado por um proxy (EJB Object) que abre a transaçao
(sempre vai abrir uma transaçao pois nao estou abrindo nenhuma no cliente), acontece uma chamada normal e nenhuma transaçao é aberta em metodo6.
Metodo 2: Acontece o mesmo de metodo1, mas como forço um rollback a instancia nao é gravada no banco.
Metodo 3: Tentei castear para interface sem sucesso. Ocorre exatemente o caso de metodo 2.
Metodo 4: Tentei usar DI. O container nao conseguiu fazer o deployment. Basicamente o container tenta injetar a dependencia, como é uma referencia ao proprio
componente e o componente nao esta em estado “Configured” o container aborta.
Metodo 5: Grava a instancia no banco sem problemas. Basicamente fez uma chamada JNDI. Comportamento igual ao metodo 1 só que se abre outro proxy antes da chamada ao metodo6
Conclusao: Nao sei o que a galera opina. A ultima soluçao poderia ser melhorada utilizando um service locator, mas isso penso é um retrocesso ja que DI é uma realidade.
Nao sei se tem muito sentido chamadas(dentro de um mesmo EJB) com serviços fornecidos pelo container. Falo de uma maneira arquitetural. Como nao tenho experiencia com EJBS, nao sei se na vida real existem arquiteturas que funcionem assim.
Bom de qualquer modo, agradeço a galera pela ajuda.