I tried to obtain the TransactionManager in a @Singleton SessionBean - EJB 3.1 - to control the scope of my transaction, because i have to access a database on a @PostConstruct method. If an exception occurrs, I cannot let the Container RollBack because it throws the TransactionRolledbackException: setRollbackOnly called from within a singleton post construct method.
I am using a JTA DataSource and defined the @TransactionManagement(TransactionManagementType.BEAN) to override control of the transaction.
@Resource private TransactionManager transactionManager;
returns to me a NullPointerException when i try to do a "transactionManager.begin();". Does anyone knows how to solve this ?
UPDATE:
the code i am using is this:
@Startup
@Singleton
@TransactionManagement(TransactionManagementType.BEAN)
public class RuntimeContextEJB
{
@EJB
private RepositoryRecursosExternosFactoryEJB repositoryRecursosExternosFactoryEJB;
@EJB
private MetodologiaIndiceLiquidezFactoryEJB metodologiaIndiceLiquidezFactoryEJB;
@EJB
private FuncaoMatematicaFactoryEJB funcaoMatematicaFactoryEJB;
private boolean bootstrapRunning = false;
private List<String> dadosMercadoMonitorados;
@PersistenceContext(unitName = "crv-persistence-unit")
private EntityManager entityManager;
@Resource
private TransactionManager transactionManager;
@PostConstruct
public void init()
{
// comentário
MotorCalculoContext.setupMotorCalculoContext(repositoryRecursosExternosFactoryEJB, metodologiaIndiceLiquidezFactoryEJB,
funcaoMatematicaFactoryEJB);
carregaDadosMercadoMonitorados();
}
public void sinalizarInicioBootstrap()
{
bootstrapRunning = true;
}
public void sinalizarTerminoBootstrap()
{
bootstrapRunning = false;
}
public boolean isBootstrapRunnnig()
{
return bootstrapRunning;
}
public void carregaDadosMercadoMonitorados()
{
try
{
transactionManager.begin();
this.dadosMercadoMonitorados = (List<String>) entityManager
.createQuery(
"SELECT DISTINCT(p.parametro.codigoDadoMercado) FROM PlanoExecucaoPasso p WHERE p.parametro.codigoDadoMercado <> '' AND p.parametro.codigoDadoMercado <> '0'")
.getResultList();
}
catch (Exception e)
{
}
}
}
I think there should be a JNDI adress to add on the @Resource annotation, one that is specific for WebSphere, but i really can't find wich is.
UPDATE:
why use JNDI on a container managed injection ? Since i am getting a nullpointer exception from a direct injection, tried to use like the ex. on page 305 from OReilly Enterprise Java Beans 3.1 6th edition.
@Resource(mappedName = "java:/TransactionManager")
//mappedName is vendor-specific, and in this case points to an address in JNDI
tried this with no success.
UPDATE
WebSphere is not getting our beans annotations - can't really know why - so the annotation:
@TransactionManagement(TransactionManagementType.BEAN)
was not working. So, edited de ejb-jar.xml and added the following code:
<transaction-type>Bean</transaction-type>
and the UserTransaction worked. Thanks for the answers.
When you have bean managed transaction, you don't use javax.transaction.TransactionManager
but instead you use javax.transaction.UserTransaction
.
And then you call begin, commit .... etc of UserTransaction
interface.
Answer Updated:
1) First of all, as I said, don't use TransactionManager
. Use UserTransaction
2) As you wanted to know the JNDI name of the UserTransaction
object. It is java:comp/UserTransaction
. But you need this only when your component is not managed. ie: Servlet, EJB. That process is called making a manual call to JNDI API
3) Provide commit() or rollback(). None of them is present.
I am looking at your class and it seems alright.
So, where is the problem ? (possibilities)
1) Your class is not treated as EJB (container managed) and which is why injection fails.
2) Transaction service is not started before EJB @Startup or it fails to start.
3) You have JTA Datasource configured in your persistence.xml. In which case, try:
@Resource
private EJBContext context;
userTransaction = context.getUserTransaction();
Note: Please also provide full stack trace and persistence.xml in order to pinpoint exact problem.