我试图在@Singleton SessionBean - EJB 3.1中获取TransactionManager来控制我的事务范围,因为我必须访问@PostConstruct方法的数据库。如果发生异常,我不能让Container RollBack因为它抛出TransactionRolledbackException:从单例post构造方法中调用setRollbackOnly。
我正在使用JTA DataSource并定义了@TransactionManagement(TransactionManagementType.BEAN)以覆盖对事务的控制。
@Resource private TransactionManager transactionManager;
当我尝试执行“transactionManager.begin();”时,返回给我一个NullPointerException。有谁知道如何解决这个问题?
更新:
我正在使用的代码是:
@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)
{
}
}
}
我认为应该有一个JNDI地址添加@Resource注释,一个特定于WebSphere的注释,但我真的找不到它。
更新:
为什么在容器管理注入上使用JNDI?因为我从直接注入得到一个nullpointer异常,试图像ex一样使用。从OReilly Enterprise Java Beans 3.1第6版开始,第305页。
@Resource(mappedName = "java:/TransactionManager")
//mappedName is vendor-specific, and in this case points to an address in JNDI
尝试了这个没有成功。
更新
WebSphere没有得到我们的bean注释 - 不能真正知道原因 - 所以注释:
@TransactionManagement(TransactionManagementType.BEAN)
无效。因此,编辑了de ejb-jar.xml并添加了以下代码:
<transaction-type>Bean</transaction-type>
并且UserTransaction工作正常。谢谢你的回答。
答案 0 :(得分:2)
如果您拥有Bean托管交易,则不使用javax.transaction.TransactionManager
,而是使用javax.transaction.UserTransaction
。
然后你调用UserTransaction
接口的开始,提交......等。
答案已更新:
1)首先,正如我所说,不要使用TransactionManager
。使用UserTransaction
2)您想了解UserTransaction
对象的 JNDI名称。它是java:comp/UserTransaction
。但是,只有在不管理组件时才需要这样做。 ie: Servlet,EJB。该过程称为手动调用JNDI API
3)提供提交()或回滚()。它们都不存在。
我正在看你的课,似乎没事。
那么,问题出在哪里? (可能性)
1)您的类不被视为EJB(容器管理),这就是注入失败的原因。
2)在EJB @Startup之前未启动事务服务,或者它无法启动。
3)您在 persistence.xml 中配置了 JTA数据源。在这种情况下,请尝试:
@Resource
private EJBContext context;
userTransaction = context.getUserTransaction();
注意:还请提供完整堆栈跟踪和 persistence.xml ,以便查明确切问题。
答案 1 :(得分:1)
您不需要在程序化(BMT)会话bean中使用事务管理器,除非您想在某些情况下挂起()或恢复()关联的事务,而是使用UserTransaction。
但是,您可以使用静态方法getTransactionManager()通过 com.ibm.ws.Transaction.TransactionManagerFactory 类获取对websphere中的事务管理器的引用。 / p>
public TransactionManager getTransactionManager() {
return TransactionManagerFactory.getTransactionManager();
}
答案 2 :(得分:0)
以下是使用UserTransaction正确运行以控制事务的一些示例代码。
@Singleton
@Startup
@TransactionManagement(TransactionManagementType.BEAN)
public class SampleUT {
Logger logger = Logger.getLogger(SampleUT.class.getName());
@Resource
private UserTransaction ut;
@PostConstruct
public void postConstruct()
{
logger.info("PostConstruct called");
try {
ut.begin();
...
您获得的NullPointerException可能与您尝试在EJB的构造函数中使用注入的资源有关。您应该知道注入的引用在EJB的构造函数完成之前永远不可用,因此如果您尝试在构造函数中使用任何注入的引用,它将抛出NullPointerException。