Showing posts with label jrules. Show all posts
Showing posts with label jrules. Show all posts

Saturday, June 5, 2010

OSB dynamic routing to JRules

We want to provide a generic proxy to invoke JRules.

We provide a routing table in a jrulesEndpointLookupTable XQuery:

<operations>
<operation>
<name>checkemployee</name>
<endpoint>http://localhost:8080/DecisionService/ws/PV01_RuleApp/1.0/PV01_RuleProject/1.0</endpoint>
</operation>

<operation>
<name>checkcompany</name>
<endpoint>http://localhost:8080/DecisionService/ws/PV01_RuleApp/1.0/PV01_RuleProjectCompany/1.0</endpoint>
</operation>


</operations>


where we identify each Ruleset with an identifier (checkemployee).
The Request payload will specify this identifier (jrulesOperation), together with the JRules payload:

<xsd:element name="DecisionServiceRequest">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element name="jrulesOperation" type="xsd:string"/>
            <xsd:element name="jrulesPayload" type="xsd:anyType"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>


This is a sample payload:

<dec:DecisionServiceRequest xmlns:dec="http://www.ilog.com/rules/DecisionService">
    <dec:jrulesOperation>checkemployee</dec:jrulesOperation>
    <dec:jrulesPayload>
        <par:employeeRequest xmlns:par="http://www.ilog.com/rules/param" xmlns:emp="http://www.acme.com/Employee">
            <emp:EmployeeRequest>
                <emp:SSN>1234-56-7890</emp:SSN>
                <emp:name>Pierre</emp:name>
                <emp:dateOfBirth>1961-02-11</emp:dateOfBirth>
                <emp:employeeType>none</emp:employeeType>
                <emp:salary>20</emp:salary>
            </emp:EmployeeRequest>
        </par:employeeRequest>
    </dec:jrulesPayload>
</dec:DecisionServiceRequest>

where par:employeeRequest is the verbalization of the input parameter in JRules.

The OSB proxy service must:

- extract the jrulesOperation (checkemployee) and payload:

$body/dec:DecisionServiceRequest/dec:jrulesOperation/text()
$body/dec:DecisionServiceRequest/dec:jrulesPayload/node()

- do a lookup on the jrulesEndpointLookupTable to determine the endpoint:

$jrulesEndpointTable/operation[name=$jrulesOperation]/endpoint/text()

- do a Service Callout by using the Routing Option element to set the URI


- return as a body the response from JRules:

replace . in variable body with variable jrulesResponse

Tuesday, June 1, 2010

JRules: deploying a Ruleset as a Web Service

Something cool is "Import-Rule Studio Samples and Tutorials", a nice one is webdecisionservice. unfortunately it looks like the example is in Java binding, and not XML binding.... If I want to expose the Ruleset as a Web Service I need to use XML binding (is this true?).
XML handling is done with IlrXmlDataDriver.


1)
Create a Java Project, call it PV01_JRulesResources, create a folder xsds and put inside this file:

http://sites.google.com/site/javamonamour/xsds/Employee.xsd?attredirects=0&d=1




2)
New, Rule Project with a BOM, call it PV01_RuleProject
no JAVA XOM
specify the Employee XSD as XML XOM:


3)
Add the Employee and EmployeeResponse XSDs as a parameter to the Ruleset (right click on PV01_RuleProject, properties, Ruleset Parameters, add employee as a IN parameter and verbalization employee, add employeeResponse as an OUT parameter and verbalization employeeResponse)
Don't forget to set the default value of the response to
new com.acme.employee.EmployeeResponse()

otherwise you will get a Null Pointer Exception when accessing it.

4) Code this business rule


if the name of employeeRequest is "Pierre" then
 set the fired of employeeResponse to "TRUE";

else set the fired of employeeResponse to "FALSE";



5) Create a Rule App project, add to it the RuleSet Project

6) Export the RuleApp project to a JAR, open the console http://localhost:8080/res and do "Deploy RuleApp Archive" and install the Rules.

7) click on "Get HTDS WSDL for this ruleset version", copy the WLSD link, go to SOAP UI and create a new Web Services Client project using the WSDL URL

8) you are now ready to test your rule from SOAP-UI! Time to celebrate.



In our case, we will get this SOAP message for test:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dec="http://www.ilog.com/rules/DecisionService" xmlns:par="http://www.ilog.com/rules/param" xmlns:emp="http://www.acme.com/Employee">
<soapenv:Header/>
<soapenv:Body>
<dec:DecisionServiceRequest>
<par:employeeRequest>
<emp:EmployeeRequest>
<emp:SSN>1234-56-7890</emp:SSN>
<emp:name>Pierre</emp:name>
<emp:dateOfBirth>1961-02-11</emp:dateOfBirth>
<emp:employeeType>none</emp:employeeType>
<emp:salary>20</emp:salary>
</emp:EmployeeRequest>
</par:employeeRequest>
</dec:DecisionServiceRequest>
</soapenv:Body>
</soapenv:Envelope>


We can see that we have a operation DecisionServiceRequest which contains a node par:employeeRequest which contains the value EmployeeRequest.

The generic request will be:


<soapenv:Body>
<dec:DecisionServiceRequest>
<par:parameter1Name>

</par:parameter1Name><par:parameter2Name>


</par:parameter2Name>
</dec:DecisionServiceRequest>
</soapenv:Body>


you should get this response:


<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ds="http://www.ilog.com/rules/DecisionService">
<soapenv:Body>
<DecisionServiceResponse xmlns="http://www.ilog.com/rules/DecisionService">
<ilog.rules.outputString></ilog.rules.outputString>
<ilog.rules.firedRulesCount>1</ilog.rules.firedRulesCount>
<employeeResponse xmlns="http://www.ilog.com/rules/param"><EmployeeResponse xmlns="http://www.acme.com/Employee" xmlns:ns0="http://www.acme.com/Employee">
<fired xmlns="http://www.acme.com/Employee">TRUE</fired>
</EmployeeResponse>
</employeeResponse>
</DecisionServiceResponse>
</soapenv:Body>
</soapenv:Envelope>


and the WSDL is here:

http://sites.google.com/site/javamonamour/xsds/rulesetwsdl.wsdl?attredirects=0&d=1


In case of fault, you get this:

<soapenv:Fault>
 <faultcode>soapenv:Server</faultcode>
 <faultstring>Error when executing the ruleset /PV01_RuleApp/1.0/PV01_RuleProject/1.0</faultstring>
 <faultactor>http://www.ilog.com/rules/DecisionService</faultactor>
 <detail>
    <ds:DecisionServiceException>
       <ds:exception>ilog.rules.res.decisionservice.IlrDecisionServiceException: Error when executing the ruleset /PV01_RuleApp/1.0/PV01_RuleProject/1.0
at ilog.rules.res.decisionservice.web.IlrDecisionServiceController.executeRuleset(IlrDecisionServiceController.java:125)

Monday, May 31, 2010

JRules, using Java BOM to pass an input parameter

Having done the tutorial on how to write a Business Rule with Java BOM, once I deploy and try to get the WSDL the RES (Rule Execution Server) tells me:

This ruleset cannot be parsed. It uses a Java XOM, which is not supported by the hosted transparent decision service., error code: XU-WS10010

Yet, the "New Rule Project" gives you a template "Rule Project with a BOM" and it says:

This template creates a rule project using the following standard options :
Java XOM settings. Path on java folders, jars or projects.
Dynamic XOM settings. Path on XML schemas or dynamic XOM files.
Rule project references. Optional rule project dependencies.
In addition, BOM entries and verbalization are automatically created for each XOM specified.
The generated project enables you to edit rules and execute them.




Note: A XOM is a "Execution Object Model".

If you wonder what a "transparent" decision service is, you might have a read here, basically "transparent" means "exposed through WS":

http://publib.boulder.ibm.com/infocenter/brjrules/v7r0m2/index.jsp?topic=/com.ibm.websphere.ilog.jrules.doc/Content/Business_Rules/Documentation/_pubskel/JRules/ps_JRules_Global800.html

"A hosted transparent decision service: this is essentially a ruleset deployed as a Web service. It is installed on the same application server as Rule Execution Server, then integrated with Rule Execution Server." It's also nicknamed htds.

So basically should I resort to using XSDs to specify input parameters, in order to expose my Rules as Web Services? Oh my my.... what an I missing?

JRules exposed via Web Services

Typically you have a RuleApp, which contains several RuleSets.

When you produce a RuleSet, you can write several BusinessRules in it.

Here http://publib.boulder.ibm.com/infocenter/brjrules/v7r0m2/index.jsp?topic=/com.ibm.websphere.ilog.jrules.doc/Content/Business_Rules/Documentation/_pubskel/JRules/ps_JRules_Global800.html it says:

The decision service automatically generates a Web Services Description Language (WSDL) file for each deployed ruleset archive

In our example, helloWorldRuleApp contains helloWorldRuleApp,
and helloWorldRuleApp contains 2 BusinessRule: greetingsItalian and greetingsEnglish.
They will return respectively Buongiorno and Good morning!.

JRules  exposes them automatically via Web Services, the endpoint looks like:

http://localhost:8080/DecisionService/ws/helloWorldRuleApp/1.0/greetingsRuleset/1.0

This will fire all the Rules inside the greetingsRuleset.


The result will be:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ds="http://www.ilog.com/rules/DecisionService">
   <soapenv:Body>
      <DecisionServiceResponse xmlns="http://www.ilog.com/rules/DecisionService">
         <ilog.rules.outputString>Buongiorno
Good morning!</ilog.rules.outputString>
         <ilog.rules.firedRulesCount>2</ilog.rules.firedRulesCount>
      </DecisionServiceResponse>
   </soapenv:Body>
</soapenv:Envelope>


that is:
ilog.rules.outputString is the output of all the Rules invoked
ilog.rules.firedRulesCount is the count of the rules fired


The WSDL associated to the Web Service is:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://www.ilog.com/rules/DecisionService" xmlns:tns="http://www.ilog.com/rules/DecisionService" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.ilog.com/rules/DecisionService" xmlns:param="http://www.ilog.com/rules/param" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:import namespace="http://www.ilog.com/rules/param"/>
<xsd:element name="DecisionServiceRequest">
<xsd:complexType>
<xsd:sequence>
</xsd:sequence>
</xsd:complexType>

</xsd:element>
<xsd:element name="DecisionServiceResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ilog.rules.outputString" type="xsd:string"/>
<xsd:element name="ilog.rules.firedRulesCount" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

<xsd:element name="DecisionServiceException">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="exception" nillable="false" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<xsd:schema targetNamespace="http://www.ilog.com/rules/param" xmlns:ns0="http://www.ilog.com/rules/param"/>

</wsdl:types>
<wsdl:message name="DecisionServiceSoapResponse">
<wsdl:part name="parameters" element="tns:DecisionServiceResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message name="DecisionServiceSoapFault">
<wsdl:part name="fault" element="tns:DecisionServiceException">
</wsdl:part>
</wsdl:message>

<wsdl:message name="DecisionServiceSoapRequest">
<wsdl:part name="parameters" element="tns:DecisionServiceRequest">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="DecisionServiceJRulesPVHelloWorld">
<wsdl:operation name="executeDecisionService">
<wsdl:input message="tns:DecisionServiceSoapRequest">
</wsdl:input>
<wsdl:output message="tns:DecisionServiceSoapResponse">

</wsdl:output>
<wsdl:fault name="DecisionServiceSoapFault" message="tns:DecisionServiceSoapFault">
</wsdl:fault>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="DecisionServiceSOAP" type="tns:DecisionServiceJRulesPVHelloWorld">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="executeDecisionService">
<soap:operation soapAction="executeDecisionService" style="document"/>

<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="DecisionServiceSoapFault">
<soap:fault name="DecisionServiceSoapFault" use="literal"/>
</wsdl:fault>

</wsdl:operation>
</wsdl:binding>
<wsdl:service name="DecisionServiceJRulesPVHelloWorld">
<wsdl:port name="DecisionServiceSOAPesp50ws17206.crb.acme.net" binding="tns:DecisionServiceSOAP">
<soap:address location="http://localhost:8080/DecisionService/ws/helloWorldRuleApp/1.0/greetingsRuleset/1.0"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>


Let's watch an example where you pass an XML parameter (thank you David Selman for your excellent presentation, but next time can you ask a beautiful girl to show her face instead of yours :O)? We are all men in this business and seing a girl once in a while would help...):




In fact it's all about invoking a Web Service, the video shows how to do it with a Eclipse Plugin and Axis2 Java generated code.


The way I see it is that there is a DecisionService servlet serving all RuleApps and acting as a Proxy to the Rules Engine.

Friday, May 28, 2010

JRules: Getting Started in 3 minutes (aka JRules for Dummies)

Installation is easy, anyway here
http://www.jaceklaskowski.pl/docs/GettingStartedWithIBMWebSphereILOGJRules7.0.2Trial-installation.pdf

you have some instructions.

After you complete installation, run  IBM WebSphere ILOG JRules V7.0.2/Samples Console

It will take a couple of minutes to start Tomcat. When you see
28-05-2010 09:36:15 org.apache.catalina.startup.Catalina start
INFO: Server startup in 138229 ms

open a browser, Rule Team Server console is:
http://localhost:8080/teamserver
rtsUser1/rtsUser1
rtsConfig/rtsConfig
rtsAdmin/rtsAdmin


and Rule Execution Server console is:
http://localhost:8080/res
resAdmin/resAdmin
resMonitor/resMonitor
resDeployer/resDeployer

Some acronyms:
ILR = ILOG Rule Language
XU = Execution Unit
XOM = XML Object Model


Now, in Eclipse Studio right click, new Rule Project, select Hello World Rule Project. I will call it JRulesPVHelloWorld.
Right click, export Ruleset Archive, ruleProject=/JRulesPVHelloWorld, save to C:\temp\greetings.jar


This will create a IRL, META-INF and RESOURCES directories, with some irl etc files:


main-rfl.irl file:

flowtask main {
  property mainflowtask = true;
  body {
    main#helloworld;
  }
};

ruletask main#helloworld {
  algorithm = default;
  ordering = dynamic;
  body {
    helloworld.*
  }
};



greetings-brl.irl file:

package helloworld {
   rule greetings {
      property status = "new";
      when {
         IlrContext() from ?context;
         evaluate (helloworld.Clock.currentTime.compareTo(new ilog.rules.brl.Time(ilog.rules.brl.IlrDateUtil.getLocalTime(1970, 0, 1, 0, 0, 0, 0, 1))) < 0);
      } then {
         ilog.rules.brl.System.printMessage("Good morning!");
      } else {
         ilog.rules.brl.System.printMessage("Good afternoon!");
      }
   }
}

plus a descriptor file with all the BOM and XOM and METADATA. The b2x files contain some horrendous XML to map Java code into functions that JRules engine can use.... XML! Mothers, keep your childer home, XML is around!


Anyway.... log into http://localhost:8080/res , add RuleApp (I call it PVRuleApp), add Ruleset, I call it PVGreetingsRuleset, and choose as archive the JAR exported from Eclipse...


Click on the WSDL, copy the URL, open SoapUI, create a new project and give it the WSDL url.... and off you go, you are ready to invoke the rule via WS!


Here you can find a more complete presentation, including how to pass parameters to a Ruleset



Thursday, May 27, 2010

OSB integration with JRules through SOAP or EJB

First, let's get familiar with this new baby, JRules; this can be done simply by playing with her.

Documentation:
http://publib.boulder.ibm.com/infocenter/brjrules/v7r0/index.jsp

Download JRules 7.0 binaries (including Tomcat, Derby etc):

https://www14.software.ibm.com/webapp/iwm/web/reg/download.do?source=swg-iwilogjt70&S_PKG=dl&S_TACT=104CBW71<=en_US&cp=UTF-8&dlmethod=http


(you need to have an account with IBM, it's free anyhow)


You can deploy JRules to WebLogic - it's only a bunch of EARs. In this case you access this way:
http://localhost:7001/res

The Console gives you:

Explorer - this contains the Navigator, to display the RuleApps and the Decision Services
You can Create a RuleApp, add RuleSet to a RuleApp by provinding a Ruleset Archive.

Decision Warehouse

Diagnostics

Server Info


In WebLogic console, view the JNDI tree and you will see this:

Binding Name: eis.XUConnectionFactory

Class: ilog.rules.res.xu.cci.IlrXUConnectionFactory


Unfortunately the JRules manual says:

"EJB3 bindings are supported for the JBoss 4.2/5.0, WebSphere 7;0 application servers."

which doesn't sound good if you use WebLogic.


Anyway ilog/rules/res/xu/cci/IlrXUConnectionFactory.class is in these 2 JARs:

C:\Program Files\IBM\WebSphereILOGJRules702\executionserver\lib\jrules-res-execution.jar:
C:\Program Files\IBM\WebSphereILOGJRules702\executionserver\lib\jrules-res-session-java.jar:

Here
http://publib.boulder.ibm.com/infocenter/brjrules/v7r0m2/index.jsp?topic=/com.ibm.websphere.ilog.jrules.doc/Content/Business_Rules/Documentation/_pubskel/JRules/ps_JRules_Global1674.html

it mentions:
"how to execute a simple stateless rule session on a Java EE application server...by using a Java client."

and here

http://publib.boulder.ibm.com/infocenter/brjrules/v7r0m2/index.jsp?topic=/com.ibm.websphere.ilog.jrules.doc/Content/Business_Rules/Documentation/_pubskel/JRules/ps_JRules_Global308.html

a promising tutorial on how to invoke JRules from WebLogic Workshop.

WIP....