First, a very basic introduction before we get into code. Drools is a Business Logic integration platform which offers an integrated platform for Rules, workflow, event processing etc. Drools started off as a Rete based rule engine but over the years has evolved to have multiple sub-projects. Main ones of course are Drools Expert (Rule Engine), Drools Flow (process/workflow) and Drools Guvnor ( Business Rules Manager). The main focus of this post is the Guvnor subproject which is centralized repository of rules. It provides a web-based application to access and create rules. It has an intuitive (or I feel so) UI to help non technical folks work with the repository.
All right, now the problem context. For our product, though we are interested in creating rules and adding them to the repository, however, instead of using the standard web UI provided by Guvnor, we would like to use our own jazzy web 3.0ish rich flex based UI, which is more appealing and user-friendly. So how do we do that?
There are possibly a few options available, two of which are
- Using the REST api exposed by the Guvnor
- Adding a rule using WebDAV
Ideally, I would have preferred the use of REST api and would still do however, there are a few complications to the use of REST api. The biggest one that I encountered was non-availability of any decent documentation. A couple of days of looking around and talking to some helpful people like @Rikkola on the Drools IRC channel, I got the idea that to do what I need to do, though REST is a viable option but there is another option with WebDAV. It is a set of methods based on the Hypertext Transfer Protocol (HTTP) that facilitates collaboration between users in editing and managing documents and files stored on World Wide Web servers.
When you run the Guvnor application in an application server, you would most likely access it with something like this
http://localhost:8080/drools-guvnor/org.drools.guvnor.Guvnor/Guvnor.html
and the screen would look like this
Now, interestingly, you can access the same information using WebDAV by using the URL as
http://localhost:8080/drools-guvnor/org.drools.guvnor.Guvnor/webdav
This would show you the following information
Contents of this Folder:
packages
snapshots
So, we are accessing the file system using Http. Now if I need to list down the contents of the package that I am interested in, I would do the following,
http://localhost:8080/drools-guvnor/org.drools.guvnor.Guvnor/webdav/packages/Analytics
and I get the following output
Contents of this Folder:
AnalyticsModel.jar
drools.package
NewRule.brl
NewDRLRule.drl
AnotherDRLRule.drl
YADRLRule.drl
So, how do I add a new rule to the above package from my Java program? For that you need a WebDAV api. I used Sardine to test out the simple case that I was interested in.
The code for connecting to the WebDAV and adding a rule looks like this
[sourcecode language=”java”]
public static void main(String[] args) throws SardineException {
listAllResources();
addARule();
}
private static void listAllResources() throws SardineException {
Sardine sardine = SardineFactory.begin("admin", "admin");
List<DavResource> resources = sardine
.getResources("http://localhost:8080/drools-guvnor/org.drools.guvnor.Guvnor/webdav/packages");
for (DavResource res : resources) {
System.out.println(res); // calls the .toString() method.
}
}
private static void addARule() throws SardineException {
Sardine sardine = SardineFactory.begin("username", "password");
String ruleDescription = "when Entity(entityName=="Car1s") then System.out.println( "*************rule executed")";
byte[] data = ruleDescription.getBytes();
sardine.put("http://localhost:8080/drools-guvnor/org.drools.guvnor.Guvnor/webdav/packages/Analytics/SimpleDRLRule.drl", data);
System.out.println("Rule added …");
}
}
[/sourcecode]
As you would notice, listAllResources() lists down the resources which are found at a particular webdav location and addARule(), adds a new rule to the Guvnor package. In our case, the rule is being added to the Analytics package by the name of SimpleDRLRule.drl
Once you execute the code, you should be able to see the rule added through your Guvnor web ui too.
Now, let us see, how we can execute this rule. The code that I used was
[sourcecode language=”java”]
public class GuvnorTest {
@Test
public void testDroolsWithGuvnor() throws Exception {
KnowledgeBase knowledgeBase = createKnowledgeBase();
StatefulKnowledgeSession session = knowledgeBase.newStatefulKnowledgeSession();
try {
Entity entity = new Entity();
entity.setEntityName("Car1s");
session.insert(entity);
Assert.assertTrue(session.getFactCount() == 1);
System.out.println("And the count is " + session.getFactCount());
session.fireAllRules();
System.out.println("And the count is " + session.getFactCount());
Assert.assertEquals(1, session.getFactCount());
}
finally {
session.dispose();
}
}
private static KnowledgeBase createKnowledgeBase() {
KnowledgeAgentConfiguration kaconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
kaconf.setProperty( "drools.agent.scanDirectories", "false" );
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent( "test agent", kaconf );
kagent.applyChangeSet( ResourceFactory.newClassPathResource("opal-guvnor.xml"));
return kagent.getKnowledgeBase();
}
}
[/sourcecode]
The opal-guvnor.xml is a changeset file and has the following
[sourcecode language=”xml”]
xmlns=’http://drools.org/drools-5.0/change-set’
xmlns:xs=’http://www.w3.org/2001/XMLSchema-instance’
xs:schemaLocation=’http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd’ >
<add>
<resource source=’http://localhost:8080/drools-guvnor/org.drools.guvnor.Guvnor/package/Analytics/LATEST.drl’ type=’DRL’ basicAuthentication="enabled" username="admin" password="admin"/>
</add>
</change-set>
[/sourcecode]
The output is the following
[sourcecode language=”text”]
[2011:02:45 23:02:558:debug] KnowledgeAgent adding KnowledgeDefinitionsPackage Analytics
[2011:02:45 23:02:583:info] KnowledgeAgent new KnowledgeBase now built and in use
[2011:02:45 23:02:583:debug] KnowledgeAgent finished rebuilding KnowledgeBase using ChangeSet
And the count is 1
*************rule executed
And the count is 1
[/sourcecode]
As you can see, we did not have the rebuild the package for the rule to get activated or something. Once the rule was added to the package, after that I could execute the rule.
So, is this the recommended approach instead the REST api. I would say maybe not. Does it work? Depending on the scenario that you are looking to solve, Yes.
Ideally, I would like to use the REST api for my product but this gives me some respite and I can go ahead. You can follow the REST api status https://issues.jboss.org/browse/GUVNOR-1080 here and if you have a working example of how you managed to use it, please link it 🙂
Related discussion on this topic http://drools-java-rules-engine.46999.n3.nabble.com/Drools-Guvnor-API-information-td2471798.html
great job, Do you have some example to create a package in guvnor from my java application
Most people seem to get a ‘javax.jcr.AccessDeniedException’ in the tomcat log when trying this. How were you able to get around that? What were your authentication configurations?