UserTransaction中的begin()抛出空指针异常

时间:2015-08-18 14:31:45

标签: multithreading java-ee ejb websphere jta

Java中存在一个代码块(一个循环),它使用UserTransaction来处理事务。 userTransaction对象在循环之前声明,该对象声明为

private javax.ejb.SessionContext mySessionCtx;
UserTransaction utx=mySessionCtx.getUserTransaction();

现在我已经在" MultiThreading"中实现了特定的代码块(循环)。我已经从启动线程的类传递了对象utx到我创建的线程中的UserTransaction对象(因为启动线程的类实现了javax.ejb.SessionBean并且这个类是通过EJB调用。)

此功能在Windows机器上运行得非常好。但是当部署在Linux服务器中时,它无法正常工作。

在Linux服务器中,在实现线程之前,语句utx.begin()运行良好。但是在实现线程后,utx.begin()会抛出NullPointerException。对象utx具有值。它是begin()语句,它抛出异常。

这个UserTransaction在Windows和Linux服务器中的行为是否不同?它取决于任何其他因素吗?它可能是什么原因使它在Windows服务器中正常工作并在Linux服务器中抛出异常?

P.S:我正在研究Java Struts 1.2。并使用IBM WebSphere

2 个答案:

答案 0 :(得分:3)

EJB UserTransaction对象只能在EJB的范围内工作。如果将对象传递给另一个线程,它将无法工作,如果将UserTransaction从EJB方法返回到servlet,它将无法工作。在更高版本的产品中,NullPointerException被IllegalStateException取代。

Java EE不支持创建自己的线程。您应该使用异步EJB方法,WebSphere Application Server asyncbeans,commonj API或JSR 236 API,具体取决于您使用的产品版本。所有这些API都会将组件上下文传播到外部线程,这将允许您lookup("java:comp/UserTransaction"),而您应该使用它。

答案 1 :(得分:0)

您的方法存在一些问题,但我还要问您为什么在Struts / WebShpere应用中使用用户管理的事务和多线程?

以下是一些可能有用的要点 -

在Java EE应用程序中,应用程序服务器负责为您管理线程。如果您还操纵线程,则可以搞乱应用程序服务器正在使用其线程管理执行的操作。通常,您可以在应用程序服务器管理手册中找到有关可以调整的设置的信息。我不确定特定于WebSphere,我希望每个HTTP请求传入将获得自己的线程。

从您的描述中我怀疑您正试图通过使用大量线程来快速批量处理大量事情。虽然您可以进行异步EJB调用,但您还应考虑将每个请求放在一个简单的JMS队列上,并使用MessageDrivenBeans为它们提供服务,这将使多个线程处于它们之上。 (如果您有较旧版本的Websphere异步EJB调用可能不可用)

我很少见到UserTransaction真正需要的地方。当您调用EJB时​​,缺省情况是事务已启动(或者如果已存在则已加入)。您可以将设置添加到会话bean方法(通过部署描述符或注释)以获得所需的行为。

例如,假设我想要处理一个项目列表,但是在列表中间的一个项目无法处理,我不想回滚那些成功的项目。在这种情况下,我将整个列表传递给EJB方法,然后为每个项调用第二个带有@RequiresNew事务属性的EJB方法。每个单独的项目都将在自己的交易中处理。

至于为什么它在Windows上运行而不是linux专用,我还需要知道涉及哪些硬件,但我推测linux机器正在利用更多真正的harware线程和并行执行。