使用持久性的 Drools Stateful Knowledge Session
Drools Stateful Knowledge Session using persistence
我正在创建一个 Drools 有状态会话,如 JBPM 持久性文档中所述:
http://docs.jboss.org/jbpm/v5.1/javadocs/org/drools/persistence/jpa/JPAKnowledgeService.html
但是,我遇到了以下异常
javax.persistence.TransactionRequiredException: joinTransaction has been called on a resource-local EntityManager which is unable to register for a JTA transaction.
我的代码是:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("metadata.model");
Environment env = KnowledgeBaseFactory.newEnvironment();
env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
env.set(EnvironmentName.TRANSACTION_MANAGER, TransactionManagerServices.getTransactionManager());
env.set(EnvironmentName.TRANSACTION, TransactionManagerServices.getTransactionManager());
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieBase kBase = kContainer.getKieBase();
StatefulKnowledgeSession kSession = JPAKnowledgeService.newStatefulKnowledgeSession(kBase, null, env);
最后一行抛出异常。事先,我已经按照上述文档中的描述绑定了 JDBC JTA 数据源。
PoolingDataSource ds = new PoolingDataSource();
ds.setUniqueName("jdbc/BitronixJTADataSource");
ds.setClassName("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
ds.setMaxPoolSize(3);
ds.setAllowLocalTransactions(true);
ds.getDriverProperties().put("user", "root");
ds.getDriverProperties().put("password", "****");
ds.getDriverProperties().put("URL", "jdbc:mysql://localhost:3306/metadatadb");
ds.init();
我正在使用 EclipseLink 持久性提供程序和 MySQL JDBC 驱动程序。
终于,我成功了。我犯的最重要的错误是我试图将 EclipseLink 用作 JPA 提供程序。这种方法行不通,因为除了自定义持久性 类 之外,Drools 使用另外两个持久性注释 类:org.drools.persistence.info.SessionInfo
和 org.drools.persistence.info.WorkItemInfo
。这两个包含未使用 JPA 时间注释进行注释的日期字段。它们似乎是专门为 Hibernate 量身定制的。
另一个引起我注意的重要方面是需要在设置环境变量后添加以下行:
env.set(EnvironmentName.OBJECT_MARSHALLING_STRATEGIES,
new ObjectMarshallingStrategy[] {
new JPAPlaceholderResolverStrategy(domainEnv),
new SerializablePlaceholderResolverStrategy(
ClassObjectMarshallingStrategyAcceptor.DEFAULT) });
执行此操作是为了宣布您打算使用 JPA 保持当前会话状态。
然而,我上面提到的异常是由于 EclipseLink 正在创建一个 "ResourceLocal" 事务包装器,即使在 persistence.xml 中明确指定了 JTA。这是因为没有指定目标服务器 属性。因此,没有外部事务控制器附加到创建的数据库会话,并且提供的包装器根本无法支持 joinTransaction 操作。要解决此问题,请将以下行添加到您的 persistence.xml 文件中:
<property name="eclipselink.target-server" value="JBoss"/>
在初始化数据源之前,添加:
Configuration conf = TransactionManagerServices.getConfiguration();
conf.setJndiUserTransactionName("java:/TransactionManager");
当然,我假设正在使用 BTM。
我正在创建一个 Drools 有状态会话,如 JBPM 持久性文档中所述: http://docs.jboss.org/jbpm/v5.1/javadocs/org/drools/persistence/jpa/JPAKnowledgeService.html
但是,我遇到了以下异常
javax.persistence.TransactionRequiredException: joinTransaction has been called on a resource-local EntityManager which is unable to register for a JTA transaction.
我的代码是:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("metadata.model");
Environment env = KnowledgeBaseFactory.newEnvironment();
env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
env.set(EnvironmentName.TRANSACTION_MANAGER, TransactionManagerServices.getTransactionManager());
env.set(EnvironmentName.TRANSACTION, TransactionManagerServices.getTransactionManager());
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieBase kBase = kContainer.getKieBase();
StatefulKnowledgeSession kSession = JPAKnowledgeService.newStatefulKnowledgeSession(kBase, null, env);
最后一行抛出异常。事先,我已经按照上述文档中的描述绑定了 JDBC JTA 数据源。
PoolingDataSource ds = new PoolingDataSource();
ds.setUniqueName("jdbc/BitronixJTADataSource");
ds.setClassName("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
ds.setMaxPoolSize(3);
ds.setAllowLocalTransactions(true);
ds.getDriverProperties().put("user", "root");
ds.getDriverProperties().put("password", "****");
ds.getDriverProperties().put("URL", "jdbc:mysql://localhost:3306/metadatadb");
ds.init();
我正在使用 EclipseLink 持久性提供程序和 MySQL JDBC 驱动程序。
终于,我成功了。我犯的最重要的错误是我试图将 EclipseLink 用作 JPA 提供程序。这种方法行不通,因为除了自定义持久性 类 之外,Drools 使用另外两个持久性注释 类:org.drools.persistence.info.SessionInfo
和 org.drools.persistence.info.WorkItemInfo
。这两个包含未使用 JPA 时间注释进行注释的日期字段。它们似乎是专门为 Hibernate 量身定制的。
另一个引起我注意的重要方面是需要在设置环境变量后添加以下行:
env.set(EnvironmentName.OBJECT_MARSHALLING_STRATEGIES,
new ObjectMarshallingStrategy[] {
new JPAPlaceholderResolverStrategy(domainEnv),
new SerializablePlaceholderResolverStrategy(
ClassObjectMarshallingStrategyAcceptor.DEFAULT) });
执行此操作是为了宣布您打算使用 JPA 保持当前会话状态。
然而,我上面提到的异常是由于 EclipseLink 正在创建一个 "ResourceLocal" 事务包装器,即使在 persistence.xml 中明确指定了 JTA。这是因为没有指定目标服务器 属性。因此,没有外部事务控制器附加到创建的数据库会话,并且提供的包装器根本无法支持 joinTransaction 操作。要解决此问题,请将以下行添加到您的 persistence.xml 文件中:
<property name="eclipselink.target-server" value="JBoss"/>
在初始化数据源之前,添加:
Configuration conf = TransactionManagerServices.getConfiguration();
conf.setJndiUserTransactionName("java:/TransactionManager");
当然,我假设正在使用 BTM。