Ouertani Slim was born in Tunisia in 1981. Now he is a software engineer since 2004 and he is Java 6 and Spring certified with 100% and 94% respectively. He is very interested in Java technology, Scala and open source projects. He believes that programming is one of the hardest jobs and most beautiful in the world. Slim has posted 32 posts at DZone. You can read more from them at their website. View Full User Profile

XML-RPC using scala

06.26.2012
| 6090 views |
  • submit to reddit
Purpose Calling remote procedure using XML-RPC and Scala. Introduction

On Telecom IT environment and specially middelware solution, we will rarely do all the work but rather delegate some of business process to other tiers. Web service communications is heavy used between solutions. However, many IT node continues to support older protocols like XML-RPC. Ericsson Intelligent Network (IN) and its subsystem uses AIR Integration Protocol user communication(UCIP) based on a variant of XM-RPC.

Why UCIP ? UCIP is intended for user self services such as Adjustments, Account Refill, and Account Inquiries and to extract account details. UCIP is an IP-based protocol used for integration towards the AIR server from the external application. Why Scala ? UCIP is an XML over HTTP based protocol, which makes it easy to integrate with a central integration point within a network. In addition, Scala can be used to easily create, parse, and process XML documents. XML data can be represented in Scala either by using a generic data representation, or with a data-specific data representation. Scala & XML-RPC Rather than using an precompiled version of XML-RPC library, we will do our home solution using httpclient library from apache :
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.1</version>
</dependency>

UpdateBalanceAndDate


The message UpdateBalanceAndDate is used to adjust balances and expiry dates on the main account and the dedicated accounts. The sample I chooses here is only to update main balance :

Let's start with some helpful class :

1- InParameters class : contains In specific configuration like ip and port
case class InParameters(ip:String,port:Int,user:String,pwd:String,agent:String,url:String)
2- XMLRPCVo abstract class : groups all XML request message like the transaction generated Id and date
object XmlRpcVo {
val f = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ssZ");
}
abstract class XmlRpcVo {
def originTransactionID = System currentTimeMillis
def dateTime:String= XmlRpcVo.f.format(new Date())
}
3- UpdateBalanceAndDateParameter class with extend our XMLRPCVo and contains all data needed by Update main balance operation like subscriber number
case class UpdateBalanceAndDateParameter(subscriberNumber:String,
originNodeType:String,
originHostName:String,
transactionCurrency:String,
amount: Int )
extends XmlRpcVo
4-UCIP suggests to add custom header on XML-RPC message. XmlRpcHttpClient class dialogue with IN nodes using generic execute method
class XmlRpcHttpClient(inp :InParameters) extends LogHelper{

private val httpclient:DefaultHttpClient = client

private [this] def client() =
{
val httpclient = new DefaultHttpClient();

httpclient.getCredentialsProvider().setCredentials(
new AuthScope(inp.ip, inp.port),
new UsernamePasswordCredentials(inp.user, inp.pwd))


httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, inp.agent)
httpclient
}
private [this] def poster(elem:Elem) ={
val httppost = new HttpPost(inp.url)
httppost.addHeader("Content-Type", "text/xml")
httppost.addHeader("Content-Disposition", "form-data; name=\"fname\"; filename=\"request.xml\"")

val comment = new StringBody(""+elem)

val reqEntity = new MultipartEntity()
reqEntity.addPart("fname", comment)
httppost.setEntity(reqEntity)
httppost
}

def execute(requestVo:scala.xml.Elem):HttpResponse = {
try { client.execute(poster(requestVo))}
catch { case e => throw new connectionExecption(e) }
finally { client.getConnectionManager().shutdown() }
}
}
XML-RPC is a Remote Procedure Calling protocol and the body of an XML-RPC request is formatted using XML. A procedure executes on the AIR server and the value it returns is also formatted in XML. The interface to the AIR server interface uses XML-RPC over HTTP. Sending an XML to update the main balance will be using this class

5- UpdateBalanceAndDate class : generates an UpdateBalanceAndDate XML request message
class UpdateBalanceAndDate (ubdp :UpdateBalanceAndDateParameter)  {
def request=
<methodCall>
<methodName>UpdateBalanceAndDate</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>originNodeType</name>
<value>
<string>{ubdp.originNodeType}</string>
</value>
</member>
<member>
<name>originHostName</name>
<value>
<string>{ubdp.originHostName}</string>
</value>
</member>
<member>
<name>originTransactionID</name>
<value>
<string>{ubdp.originTransactionID}</string>
</value>
</member>
<member>
<name>originTimeStamp</name>
<value>
<dateTime.iso8601>{ubdp.dateTime}</dateTime.iso8601>
</value>
</member>
<member>
<name>subscriberNumber</name>
<value>
<string>{ubdp.subscriberNumber}</string>
</value>
</member>
<member>
<name>transactionCurrency</name>
<value>
<string>{ubdp.transactionCurrency}</string>
</value>
</member>
<member>
<name>adjustmentAmountRelative</name>
<value>
<string>{ubdp.amount}</string>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
}
6- UpdateBalanceAndDate companion object is used to parse response and validate the transaction
object UpdateBalanceAndDate {

@throws (classOf[ClientProtocolException])
@throws (classOf[IOException])
def getResponse(response:HttpResponse ):Int= {

try {
val entity = response.getEntity();
if (entity != null) {
val s = EntityUtils.toString(entity)
val elem = XML.loadString(s)

val tuple= for {
x <- (elem \\ "member")
name = (x \ "name" ) .text
code = ( x \ "value" \ "i4" ).text if(name == "responseCode")
} yield (code)

if(tuple.size == 1) {
return tuple(0).toInt
}
return RESPONSE_PARSE_EXCEPTION
}
else { return NULL_RESPONSE }
}
catch {
case _ => return UNEXCEPTED_ERROR_WHILE_PARSE_RESPONSE
}
}
}
7- UpdateBalanceAndDateController controlleur class orchestrate requests and utilities class
class UpdateBalanceAndDateController {

def update(inp: InParameters, ubdp : UpdateBalanceAndDateParameter ):Int={
try {
val c = new XmlRpcHttpClient(inp)
val ubd = new UpdateBalanceAndDate (ubdp)
val rep= c execute(ubd.request)
return UpdateBalanceAndDate.getResponse(rep )
}catch {
case e:connectionExecption => return AIR_EXCEPTION
case e => return UNEXPECTED_CONNECTION__EXCEPTION
}
}
}
Conclusion Create XML message and parse it using scala is like a baby toy and makes using UCIP protocol easier and simpler. This sample can be generalized to the other UCIP messages like GetBalanceAndDate or GetAccountDetails and any other XML-RPC communication.
Published at DZone with permission of its author, Slim Ouertani.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)