Runtime components : Channels components : SMS handler : Development using the SMS handler : Example: account transfer
  
Example: account transfer
In this example, an SMS solution for account transferring by sending short messages is created. The message format is:
FT <Customer ID=""> {Source account number} <Payee nick=""> <Amount>
<>: mandatory
{}: optional
This service is only available during 9:00am - 20:00pm.
Install the SMS gateway server and do the configuration.
The knowledge about the SMS gateway is needed to develop the SMS solution according to the specific gateway. Use the SMS gateway named gateway A. The gateway is installed in machine 9.186.64.161 and the service port is 9501. Create a user test2 for the application.
This graphic is described in the surrounding text.
Development using UDTT framework and UDTT SMS Handler
1 Create an enterprise application project named SMSEAR, create a dynamic web project named SMSWeb. Copy the bttchannels.jar, bttcore.jar, bttruleprovider.jar into the EAR project and add them to build path and J2EE dependency.
2 Right click the SMSWeb project, and select BTT Tools->Add BTT Nature. This step creates a default btt.xml file under the definitionfolder. Add the following code into the btt.xml:
<kColl id="sms"> <field id="encoding" value="UTF-8"/>
<field id="requestHandler"
value="com.ibm.btt.channel.sms.SMSRequestHandler"/>
<field id="presentationHandler"
value="com.ibm.btt.channel.sms.SMSPresentationHandler"/>
<!-- channel policy configuration -->
<field id="channelPolicyHandler" value="com.ibm.btt.test.MyC hannelPolicyHandler"/>
<field id="ruleService" value="javaCodeChannelRuleService"/>
</kColl>
3 Create the other UDTT definition files: format.xml, operation.xml, processor.xml, invoker.xml. The content can be left empty as the data in these definition files are not used here.
4 Create the following UDTT definition files with the sample code:
data.xml
<data.xml>
<!-- Data collection for the branch context--> <kColl id="branchData"
dynamic="true">
<field id="BranchId"/>
<field id="REPLY_SMS_MSG"/>
<iColl id="titles" size="2">
<kColl id="title">
<field id="name"/>
<field id="value"/>
</kColl>
</iColl>
</kColl>
<!-- Data collection for the html session context--> <kColl
id="sessionData">
</kColl>
</data.xml>
context.xml
<context.xml>
  <!--root context-->
  <context id="branchServer" type="branch"
           parent="nil">
     <refKColl refId="branchData"/>
     <refService alias="realCSServer" refId="realCSServer"                  type="cs"/>
  </context>
  <!-- The session context is created by the StartHtmlSession operation -->
  <!-- This context is dynamically chained to the root context by the operation -->
  <context id="htmlSessionCtx" type="session" parent="branchServer">
<refKColl refId="sessionData"/>
</context>

</context.xml>
type.xml
<type.xml>
<type id="String" implClass="com.ibm.btt.base.DataField">
<descriptor id="typeDefault"
implClass="com.ibm.btt.base.types.ext.StringPropertyDescriptor">
<Converter convTypes="default,host"
implClass="com.ibm.btt.base.types.ext.StringConverter"/>
<Validator implClass="com.ibm.btt.base.types.ext.StringValidator"/>
</descriptor>
</type>
<type id="Integer" implClass="com.ibm.btt.base.DataField">
<descriptor id="typeDefault"
implClass="com.ibm.btt.base.types.ext.IntegerPropertyDescriptor">
<param id="initialValue" value=""/>
<Converter convTypes="default,host"
implClass="com.ibm.btt.base.types.ext.IntegerConverter"/>
<Validator implClass="com.ibm.btt.base.types.ext.IntegerValidator"
lowerLimit="10" upperLimit="90"/>
</descriptor>
</type>
</type.xml>
service.xml
<service.xml>
  <!-- Client-Server Service-->
  <CSServer id="realCSServer"
            inactivityClientTimeout="1800000"
            timeBetweenSessionCheck="20000"/>
  <com.ibm.btt.channel.ruleprovider.ilog.ILogRuleProviderService
            id="checkTransferAmountILogRule"
            ruleID="/checkChannelRuleApp/BTTChannelRules"/>   <com.ibm.btt.test.JavaCodeChannelRuleService
            id="javaCodeChannelRuleService"/>

</service.xml>
accountTransferOp.xml
<Op_Account_Transfer>
  <operation context="accountTransferCtx" id="accountTransferOp"
implClass="com.ibm.btt.test.TransferOperation"></operation>
  <context id="accountTransferCtx" type="op">
    <refKColl refId="TransferData"/>
  </context>
  <kColl id="TransferData">
    <field id="custid"/>
    <field id="sourceAccount"/>
    <field id="nickName"/>
    <field id="amount"/>
    <field id="amountLimit"/>
  </kColl>
</Op_Account_Transfer>
1 Create a package named com.ibm.btt.test under src folder. Create the SMS Handler configuration XML file named SMSHandlerConfig.xml in this folder. Add the following code into the SMSHandlerConfig.xml file:
<SMSHandler>
<com.ibm.btt.channel.sms.config.InboundHandlerConfiguration
id="inbound1">
<com.ibm.btt.channel.sms.config.ParameterNames
Injection="parameterNames" fromParamName="sender"
messageIDParamName="msgid" messageParamName="msgdata"/>
<ref Injection="replyMsgOutboundHandler" refId="outbound1"/>
<ref Injection="smsCommands" refId="SMSCommandTable"/>
</com.ibm.btt.channel.sms.config.InboundHandlerConfiguration>
<list id="SMSCommandTable">
<com.ibm.btt.channel.sms.config.CommandMetaData id="Tansfer"
shortCode="FT" bttOperationName="accountTransferOp">
<list Injection="parameters">
<com.ibm.btt.channel.sms.config.CommandParamter name="custid"
type="java.lang.String"/>
<com.ibm.btt.channel.sms.config.CommandParamter name="sourceAccount"
type="java.lang.String" optional="true"/>
<com.ibm.btt.channel.sms.config.CommandParamter name="nickName"
type="java.lang.String"/>
<com.ibm.btt.channel.sms.config.CommandParamter name="amount"
type="java.lang.Double"/>
</list>
</com.ibm.btt.channel.sms.config.CommandMetaData>
</list>
<com.ibm.btt.channel.sms.outbound.BTTOutboundMessageHandler
id="outbound1">
<com.ibm.btt.channel.sms.config.OutboundHandlerConfiguration
Injection="config" hostName="9.186.64.161" port="9501"
programName="api?action=sendmessage" account="tester2"
password="q1w2e3r4">
<com.ibm.btt.channel.sms.config.ParameterNames
Injection="parameterNames" messageParamName="messagedata"
accountParamName="username" passwordParamName="password"
toParamName="recipient"/>
<ref Injection="dlrConfig"
refId="OZEKIOutboundResponseDLRHandlerConfig"/>
</com.ibm.btt.channel.sms.config.OutboundHandlerConfiguration>
</com.ibm.btt.channel.sms.outbound.BTTOutboundMessageHandler>
<com.ibm.btt.channel.sms.config.DLRHandlerConfiguration
id="OZEKIOutboundResponseDLRHandlerConfig">
<com.ibm.btt.channel.sms.config.ParameterNames
Injection="parameterNames" messageIDParamName="messageid"
toParamName="recipient" statusParamName="statuscode"/>
<map Injection="statusCodeConverter">
<entry key="0" value="0"></entry>
<entry key="1" value="1"></entry>
<entry key="2" value="2"></entry>
</map>
<ref Injection="dlrStore" refId="dlrMemoryStore"/>
</com.ibm.btt.channel.sms.config.DLRHandlerConfiguration>
<com.ibm.btt.channel.sms.dlr.DLRMemoryStore id="dlrMemoryStore"/>
</SMSHandler>
2 In the package com.ibm.btt.test, create the following Java file with the sample code: TransferOperation.java
package com.ibm.btt.test;
import com.ibm.btt.base.BTTServerOperation;
import com.ibm.btt.channel.sms.SMSHandlerConstant;
@SuppressWarnings("serial")
public class TransferOperation extends BTTServerOperation {
public void execute() throws Exception {
try {
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}

super.execute();
System.out.println("====== TransferOp Start =====with context: \n"+getContext().getKeyedCollection());

if (getValueAt(SMSHandlerConstant.REPLYMSG)==""||getValueAt(SMSHandlerConstant.REPLYMSG)==null)
setValueAt(SMSHandlerConstant.REPLYMSG, "==== Transfer Successfully!==== \n Recipient:"
+getContext().getValueAt("nickName")+"\n Amount:"+getContext().getValueAt("amount")
+"\n Balance: 9201.20");
}
}
JavaCodeChannelRuleService.java
package com.ibm.btt.test;
import java.util.Calendar;
import java.util.Map;
import com.ibm.btt.channel.PolicyResult;
import com.ibm.btt.channel.ruleprovider.java.JavaCodeRuleProviderService;
public class JavaCodeChannelRuleService extends JavaCodeRuleProviderService {
public Map<String> checkRule(Map<String> params) { System.out.println("JavaCodeChannelRuleService: checking the channel rule..."); PolicyResult result = (PolicyResult) params.get("result"); ChannelPolicyData data = (ChannelPolicyData) params.get("data"); Calendar now = data.getNow(); int hours = now.get(Calendar.HOUR_OF_DAY); if (hours >= 20 || hours < 9) { result.reject(); String message = "The Internet Bank is just opening for 9:00-20:00, please try later.”; result.addToMessages(message); } System.out.println("JavaCodeChannelRuleService: the result message is:" + result.getMessages()); return null; } }
</String></String>
MyChannelPolicyHandler.java
package com.ibm.btt.test;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import com.ibm.btt.channel.AbstractChannelPolicy;
import com.ibm.btt.channel.PolicyResult;
import com.ibm.btt.clientserver.ChannelContext;
public class MyChannelPolicyHandler extends AbstractChannelPolicy {
private PolicyResult result;
@Override
protected Map<String> getInputParameter(ChannelContext ctx) { Map<String> input = new HashMap<String>(); result = new PolicyResult(); ChannelPolicyData data = new ChannelPolicyData(); data.setDeviceType(ctx.getDeviceType()); data.setNow(Calendar.getInstance()); input.put("data", data); input.put("result", result); return input; } @Override protected PolicyResult processResult(Map<String> resultMap) { return result; } }
</String></String></String></String>
StartServerServlet.java:
package com.ibm.btt.test;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import com.ibm.btt.base.Context;
import com.ibm.btt.base.ContextFactory;
import com.ibm.btt.config.InitManager;
@SuppressWarnings("serial")
public class StartServerServlet extends HttpServlet implements Servlet {
public void init(ServletConfig arg0) throws ServletException {
try {
final String bttPath = (String) arg0
.getInitParameter("bttConfigPath");
InitManager.reset(bttPath);
Context root = ContextFactory.createContext("branchServer",
true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Update the file web.xml in the SMSWeb project with following code:
<servlet>
<description></description>
<display-name>InitServlet</display-name>
<servlet-name>InitServlet</servlet-name>
<servlet-class>com.ibm.btt.test.StartServerServlet</servlet-class>
<init-param>
<description></description>
<param-name>bttConfigPath</param-name>
<param-value>jar:///definitions/btt.xml</param-value>
</init-param>
<load-on-startup>-1</load-on-startup>
</servlet><servlet-mapping>
<servlet-name>InitServlet</servlet-name>
<url-pattern>/InitServlet</url-pattern>
</servlet-mapping><servlet>
<servlet-name>OZEKIBTTInboundMessageHandler01</servlet-name>
<servlet-class>com.ibm.btt.channel.sms.inbound.BTTInboundMessageHandler</servlet-class>
<init-param>
<description> Configuration File path </description>
<param-name>configFile</param-name>
<param-value>jar:///com/ibm/btt/test/SMSHandlerConfig.xml</param-value>
</init-param>
<init-param>
<description> ID of Inbound handler configuration defined config file </description>
<param-name>inboundConfigID</param-name>
<param-value>inbound1</param-value>
</init-param>
</servlet><servlet-mapping>
<servlet-name>OZEKIBTTInboundMessageHandler01</servlet-name>
<url-pattern>/OZEKIBTTInboundMessageHandler01</url-pattern>
</servlet-mapping>
3 Configure the SMS gateway incoming HTTP URL to be called if an SMS message arrives.
http://localhost:9080/SMSWeb/servlet/OZEKIBTTInboundMessageHandler01?sender=$originator&receiver=$recipient&msgdata=$messagedata&recvtime=$receivedtime&msgid=$messageid
4 Deploy the solution and use mobile phone to do the test. Deploy the EAR to the WebShpere Application Server. Then use the mobile phone to send a transfer command to the SMS gateway number, such as:
FT user01 payee01 1200
After a while, the mobile will receive the reply message:
==== Transfer Successfully!====
Recipient: payee01
Amount:1200.0
Balance: 9201.20
If you send the message not during 9:00am - 20:00pm, then the mobile will receive the reply message:
SMS command is rejected by channel policy. Reason= The Internet Bank is just opening for 9:00-20:00, please try later.
See also
Development using the SMS handler