[rules-users] How do I persist at every node transition?

Kris Verlaenen Kris.Verlaenen at cs.kuleuven.be
Wed Oct 20 11:25:52 EDT 2010


The engine will store the state of the process instance at any "safe
state".  This means we won't store the state while we're still in the
middle of processing it (as that means the state is still changing), but
only once we're done processing that one trigger.

So if you have a synchronous process that executes synchronously from
start to finish based on a trigger, it doesn't really make sense to
store the state after each node, as you can easily restore later by
replaying the trigger.

As soon as you start using asynchronous or stateful processes, the
process instance state is stored once it reaches that wait state.  You
can always restore by restoring the previous state and reapplying the
same trigger so you continue exactly where you left off last time.

Kris

Quoting kirakane <kirakane at gmail.com>:

> 
> I setup JPA persistence using a MySQL DB and the BTM transaction
> manager as a
> stand alone J2SE application.   I'm trying to setup to be able to
> continue
> from the last transition on a workflow if a process dies in the
> middle. 
> 
> I have show sql turned on and I can see the ProcessInstance get saved
> at the
> start but not at any of the node transitions.  So if I kill the
> process in
> the middle or simulate an outage and recover the session using 
> 
>             ksession =
> JPAKnowledgeService.loadStatefulKnowledgeSession(
> sessionID, kbase, null, env );
> 
> the process restarts from the very beginning which is not the
> behavior I
> desire.  
> 
> For example for the RulesFlow 
> 
> Start->A->B->C->End 
> 
> and the server dies in B I would like the process to pickup from B.
> 
> How do I get this behavior? 
> 
> Log:
> --------------------------
> create jpa backed stateful ksession
> Hibernate: insert into SessionInfo (lastModificationDate,
> rulesByteArray,
> startDate, OPTLOCK) values (?, ?, ?, ?)
> Oct 18, 2010 10:56:14 AM bitronix.tm.twopc.Preparer prepare
> WARNING: executing transaction with 0 enlisted resource
> SESSIONID:80
> Object Persisted
> Hibernate: update SessionInfo set lastModificationDate=?,
> rulesByteArray=?,
> startDate=?, OPTLOCK=? where id=? and OPTLOCK=?
> Starting Process...
> Hibernate: insert into ProcessInstanceInfo (externalVariables,
> lastModificationDate, lastReadDate, processId,
> processInstanceByteArray,
> startDate, state, OPTLOCK) values (?, ?, ?, ?, ?, ?, ?, ?)
> Hibernate: update ProcessInstanceInfo set externalVariables=?,
> lastModificationDate=?, lastReadDate=?, processId=?,
> processInstanceByteArray=?, startDate=?, state=?, OPTLOCK=? where
> InstanceId=? and OPTLOCK=?
> Hibernate: insert into EventTypes (InstanceId, element) values (?,
> ?)
> Hibernate: update SessionInfo set lastModificationDate=?,
> rulesByteArray=?,
> startDate=?, OPTLOCK=? where id=? and OPTLOCK=?
> Fire All Rules...
> Created Status:VirusScanStatus [count=0, status=null,
> unquarantineCount=0]
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> Hibernate: select processins0_.InstanceId as InstanceId1_0_,
> processins0_.externalVariables as external2_1_0_,
> processins0_.lastModificationDate as lastModi3_1_0_,
> processins0_.lastReadDate as lastRead4_1_0_, processins0_.processId
> as
> processId1_0_, processins0_.processInstanceByteArray as
> processI6_1_0_,
> processins0_.startDate as startDate1_0_, processins0_.state as
> state1_0_,
> processins0_.OPTLOCK as OPTLOCK1_0_ from ProcessInstanceInfo
> processins0_
> where processins0_.InstanceId=?
> In virus scanner:DocumentId [doc_id=THIS IS A DOCUMENT ID 1234]
> did the scan:VirusScanStatus [count=1, status=success,
> unquarantineCount=0]
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> remove from quarentine:DocumentId [doc_id=THIS IS A DOCUMENT ID
> 1234]
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> VirusScanStatus [count=1, status=failed, unquarantineCount=1]
> sleeping:1000
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> entering state
> remove from quarentine:DocumentId [doc_id=THIS IS A DOCUMENT ID
> 1234]
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> VirusScanStatus [count=1, status=failed, unquarantineCount=2]
> sleeping:4000
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> entering state
> remove from quarentine:DocumentId [doc_id=THIS IS A DOCUMENT ID
> 1234]
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> VirusScanStatus [count=1, status=failed, unquarantineCount=3]
> sleeping:9000
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> entering state
> remove from quarentine:DocumentId [doc_id=THIS IS A DOCUMENT ID
> 1234]
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> Hibernate: select variables0_.processInstanceId as processI5_1_,
> variables0_.id as id1_, variables0_.name as formula1_1_,
> variables0_.id as
> id4_0_, variables0_.name as name4_0_, variables0_.persister as
> persister4_0_, variables0_.processInstanceId as processI5_4_0_,
> variables0_.workItemId as workItemId4_0_, variables0_.entityClass as
> entityCl7_4_0_, variables0_.entityId as entityId4_0_,
> variables0_.TYPE as
> TYPE4_0_ from VariableInstanceInfo variables0_ where
> variables0_.processInstanceId=?
> Hibernate: select processins0_.InstanceId as col_0_0_ from
> ProcessInstanceInfo processins0_ where ? in (select
> eventtypes1_.element
> from EventTypes eventtypes1_ where
> processins0_.InstanceId=eventtypes1_.InstanceId)
> Hibernate: delete from EventTypes where InstanceId=?
> Hibernate: delete from ProcessInstanceInfo where InstanceId=? and
> OPTLOCK=?
> Hibernate: update SessionInfo set lastModificationDate=?,
> rulesByteArray=?,
> startDate=?, OPTLOCK=? where id=? and OPTLOCK=?
> finished
> 
> Here's my configuration:
> 
> orm.xml
> --------------------------------------
> <?xml version="1.0" encoding="UTF-8"?>
> <entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
>                 
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>                 
> xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
> orm_1_0.xsd"
>                  version="1.0">
>     <named-query name="ProcessInstancesWaitingForEvent">
>         <query>
>             select
>             processInstanceInfo.processInstanceId
>             from
>             ProcessInstanceInfo processInstanceInfo
>             where
>             :type in elements(processInstanceInfo.eventTypes)
>         </query>
>     </named-query>
> </entity-mappings>
> 
> persistance.xml
> --------------------------------------
> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
> <persistence version="1.0"
>             
> xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
>      http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
>      http://java.sun.com/xml/ns/persistence/orm
>      http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
>              xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
>              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>              xmlns="http://java.sun.com/xml/ns/persistence">
> 
>     <persistence-unit name="org.drools.persistence.jpa">
>         <provider>org.hibernate.ejb.HibernatePersistence</provider>
>         <jta-data-source>jdbc/TEST</jta-data-source>
>         <class>org.drools.persistence.session.SessionInfo</class>
>        
> <class>org.drools.persistence.processinstance.ProcessInstanceInfo</class>
>        
>
<class>org.drools.persistence.processinstance.ProcessInstanceEventInfo</class>
>        
> <class>org.drools.persistence.processinstance.WorkItemInfo</class>
>        
>
<class>org.drools.persistence.processinstance.variabletypes.VariableInstanceInfo</class>
>        
>
<class>org.drools.persistence.processinstance.variabletypes.JPAPersistedVariable</class>
> 
>         <properties>
>             <property name="hibernate.dialect"
> value="org.hibernate.dialect.MySQL5Dialect" />
>             <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"/>
>             <property name="hibernate.jndi.class"
> value="bitronix.tm.jndi.BitronixInitialContextFactory"/>
>         </properties>
>     </persistence-unit>
> </persistence> 
> 
> Calling Code
> -------------------------------
> 
>     public static final void main(String[] args) {
>         try {
>             createDataSource();
>             // load up the knowledge base
>             KnowledgeBase kbase = readKnowledgeBase();
>             // create the entity manager factory and register it in
> the
>             // environment
>             System.out.println("create entity manager");
> 
>             System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
> "bitronix.tm.jndi.BitronixInitialContextFactory");
> 
>             EntityManagerFactory emf = Persistence
>                    
> .createEntityManagerFactory("org.drools.persistence.jpa");
>             Environment env = KnowledgeBaseFactory.newEnvironment();
>             env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
>             env.set(Context.INITIAL_CONTEXT_FACTORY,
> "bitronix.tm.jndi.BitronixInitialContextFactory");
>            
>
env.set(EnvironmentName.TRANSACTION_MANAGER,TransactionManagerServices.getTransactionManager());
> 
>             // create a new knowledge session that uses JPA to store
> the
> runtime
>             // state
>             System.out.println("create jpa backed stateful
> ksession");
> 
>             StatefulKnowledgeSession ksession = null;
>             if (ksession == null) {
>                 ksession = JPAKnowledgeService
>                         .newStatefulKnowledgeSession(kbase, null,
> env);
>                 int sessionId = ksession.getId();
>                 System.out.println("SESSIONID:" + sessionId);
>                 Persister pes = new Persister();
>                 pes.put(new Integer(sessionId));
>             }
> 
>             // KnowledgeRuntimeLogger logger =
> KnowledgeRuntimeLoggerFactory.newConsoleLogger(ksession);
>             KnowledgeRuntimeLogger logger =
> KnowledgeRuntimeLoggerFactory
>                     .newFileLogger(ksession, "test");
> 
>             ksession.insert(new DocumentId("THIS IS A DOCUMENT ID
> 1234"));
> 
>             System.out.println("Starting Process...");
>             ksession.startProcess("VirusScan");
> 
>             System.out.println("Fire All Rules...");
>             ksession.fireAllRules();
>             System.out.println("finished");
>             logger.close();
> //            ksession.dispose();
>         } catch (Throwable t) {
>             t.printStackTrace();
>         }
>     }
> 
>     private static KnowledgeBase readKnowledgeBase() throws Exception
> {
>         KnowledgeBuilder kbuilder =
> KnowledgeBuilderFactory.newKnowledgeBuilder();
> 	
>
kbuilder.add(ResourceFactory.newClassPathResource("VirusScanner.drl",VirusScanStatus.class),
> ResourceType.DRL);
> 	
>
kbuilder.add(ResourceFactory.newClassPathResource("VirusScan.rf",VirusScanStatus.class),
> ResourceType.DRF);
>         KnowledgeBuilderErrors errors = kbuilder.getErrors();
>         if (errors.size() > 0) {
>             System.out.println("NUM:" + errors.size());
>             for (KnowledgeBuilderError error : errors) {
>                 System.err.println("A_ERROR:" + error);
>             }
>             throw new IllegalArgumentException("Could not parse
> knowledge.");
>         }
>         KnowledgeBase kbase =
> KnowledgeBaseFactory.newKnowledgeBase();
>         kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
>         return kbase;
>     }
> 
> 
> 
>     private static void createDataSource() {
>         System.out.println("creating datasource");
>         Configuration conf =
> TransactionManagerServices.getConfiguration();
>         conf.setServerId("jvm-1");
>         conf.setLogPart1Filename("./tx-logs/part1.btm");
>         conf.setLogPart2Filename("./tx-logs/part2.btm");
> 
>         PoolingDataSource ds = new PoolingDataSource();
>         ds.setUniqueName("jdbc/TEST");
>        
> ds.setClassName("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
>         ds.setMaxPoolSize(3);
>         ds.setAllowLocalTransactions(true);
>         ds.getDriverProperties().put("user", "jboss");
>         ds.getDriverProperties().put("password", "jboss");
>         ds.getDriverProperties().put("URL",
> "jdbc:mysql://localhost:3306/jpadrools5");
>         ds.init();
>     }
> 
> 
> Regards,
> Lawrence
> 
> 
> -- 
> View this message in context:
>
http://drools-java-rules-engine.46999.n3.nabble.com/How-do-I-persist-at-every-node-transition-tp1727066p1727066.html
> Sent from the Drools - User mailing list archive at Nabble.com.
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
> 




Disclaimer: http://www.kuleuven.be/cwis/email_disclaimer.htm



More information about the rules-users mailing list