...
This sample demonstrates the stateful behavior of a rule session through a simple banking application which uses business rules. This sample should be deployed in a stateful axis2 session - i.e. session scope or transport scope.
Sample
...
configuration
Table of Contents | ||||
---|---|---|---|---|
|
Sample
...
rule definition
Rules
Rule 1: Withdrawing is only allowed if the account balance is higher than the requested amount.
Rule 2: 5% credits given if the deposit is higher than 1000.
Facts
There are two facts: A customer made a deposit request
and A customer made a withdraw request
.
Code Block | ||
---|---|---|
| ||
package samples.banking; /** * Account */ public class Account { private String accountNumber; private int balance; public String getAccountNumber() { return accountNumber; } public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; } public int getBalance() { return balance; } public void setBalance(int balance) { this.balance = balance; } public void increment(int value) { balance += value; } public void decrement(int value) { balance -= value; } } package samples.banking; /** * Deposit fact */ public class Deposit { private String accountNumber; private int amount; public String getAccountNumber() { return accountNumber; } public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; } public int getAmount() { return amount; } public void setAmount(int amount) { this.amount = amount; } } package samples.banking; /** * DepositAccept facts */ public class DepositAccept { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } package samples.banking; /** * Withdraw fact */ public class Withdraw { private String accountNumber; private int amount; public String getAccountNumber() { return accountNumber; } public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; } public int getAmount() { return amount; } public void setAmount(int amount) { this.amount = amount; } } package samples.banking; /** * WithdrawAccept fact */ public class WithdrawAccept { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } package samples.banking; /** * WithdrawReject fact */ public class WithdrawReject { private String reason; public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } } |
Rule
Service Configurationservice configuration (service.rsl)
An in-line rule set is used within the service.rsl file as follows.
Code Block | ||
---|---|---|
| ||
<ruleService name="BankingService" scope="transportsession" xmlns="http://wso2.org/carbon/rules" targetNamespace="http://com.test/Banking"> <ruleSet> <rule resourceType="regular" sourceType="inline"> <![CDATA[ package Banking; import samples.banking.Account; import samples.banking.Deposit; import samples.banking.DepositAccept; import samples.banking.WithdrawAccept; import samples.banking.WithdrawReject; import samples.banking.Withdraw; rule "Deposit with amount higher than 1000 in an Existing Account" dialect "mvel" no-loop true salience 6 when $deposit : Deposit( amount > 1000 ) $account : Account( accountNumber == $deposit.accountNumber ) then $account.increment($deposit.amount * 1.05); DepositAccept depositAccept = new DepositAccept(); depositAccept.setMessage("Deposit was successfully done. 5 percentage credits is given because the deposit amount is higher than 1000. Amount was : " + $deposit.amount + ". Your account balance is now : "+ $account.balance); insertLogical(depositAccept); end rule "Deposit with amount higher than 1000 in a new Account" dialect "mvel" no-loop true salience 5 when $deposit : Deposit( amount > 1000) not( Account( accountNumber == $deposit.accountNumber ) ) then Account account = new Account(); account.setAccountNumber($deposit.accountNumber); account.increment($deposit.amount * 1.05); DepositAccept depositAccept = new DepositAccept(); depositAccept.setMessage("Deposit was successfully done.5 percentage credits is given because the deposit amount is higher than 1000. Amount was : " + $deposit.amount + ". Your account balance is now : "+ account.balance); retract($deposit); insert(account); insertLogical(depositAccept); end rule "Deposit in an Existing Account" dialect "mvel" no-loop true salience 4 when $deposit : Deposit( amount <= 1000 ) $account : Account( accountNumber == $deposit.accountNumber ) then $account.increment($deposit.amount); DepositAccept depositAccept = new DepositAccept(); depositAccept.setMessage("Deposit was successfully done. 5 percentage credits would be given if the deposit amount was higher than 1000. Amount was : " + $deposit.amount + ". Your account balance is now : "+ $account.balance); insertLogical(depositAccept); end rule "Deposit in a new Account" dialect "mvel" no-loop true salience 3 when $deposit : Deposit( amount <= 1000) not( Account( accountNumber == $deposit.accountNumber) ) then Account account = new Account(); account.setAccountNumber($deposit.accountNumber); account.increment($deposit.amount); DepositAccept depositAccept = new DepositAccept(); depositAccept.setMessage("Deposit was successfully done.5 percentage credits would be given if the deposit amount was higher than 1000. Amount was : " + $deposit.amount + ". Your account balance is now : "+ account.balance); retract($deposit); insert(account); insertLogical(depositAccept); end rule "Withdrawing Allow" dialect "mvel" no-loop true salience 2 when $withdraw : Withdraw() $account : Account( accountNumber == $withdraw.accountNumber ) eval($account.balance > $withdraw.amount) then $account.decrement($withdraw.amount); WithdrawAccept withdrawAccept = new WithdrawAccept(); withdrawAccept.setMessage("Withdraw was successfully done. Amount was : " + $withdraw.amount + ". Your new account balance is : "+ $account.balance); insertLogical(withdrawAccept); end rule "Withdrawing Deny" dialect "mvel" no-loop true salience 1 when $withdraw : Withdraw() $account : Account( accountNumber == $withdraw.accountNumber ) eval($account.balance < $withdraw.amount) then WithdrawReject withdrawReject = new WithdrawReject(); withdrawReject.setReason("Withdrawing is only allowed if the account balance is higher than the requested amount. Your account balance is : "+ $account.balance); insertLogical(withdrawReject); end ]]> </rule> </ruleSet> <operation name="withDraw"> <input wrapperElementName="withDraw" namespace="http://com.test/withDraw"> <fact elementName="withDraw" namespace="http://com.test/withDraw" type="samples.banking.Withdraw"></fact> </input> <output wrapperElementName="withDrawRespone" namespace="http://com.test/withDraw"> <fact elementName="withdrawAccept" namespace="http://com.test/withDraw" type="samples.banking.WithdrawAccept"></fact> <fact elementName="withdrawReject" namespace="http://com.test/withDraw" type="samples.banking.WithdrawReject"></fact> </output> </operation> <operation name="deposit"> <input wrapperElementName="deposit" namespace="http://com.test/deposit"> <fact elementName="deposit" namespace="http://com.test/deposit" type="samples.banking.Deposit"></fact> </input> <output wrapperElementName="depositRespone" namespace="http://com.test/deposit"> <fact elementName="depositAccept" namespace="http://com.test/deposit" type="samples.banking.DepositAccept"></fact> </output> </operation> </ruleService> |
Executing the
Sampleservice
To execute the sampleservice, run the ant
command from the <PRODUCT_HOME>/samples/banking.service
directory to run the Banking Service.
Info |
---|
Before executing this sampleservice, it is recommended that you refer Exposing Rules as Services which explains in detail the process of writing and deploying a business rule. |
Deploying and
Testingtesting the
Serviceservice
- Deploy the rule service through the BRS management console. You can follow either of the two methods:
- Bundle all artifacts in an .aar file and upload it (Rule Service -> Upload menu).
- Create using the Rule Service wizard UI (Rule Service -> Create menu).
The above steps are discussed in detail in section Exposing Rules as Services. - After deployment, click on List under Services in the main tab of the management console. The service will appear in the Deployed Services page.
- Click Banking Service to access the dashboard of the service.
- Click Try this service in the Client Operations widget of the dashboard to invoke the Try-it tool.
Click deposit in the left pane of the Try-it tool and issue the following request to make a deposit:
Code Block language html/xml <amount>2432</amount> <accountNumber>330021vc</accountNumber>
You would get the following result:
Code Block language html/xml <message>Deposit was successfully done.5 percentage credits is given because the deposit amount is higher than 1000. Amount was : 2432. Your account balance is now : 2432</message>
Click withDraw in the left pane of the Try-it tool and issue another request as follows to make a withdrawal:
Code Block language html/xml <amount>200</amount> <accountNumber>330021vc</accountNumber>
You would get the following response:Code Block language xml <message>Withdraw was successfully done. Amount was : 200. Your new account balance is : 2232</message>
Alternatively, you can click Generate Axis2 Client in the Client Operations widget of the dashboard to invoke the service. A client using generated stub codes is shown below where the codes were generated with the Unpacks the databinding classes check box checked.
Code Block language java package org.wso2.carbon.samples; import org.apache.axis2.AxisFault; import org.wso2.carbon.samples.bankingService.deposit.Deposit; import org.wso2.carbon.samples.bankingService.deposit.DepositAccept; import org.wso2.carbon.samples.bankingService.deposit.DepositE; import org.wso2.carbon.samples.bankingService.stub.BankingServiceStub; import org.wso2.carbon.samples.bankingService.withdraw.*; import java.rmi.RemoteException; public class BankingServiceTestCase { public static void main(String[] args) { try { BankingServiceStub bankingServiceStub = new BankingServiceStub("http://localhost:9763/services/BankingService"); bankingServiceStub._getServiceClient().getOptions().setManageSession(true); DepositE depositRequest = new DepositE(); Deposit deposit = new Deposit(); deposit.setAccountNumber("070229x"); deposit.setAmount(1000); depositRequest.addDeposit(deposit); Deposit[] deposits = new Deposit[1]; deposits[0] = deposit; depositRequest.setDeposit(deposits); DepositAccept[] results = bankingServiceStub.deposit(deposits); String result = results[0].getMessage(); System.out.println(result); WithDrawE withDrawRequest = new WithDrawE(); Withdraw withdraw = new Withdraw(); withdraw.setAccountNumber("070229x"); withdraw.setAmount(500); Withdraw[] withdraws = new Withdraw[1]; withdraws[0] = withdraw; withDrawRequest.setWithDraw(withdraws); WithDrawRespone withDrawRespone = bankingServiceStub.withDraw(withdraws); WithdrawAccept[] withdrawAccepts = withDrawRespone.getWithdrawAccept(); WithdrawReject[] withdrawRejects = withDrawRespone.getWithdrawReject(); String resultWithDraw = withdrawAccepts[0].getMessage(); System.out.println(resultWithDraw); } catch (AxisFault axisFault) { axisFault.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } }
Excerpt hidden true Banking service sample to demonstrate the stateful behavior of a rule session in the WSO2 Business Rules Server.
...