Monday, March 30, 2009

Integrating Oracle Business Rules with Coherence

"Do something if something happens" - believe me is a problem statement of 99% of applications running today. Wise men spend a number of years tuning these somethings. Oracle Coherence is one such infrastructure where something happens all the time. Objects are being put, mutated, removed, evicted and events are continuously generated. Components like EntryProcessors provide a mechanism to perform some functions that can be easily integrated with these events. So "Do" and "happenings" are covered with EntryProcessors and Events respectively. Next thing is "If" and the other something ("what should happen?"). Lets take a concrete scenario, what IF we want to approve all drivers in the Coherence Cache of age greater than 21 to have a license? Easy to implement. Execute an EntryProcessor for drivers whose age is greater than or equal to 21. Now, what IF business decides they will approve all drivers of ages 17 and more in the future? Even though there are quite a few ways of incorporating ever-changing-rules in an application but Oracle Business Rules is tailored made for such IFs that change. Lets implement our scenario... Application is continuously adding new Drivers in the Coherence Cache and we want automatic processes to approve these Drivers based on their age. Implementation is simple. Just add a BackingMapListener to the Driver's cache and with each driver being added assert the Driver's age using Business Rules APIs (JSR-94). How would this BML look like? Following is one sample using File as a Rule Repository (Or use WebDav):

public class RuleListener implements MapListener {

private RuleSession session;
private String ruleSet;
private RuleDictionary dict;

public RuleListener(String repoPath, String dictionary, String ruleSet) {
this.ruleSet = ruleSet;
RepositoryType jarType =
RepositoryManager.getRegisteredRepositoryType(Keys.CONNECTION);
try {
RuleRepository repo =
RepositoryManager.createRuleRepositoryInstance(jarType);
RepositoryContext jarCtx = new RepositoryContext();
jarCtx.setProperty(Keys.PATH, repoPath);
repo.init(jarCtx);

dict = repo.loadDictionary(dictionary);
String dmrl = dict.dataModelRL();
String rsrl = dict.ruleSetRL(ruleSet);

session = new RuleSession();
session.executeRuleset(dmrl);
session.executeRuleset(rsrl);
} catch (RepositoryException e) {
e.printStackTrace();
} catch (RLException e) {
e.printStackTrace();
} catch (RuleSetException e) {
e.printStackTrace();
}
}

private void process(MapEvent mapEvent) {
System.out.println("Processing Event");
try {
Object obj = mapEvent.getNewValue();
Object key = mapEvent.getKey();

Driver driver =
(Driver)(obj instanceof Binary ?
ExternalizableHelper.fromBinary((Binary)obj) : obj);
if (session != null) {
session.callFunctionWithArgument("assert", driver);
Integer isSuccess =
(Integer) session.callFunctionWithArgument("run", ruleSet);
// -- Is the following necessary?
if (isSuccess != null && isSuccess.intValue () == 1) {
// -- Do Something
}

}
} catch (RLException e) {
e.printStackTrace();
} catch (RuleSetException e) {
e.printStackTrace();
}

}
public void entryInserted(MapEvent mapEvent) {
process(mapEvent);
}
....
}
Even better implementation would be if even the "Do Something" is taken out of this code and is run as a Business Rule function. So what does a Business user do? They change the RuleSet for the business conditions and also what to do when it is met. Another business use case is to buy n-stocks if the price of a Stock is at $x. This $x can be changed using Business Rules while Coherence continues to process stocks in it's system. More codes and a sample project to follow...
What's next? If I am using Coherence as an Execution engine for data (BML + EntryProcessors), how to control the EntryProcessor's execution? With no human interaction to build an auto-process-configurer engine that changes the RuleSet dynamically inside the Cluster based on certain state of data. Stay tuned while I go and discuss it more with the Wise men I know.

No comments: