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

kirakane kirakane at gmail.com
Mon Oct 18 14:07:49 EDT 2010


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.



More information about the rules-users mailing list