如何在Kie Persistence中实现JBoss事务管理?求生产可用示例
I totally get why you’d want to switch from Bitronix to JBoss Transaction Manager (Narayana) for production—Drools docs are right that Bitronix is more suited for testing. Let’s walk through a complete, production-ready setup step by step.
1. Add Maven Dependencies
First, update your pom.xml to include the required Narayana and Drools persistence libraries. These pull in the production-grade transaction manager and seamless integration with KiePersistence:
<dependencies> <!-- JBoss Transaction API --> <dependency> <groupId>org.jboss.spec.javax.transaction</groupId> <artifactId>jboss-transaction-api_2.0_spec</artifactId> <version>1.0.1.Final</version> </dependency> <!-- Narayana Transaction Manager --> <dependency> <groupId>org.jboss.narayana.jta</groupId> <artifactId>narayana-jta</artifactId> <version>5.12.0.Final</version> </dependency> <!-- Drools Kie Persistence --> <dependency> <groupId>org.drools</groupId> <artifactId>kie-persistence-jpa</artifactId> <version>7.74.0.Final</version> </dependency> <!-- JPA Provider (Hibernate example) --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.6.14.Final</version> </dependency> <!-- Database Driver (MySQL example) --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> </dependencies>
2. Configure JBoss Transaction Manager & DataSource
Next, set up the transaction manager and a managed data source. Here’s a reusable Java configuration class (works for both Spring and plain Java SE):
import org.jboss.narayana.jta.UserTransaction; import org.jboss.narayana.jta.UserTransactionImp; import org.jboss.narayana.txframework.api.configuration.transaction.TransactionManager; import org.jboss.narayana.txframework.api.configuration.transaction.TransactionManagerImp; import javax.sql.DataSource; import com.mysql.cj.jdbc.MysqlDataSource; public class JBossTMConfig { public static DataSource getDataSource() { MysqlDataSource dataSource = new MysqlDataSource(); dataSource.setURL("jdbc:mysql://localhost:3306/kie_db?useSSL=false"); dataSource.setUser("db_user"); dataSource.setPassword("db_password"); // Production-focused settings dataSource.setInitialSize(10); dataSource.setMaxTotal(50); dataSource.setMaxWaitMillis(3000); return dataSource; } public static UserTransaction getUserTransaction() { return new UserTransactionImp(); } public static TransactionManager getTransactionManager() { return TransactionManagerImp.getTransactionManager(); } }
3. Initialize KieSession with Persistence & JBoss TM
Now wire up the KieSession to use JBoss transactions for persistence. This example uses JPA (required for KiePersistence):
import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; import org.kie.api.runtime.Environment; import org.kie.api.runtime.EnvironmentName; import org.kie.internal.persistence.jpa.JPAKnowledgeService; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public class KiePersistenceSetup { public static KieSession createPersistentKieSession() { // Initialize JPA EntityManagerFactory (matches persistence.xml) EntityManagerFactory emf = Persistence.createEntityManagerFactory("kie-persistence-unit"); // Set up environment with JBoss TM and EMF Environment env = KieServices.Factory.get().newEnvironment(); env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf); env.set(EnvironmentName.TRANSACTION_MANAGER, JBossTMConfig.getTransactionManager()); env.set(EnvironmentName.DATASOURCE, JBossTMConfig.getDataSource()); // Load KieContainer from your kmodule.xml KieContainer kieContainer = KieServices.Factory.get().getKieClasspathContainer(); // Create persistent KieSession (JTA transaction-aware) return JPAKnowledgeService.newStatefulKnowledgeSession( kieContainer.getKieBase("myKieBase"), null, env ); } }
Don’t forget your persistence.xml (place in src/main/resources/META-INF/):
<persistence-unit name="kie-persistence-unit" transaction-type="JTA"> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <jta-data-source>java:/MySqlDS</jta-data-source> <class>org.drools.persistence.info.SessionInfo</class> <class>org.drools.persistence.info.WorkItemInfo</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.show_sql" value="false"/> <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"/> </properties> </persistence-unit>
4. Execute Rules with Transaction Management
Finally, wrap rule execution in a transaction to ensure atomic persistence:
import org.kie.api.runtime.KieSession; import javax.transaction.UserTransaction; public class RuleExecutor { public static void executeRulesWithTransaction() { UserTransaction ut = JBossTMConfig.getUserTransaction(); KieSession ksession = null; try { ut.begin(); ut.setTransactionTimeout(30); // Prevent long-running transactions ksession = KiePersistenceSetup.createPersistentKieSession(); // Insert your business facts ksession.insert(new Order("ORD-123", 100.0)); // Fire rules ksession.fireAllRules(); ut.commit(); System.out.println("Rules executed and session persisted successfully"); } catch (Exception e) { try { if (ut != null) ut.rollback(); System.err.println("Transaction rolled back due to error: " + e.getMessage()); } catch (Exception rollbackEx) { rollbackEx.printStackTrace(); } } finally { if (ksession != null) { ksession.dispose(); } } } public static void main(String[] args) { executeRulesWithTransaction(); } } // Example fact class (must be serializable for persistence) class Order implements java.io.Serializable { private String orderId; private double amount; public Order(String orderId, double amount) { this.orderId = orderId; this.amount = amount; } // Getters/setters omitted for brevity }
Production Tips
- Tune Data Source: Adjust connection pool sizes, timeouts, and validation settings based on your actual workload.
- Monitoring: Use Narayana’s built-in JMX endpoints or tools like Prometheus to track transaction performance and status.
- Serialization: Ensure all facts inserted into the KieSession implement
java.io.Serializable—required for persistent sessions. - Error Handling: Add retry logic for transient database errors to improve resilience.
内容的提问来源于stack exchange,提问作者Prog_G

