Saturday, February 9, 2008

Scala and Lift snippet: taste of XML with Scala and Lift for simple XML over HTTP RPC protocol

The botlist application is a distributed system. Bots/Agents run in the background on some remote machine and send payloads to a web front end server. In this case, a J2EE server (botlist). Here is some of the code that makes that happen.

On the receiving end; a liftweb based application running on Tomcat:

The method remote_agent is associated with the remote_agent URI. It returns a XML response when a GET request is encountered. The remote_agent_send function is used to process POST requests from the stand-alone client.


import java.util.Random
import org.springframework.context.{ApplicationContext => AC}
import org.spirit.dao.impl.{BotListUserVisitLogDAOImpl => LogDAO}
import org.spirit.dao.impl.{BotListSessionRequestLogDAOImpl => SessDAO}
import org.spirit.bean.impl.{BotListUserVisitLog => Log}
import org.spirit.bean.impl.{BotListSessionRequestLog => Sess}
import net.liftweb.http._
import net.liftweb.http.S._
import net.liftweb.http.S
import scala.xml.{NodeSeq, Text, Group}
import net.liftweb.util.Helpers._
import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse, HttpSession}

import org.spirit.lift.agents._

class RemoteAgents (val request: RequestState, val httpRequest: HttpServletRequest) extends SimpleController {

def remote_agent_req : XmlResponse = {
// Cast to the user visit log bean (defined in the spring configuration)
val log_obj = AgentUtil.getAC(httpRequest).getBean("userVisitLogDaoBean")
val log_dao = log_obj.asInstanceOf[LogDAO]
val sess_obj = AgentUtil.getAC(httpRequest).getBean("sessionRequestLogDaoBean")
val sess_dao = sess_obj.asInstanceOf[SessDAO]
val uniq_id = AgentUtil.buildRequestSession(sess_dao, httpRequest, "request_auth", "true")
AgentUtil.auditLogPage(log_dao, httpRequest, "remote_agent")

XmlResponse(
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
<agentmsg>
<botid>serverbot</botid>
<message>Hello my name is serverbot. Would you like some cake?</message>
<status>200</status>
<requestid>{ Text(uniq_id) }</requestid>
<majorvers>0</majorvers>
<minorvers>0</minorvers>
</agentmsg>
</rdf:RDF>)
} // End of Method Request

def remote_agent_send : XmlResponse = {
var payload = ""
S.param("types_payload").map { (u => payload = u) }

Console.println(payload.toString)
if (S.post_?) XmlResponse { (
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
<message>Enjoy your cake</message>
</rdf:RDF>) }
else AgentUtil.invalidXMLResponse
} // End of Method Send

}


The client is a simple main application that connects to that URL and sends the XML payload request.


package org.spirit.spiderremote

import scala.xml._
import java.sql.{DriverManager}
import org.spirit.loadtest.{LoadTestManager}
import scala.collection.jcl.{HashMap, Map}

import org.spirit.spiderremote.model.AgentMessage

object SpiderRemote {

def main(args: Array[String]): Unit = {
Console.println("spider remote")
Class.forName("org.sqlite.JDBC")
val conn = DriverManager.getConnection("jdbc:sqlite:../../../var/lib/spiderdb/contentdb/spider_queue.db")
val stat = conn.createStatement()
Console.println(conn)
val rs = stat.executeQuery("select * from remotequeue")

while (rs.next()) {
Console.println("name = " + rs.getString("url"))
}
// Connect to the server
LoadTestManager.verifySystemDirs
val res_from_req = LoadTestManager.connectURL("http://127.0.0.1:8080/botlist/lift/pipes/types/remote_agent_req", false)
val serv_agent_doc = XML.loadString(res_from_req(1))
val b = serv_agent_doc \\ "message"
Console.println(b)

// Post to server
val m = new java.util.HashMap
val map = new HashMap[String, String](m)
val types_msg_payload = new AgentMessage {
val message = "I enjoyed my cake."
val status = 200
val agentName = "botspiderremote"
val messageReqId = "123"
}

map("types_payload") = types_msg_payload.toXML.toString
val res_from_snd = LoadTestManager.postData(m, "http://127.0.0.1:8080/botlist/lift/pipes/types/remote_agent_send", false)
Console.println(res_from_snd(1))
Console.println("done");
}
}


Because my blog is at low-activity, I don't plan on explaining any further.

No comments: