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(a)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-e...
Sent from the Drools - User mailing list archive at
Nabble.com.
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users
Disclaimer:
http://www.kuleuven.be/cwis/email_disclaimer.htm