Update: drools-server features/configuration were changed, please read the updated post here
Hi everyone, last week I was working on a new version of the Drools Execution Server. The goal of this new version was to get the new XStream/JAXB Drools Camel integration to execute commands using a simple service that can be accessed using the RestWS and SOAP protocols. Similar to the previous version, the Drools Execution Server is a simple WAR file that can be deployed on a JBoss AS or any other servlet container.
But the big new feature is the ability to use both stateful and stateless knowledge sessions that can be accessed throught REST and SOAP at the same time.
You must note that in the past, the old drools-server saved the following information in order to create only stateless knowledge session:
This information was stored in a file called <session>.properties, where <session> is the name of the stateless session that was used in the request to reference a specific state knowledge session, that in the previous version can only contain a single rule file.
This approach was extended with the concept of Knowledge Context Profiles. Each Knowledge Context Profile let us define more complex execution scenarios. Now we can define Stateful and Stateless sessions with more that one Knowledge resource, using different marshallers to send and recieve the information that we will use to interact with this remote sessions.
Profiles can be configured through a simple profiles.xml file, which resides inside the WAR file, and can contain multiple Knowledge Context Profiles definitions, as in the following XML example:
<?xml version="1.0" encoding="UTF-8" ?> <profiles> <knowledge-context-profile id="ksession1"> <session-type>stateful</session-type> <change-sets> <file>changesets/change-set-1.xml</file> </change-sets> <marshaller>jaxb</marshaller> <jaxb-models> <file>model/person.xsd</file> </jaxb-models> <startup-commands> <command> <![CDATA[ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1" xmlns:ns2="http://drools.org/model"> <insert out-identifier="santa"> <object xsi:type="ns2:person" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ns2:name>santa</ns2:name> <ns2:age>99</ns2:age> </object> </insert> </batch-execution> ]]> </command> </startup-commands> </knowledge-context-profile> <knowledge-context-profile id="ksession2"> <session-type>stateless</session-type> <marshaller>xstream</marshaller> <change-sets> <file>changesets/change-set-2.xml</file> </change-sets> </knowledge-context-profile> </profiles>
As you can see to configure each knowledge-context-profiles you need to set up the following information:
- id: the session identifier (required)
- session-type: stateless/stateful (required)
- change-sets: here you can add the changesets that contains references to the rules to be used on the session
- jaxb-models: this is only if you wanted to use jaxb-commands and define the model with an XSD model definition (required only when using jaxb)
- classes-names: classes that you could include on jaxb context (required on jaxb)
- startup-commands: here you can add xml commands to be executed on the session startup.
Actually the drools server was tested on JBoss AS 5.X and JBoss AS 4.2.3, but should work on any servlet container. Just copy the .war file on the deploy folder and configure the profiles.xml file inside the /WEB-INF/classes directory.
Note: to deploy in JBoss AS 4.X (and probably another servlet containter) you need to modify the cxf.xml server configuration file located inside /WEB-INF/. You need to replace the next lines
<bean id="knowledgeService" class="org.drools.server.KnowledgeService" > <property name="packageScanClassResolver"> <ref local="jbossResolver" /> </property> </bean> <bean id="jbossResolver" />
<bean id="knowledgeService" class="org.drools.server.KnowledgeService" /> to make it work.
This will change how Apache Camel will interact with the JBoss AS5 classloader, pretty simple.
On this new version we are using the Drools Commands API in XML form. Take a look at the following example:
BatchExecutionCommand executionCommand = new BatchExecutionCommand(); InsertObjectCommand insertCommand = new InsertObjectCommand(); insertCommand.setObject(new Person("lucaz")); insertCommand.setOutIdentifier("person1"); executionCommand.setLookup("ksession1"); executionCommand.getCommands().add(insertCommand); String xml = BatchExecutionHelper.newXStreamMarshaller().toXML(executionCommand);
With this lines you will get the xml command representation, using xstream marshaller, that you can use to interact with the drools execution server:
<batch-execution lookup="ksession1"> <insert out-identifier="person1" return-object="true"> <org.drools.pipeline.camel.Person> <name>lucaz</name> </org.drools.pipeline.camel.Person> </insert> </batch-execution>
Let’s test the RestWS service by following this steps:
1) Create an Apache HttpClient instance and configure it with the drools-server ip address and port:
HttpClient httpClient = new HttpClient(); httpClient.getHostConfiguration().setHost("127.0.0.1", 8080);
2) Create a PosthMethod and send the xml command to the URI /drools-server/services/rest/execute
PostMethod postMethod = new PostMethod("/drools-server/services/rest/execute"); postMethod.addParameter("command", xmlCommand);
3) Execute the method. If the execution was succesfull you will got a HTTP Response Code OK (200) otherwise a BAD_REQUEST (400) response code will be thrown to the client.
httpClient.executeMethod(postMethod); assertEquals(200, postMethod.getStatusCode());
4) And finally, get the execution response
String response = postMethod.getResponseBodyAsString();
Here’s one way to use the SOAP interface with Apache CXF:
1) Create a JaxWsProxyFactoryBean, set the KnowledgeServiceSoap (that could be generated with the WSDL exposed at http://127.0.0.1:8080/drools-server/services/soap?wsdl ) as the Service Class and the URL
JaxWsProxyFactoryBean clientFactory = new JaxWsProxyFactoryBean(); clientFactory.setServiceClass(KnowledgeServiceSoap.class); clientFactory.setAddress("http://127.0.0.1:8080/drools-server/services/soap");
2) Create the KnowledgeServiceSoap client and execute the xml command
<span style="font-size: x-small;">KnowledgeServiceSoap client = (KnowledgeServiceSoap) clientFactory.create(); String response = client.execute(xmlCommand);</span>
Future Steps (in development)
Currently I’m working on a new Guvnor module that will let us define the Knowledge Context Profile with a guided editor (without write XML!), and with a similar change-sets structure. Also you could add drools-server instance and do simple operations, as send commands to execute, check the server status and others features.
Note: Drools Execution Server is not merged into the trunk, but we are working to merge it as soon as possible and include this features in the M2 release. Please, let me kwow what do you think when M2 is ready!