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.