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-tp130284p1...
Sent from the Drools - User mailing list archive at
Nabble.com.