无法使Bitronix在Spring Boot项目中管理我的数据源/事务

时间:2017-02-15 10:35:22

标签: java hibernate jpa drools bitronix

我现在已经尝试将JPAKnowledgeService做了大约3天,而且我已经非常接近放弃了,看起来配置和细节太多,它的功能是什么。然而,

我最初有this problem,在我添加

之后就消失了
java.naming.factory.initial=bitronix.tm.jndi.BitronixInitialContextFactory
正如答案所示,

进入我的jndi.properties文件。我终于能够创建一个StatefulKnowledgeSession,并认为工作已经完成。但是在drools聊天中,同一个人建议我的交易可能是由Hibernate而不是Bitronix处理的,这可能会使我的持久性完全不是事务性的。

我猜他是对的,因为每当我尝试将Object插入知识会话并致电fireAllRules时,我就被困在:

executing transaction with 0 enlisted resource

接下来是:

transaction timed out: a Bitronix Transaction with GTRID [3132372E302E312E310000000000AFB9D800000006], status=MARKED_ROLLBACK, 0 resource(s) enlisted (started Thu Jan 01 05:11:56 EET 1970)

之后我改变的是;我更新了我的persistence.xml,如下所示:

    <?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
    <persistence-unit  name="org.jbpm.persistence.jpa" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>java:comp/env/jdbc/jbpm</jta-data-source>
        <class>org.drools.persistence.info.SessionInfo</class>
        <properties>
            <property name="hibernate.jndi.class" value="bitronix.tm.jndi.BitronixInitialContextFactory"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <property name="hibernate.max_fetch_depth" value="3"/>
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.BTMTransactionManagerLookup" />
        </properties>
    </persistence-unit>
</persistence>

将此行添加到我的application.properties

spring.datasource.jndi-name=java:comp/env/jdbc/jbpm

并按照these instructions为嵌入式tomcat的数据源提供了一个jndi名称。

,错误又回来了:

Caused by: java.lang.NullPointerException: null
    at org.drools.persistence.jta.JtaTransactionManager.getStatus(JtaTransactionManager.java:273) ~[drools-persistence-jpa-6.5.0.Final.jar:6.5.0.Final]
    at org.drools.persistence.jpa.AbstractPersistenceContextManager.getApplicationScopedEntityManager(AbstractPersistenceContextManager.java:78) ~[drools-persistence-jpa-6.5.0.Final.jar:6.5.0.Final]
    at org.drools.persistence.jpa.JpaPersistenceContextManager.getApplicationScopedPersistenceContext(JpaPersistenceContextManager.java:55) ~[drools-persistence-jpa-6.5.0.Final.jar:6.5.0.Final]
    at org.drools.persistence.SingleSessionCommandService.<init>(SingleSessionCommandService.java:103) ~[drools-persistence-jpa-6.5.0.Final.jar:6.5.0.Final]
    ... 43 common frames omitted

JPAKnowledgeService相关的表是在数据库中创建的,所以我想我的JNDI注册成功,但我似乎无法找到Bitronix作为我的事务管理器,因为JtaTransactionManager似乎为null。我究竟做错了什么?我感到沮丧和无能。

1 个答案:

答案 0 :(得分:2)

显然,我没有必要使用Tomcat将我的默认数据源注册为JNDI,但是让Bitronix直接管理它如下:

@Bean
public PoolingDataSource setupPoolingDataSource() {
    PoolingDataSource pds = new PoolingDataSource();
    pds.setUniqueName("jdbc/jbpm");
    pds.setClassName("bitronix.tm.resource.jdbc.lrc.LrcXADataSource");
    pds.setMaxPoolSize(50);
    pds.setAllowLocalTransactions(true);
    pds.getDriverProperties().put("user", "username");
    pds.getDriverProperties().put("password", "password");
    pds.getDriverProperties().put("url", "jdbc:mysql://localhost/databaseName?useUnicode=yes&characterEncoding=UTF-8&useSSL=false");
    pds.getDriverProperties().put("driverClassName", "com.mysql.jdbc.Driver");
    pds.init();
    return pds;
}

并删除了这些内容:

@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
    return new TomcatEmbeddedServletContainerFactory() {

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                Tomcat tomcat) {
            tomcat.enableNaming();
            return super.getTomcatEmbeddedServletContainer(tomcat);
        }

        @Override
        protected void postProcessContext(Context context) {

            ContextResource resource = new ContextResource();
            resource.setName(name);
            resource.setType(DataSource.class.getName());
            resource.setProperty("url", "...");
            resource.setProperty("username", "...");
            resource.setProperty("password", "...");
            resource.setProperty("driverClassName", "...");
            resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
            context.getNamingResources().addResource(resource);
        }
    };
}

@Bean
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {

    JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
    bean.setJndiName("...");
    bean.setProxyInterface(DataSource.class);
    bean.setLookupOnStartup(false);
    bean.afterPropertiesSet();
    return (DataSource)bean.getObject();
}

其他一切都保持不变并且有效!