[rules-users] Stateless Vs Stateful Sessions in Webtier

Pritham infinity2heaven at gmail.com
Tue Jan 26 17:07:56 EST 2010


I'm planning to use the following approach in my webtier:

High level design: Each http request for a page on our site has an average
of 5 separate requests to process rules before finally rendering. Each time,
servlet handler calls runRule(<some context object>). Essentially, rules is
serving as a filtering process and while Stateless ksession would have done
the trick, I needed to control the execution of rules based on agenda-order
and salience, hence the stateful ksession. The rules themselves are pretty
st forward and I don't see the need to insert facts "dynamically" during a
long web conversation (at least for now). 

protected void runRule(MyContect context) {

    try {
        KnowledgeBase kbase = loadKnowledgeBase(context);

        StatefulKnowledgeSession kSession =
kbase.newStatefulKnowledgeSession();
       
        // set some globals here         

        // pop groups into agenda's stack for controlling execution order
        kSession.getAgenda().getAgendaGroup("<page-id>").setFocus();
        kSession.getAgenda().getAgendaGroup("<section-id>).setFocus();
        kSession.getAgenda().getAgendaGroup("site-global").setFocus();          

        kSession.insert(context);

        kSession.fireAllRules();
        
        // at this point context is updated by rules for the servlet to
handle after the call;
        
        kSession.dispose();

    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("Error occured in processing Drools
rules", e);
    }       
}

public KnowledgeBase loadKnowledgeBase() throws DroolsParserException,
IOException {

     if(kbase != null) { // singleton instance
	return kbase;
     }	

    KnowledgeBuilder knowledgeBuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder();

   
knowledgeBuilder.add(ResourceFactory.newClassPathResource("dsl/global.dsl"),
                ResourceType.DSL);
    knowledgeBuilder.add(ResourceFactory.newClassPathResource("rules/"),
                ResourceType.DSLR);
      
    if (knowledgeBuilder.hasErrors()) {
        throw new RuntimeException(knowledgeBuilder.getErrors().toString());
    }

    kbase = KnowledgeBaseFactory.newKnowledgeBase();
    kbase .addKnowledgePackages(knowledgeBuilder.getKnowledgePackages());

    return kbase ;
}


Michael Bali's book has an entire chapter on Stateful Session in which it
recommended to create a 
StatefulSession Service with a dedicated writeObject and readObject and
"warns" about thread safety. 

I'm still not clear about the unsafe threading issues with using a stateful
ksession inside a webtier. 

And would the approach 1 in the above work, assuming multiple users are
executing the same rules at the same time?

Thanks



public class DroolsService implements Serializable {
	
	private static final long serialVersionUID = 6623448115053519253L;
	private transient KnowledgeBase knowledgeBase;
	private transient StatefulKnowledgeSession statefulSession;
	
	public DroolsService(KnowledgeBase knowledgeBase) {
		this.knowledgeBase = knowledgeBase;
		statefulSession = createKnowledgeSession();
	}

	private StatefulKnowledgeSession createKnowledgeSession() {
		StatefulKnowledgeSession session = knowledgeBase
				.newStatefulKnowledgeSession();
		return session;
	}

	public void insertOrUpdate(Object fact) {
		if (fact == null) {
			return;
		}

		FactHandle factHandle = statefulSession.getFactHandle(fact);

		if (factHandle == null) {
			statefulSession.insert(fact);
		} else {
			statefulSession.update(factHandle, fact);
		}
	}

	public void executeRules() {
		statefulSession.fireAllRules();
	}

	public void terminate() {
		statefulSession.dispose();
	}

	private void writeObject(ObjectOutputStream out) throws IOException {
		out.defaultWriteObject();
		DroolsObjectOutputStream droolsOut = new DroolsObjectOutputStream(
				(OutputStream) out);
		droolsOut.writeObject(knowledgeBase);
		Marshaller marshaller = createSerializableMarshaller(knowledgeBase);
		marshaller.marshall(droolsOut, statefulSession);
	}

	private void readObject(ObjectInputStream in) throws IOException,
			ClassNotFoundException {
		in.defaultReadObject();
		DroolsObjectInputStream droolsIn = new DroolsObjectInputStream(
				(InputStream) in);
		this.knowledgeBase = (KnowledgeBase) droolsIn.readObject();
		Marshaller marshaller = createSerializableMarshaller(knowledgeBase);
		statefulSession = marshaller.unmarshall(droolsIn);
	}

	private Marshaller createSerializableMarshaller(KnowledgeBase
knowledgeBase) {
		ObjectMarshallingStrategyAcceptor acceptor = MarshallerFactory
				.newClassFilterAcceptor(new String[] { "*.*" });
		ObjectMarshallingStrategy strategy = MarshallerFactory
				.newSerializeMarshallingStrategy(acceptor);
		Marshaller marshaller = MarshallerFactory.newMarshaller(knowledgeBase,
				new ObjectMarshallingStrategy[] { strategy });
		return marshaller;
	}

}

-- 
View this message in context: http://n3.nabble.com/Stateless-Vs-Stateful-Sessions-in-Webtier-tp130284p139893.html
Sent from the Drools - User mailing list archive at Nabble.com.



More information about the rules-users mailing list