【问题标题】:how can i obtain TransactionManager on WebSphere 8.0?如何在 WebSphere 8.0 上获取 TransactionManager?
【发布时间】:2013-04-25 18:16:18
【问题描述】:

我试图在@Singleton SessionBean - EJB 3.1 - 中获取 TransactionManager 来控制我的事务范围,因为我必须通过 @PostConstruct 方法访问数据库。如果发生异常,我不能让容器回滚,因为它会抛出 TransactionRolledbackException: setRollbackOnly 从单例 post 构造方法中调用。

我正在使用 JTA 数据源并定义了 @TransactionManagement(TransactionManagementType.BEAN) 来覆盖对事务的控制。

@资源 私有事务管理器事务管理器;

当我尝试执行“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)
        {
        }

    }

}

我认为应该在 @Resource 注释上添加一个 JNDI 地址,这是特定于 WebSphere 的,但我真的找不到。

更新:

为什么在容器管理的注入上使用 JNDI?由于我从直接注入中获得了空指针异常,因此尝试像 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 工作。感谢您的回答。

【问题讨论】:

  • mappedName 在 websphere 中不受支持。

标签: java websphere transactionmanager


【解决方案1】:

当您有 bean 托管事务时,您不使用 javax.transaction.TransactionManager,而是使用 javax.transaction.UserTransaction

然后你调用UserTransaction接口的begin、commit ...等。

答案已更新:

1) 首先,正如我所说,不要使用TransactionManager。使用UserTransaction

2)正如您想知道UserTransaction 对象的JNDI 名称。它是java:comp/UserTransaction。但是只有在您的组件不受管理时才需要它。 ie: Servlet、EJB。该过程称为手动调用 JNDI API

3) 提供 commit()rollback()。它们都不存在。

我正在看你的课,看起来还不错。

那么,问题出在哪里? (可能性)

1)您的类不被视为 EJB(容器管理),这就是注入失败的原因。

2)事务服务在EJB @Startup之前没有启动或者启动失败。

3) 您在 persistence.xml 中配置了 JTA 数据源。在这种情况下,请尝试:

@Resource
private EJBContext context;

userTransaction  = context.getUserTransaction(); 

注意:还请提供完整的堆栈跟踪和persistence.xml,以便查明确切的问题。

【讨论】:

  • 再次感谢您。我已经使用了 UserTransactin - 通过注入 - 并遇到了同样的问题。贴上原代码。没有使用 commit() 或 rollback() 因为我必须在完成其余的事务处理之前解决这个问题。我将尝试改用 UserTransaction 并使用结果进行更新。
【解决方案2】:

您不需要在程序化 (BMT) 会话 bean 中使用事务管理器,除非您想在某些情况下挂起()或恢复()相关事务,否则请改用 UserTransaction。

但是,您可以通过 com.ibm.ws.Transaction.TransactionManagerFactory 类使用静态方法 getTransactionManager() 获取对 websphere 中事务管理器的引用。

public TransactionManager getTransactionManager() {
    return TransactionManagerFactory.getTransactionManager();
}

【讨论】:

    【解决方案3】:

    下面是一些使用 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。

    【讨论】:

    • 感谢您的回答。我知道注入是在 bean 实例准备好之后进行的,这就是我在 @PostConstruct 方法中使用注入引用的原因。明天我一上班就会发布 bean 代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多