Introduction
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.
Info |
---|
Before executing this sample, it is recommended that you refer to section Exposing Rules as Services which explains in detail the process of writing and deploying a business rule. |
...
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
service
To execute the service, run the ant
command from the <PRODUCT_HOME>/samples/banking.service
directory to run the Banking Service.
Info |
---|
Before executing this service, 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 testing the service
- 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.
3. In the "Client Operations" widget of the dashboard, invoke the Try-it tool to test the service.
4. In the service's TryIt window, issue a request similar to the following. As the first step, we do a deposit followed by funds withdrawal.
Make a Deposit:
Code Block | ||
---|---|---|
| ||
<amount>2432</amount>
<accountNumber>330021vc</accountNumber> |
Make a withdrawal:
Code Block | ||
---|---|---|
| ||
<amount>200</amount>
<accountNumber>330021vc</accountNumber> |
...
- The service will appear in the Deployed Services page.
- Click Banking Service to access the dashboard of the service.
Since this service is an stateful service, the java client which uses the axis2 session management is necessary for proper execution. Execute the axis2 java client found in <BRS_HOME>/samples/clients directory.
Following is the sample that comes with brs clients. Note how the setManageSession(true) is used to enable axis2 session inorder to execute the stateful request.
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.