XML-RPC Plugin
Dependency :
compile ":xmlrpc:0.1"
Summary
Description
XML RPC Plugin
The XML RPC plugin allows a GRAILS application to act as an XML RPC server.HOWTO
This is how to set up the GRAILS app to handle an RPC call.The Service
The first step is to implement a Service that extends the Xmlrpc class.class HelloService extends Xmlrpc { boolean transactional = false // say hello def hello(params) { return "hello" } }
The Controller
The second step is to arrange for a controller action to service the RPC call. The contoller needs to inject the HelloService, and then call the service() routine.class MyController { def helloService def xmlrpc = {
helloService.service(request, response)
}
}Doing a call
To check that everything is set up correcty, we can make a call into the server.Here is code that uses John Wilson's groovy-xmlrpc library to call the hello() function.import groovy.net.xmlrpc.*class XMLRPC1 { def static main(args) { def remote = new XMLRPCServerProxy("http://127.0.0.1/app/my/xmlrpc") def response = remote.hello() println "response = " + response.class + " => " + response } }
An More Useful Example
In reality, we need the RPC to do more than say "hello". The example here, is an outline for implmenting the MetaWebLog API for blogs. See http://www.xmlrpc.com/metaWeblogApi for more details.One of the things to notice about this API, is that the function names have dots (.) in them. e.g, metaWeblog.getRecentPosts or metaWeblog.newPost. Also, these functions take a set of parameters, which are passed to the server.How these are dealt with will be shown here.The Service
This service acts as the handler for the MetaWebLog API.To call functions with names that are not legal as groovy method names, there is a mapping from function name to legal method name. This is held in the static property called 'mapping'The parameters to the original call come in as a list of values. For example, the MetaWebLog call:metaWeblog.newPost (blogid, username, password, struct, publish)
class MetaweblogService extends Xmlrpc { boolean transactional = false // this is the mapping from function name to method name static final def mapping = [ 'metaWeblog.getRecentPosts' : 'recentPosts', 'metaWeblog.newPost' : 'newPost' ] // its a new post def newPost(params) { def blogid = params[0] def username = params[1] def password = params[2] def struct = params[3] def publish = params[4] // The struct is a map def newTitle = struct.title def newDesc = struct.description … } // return some recent posts def recentPosts(params) { def count = params[3] def answer = [] answer << [title: "One", description: "Number 1"] answer << [title: "Two", description: "Number 2"] return answer }}
The Controller
This is set up exactly the same way as before.class MyController { def metaweblogService def xmlrpc = {
metaweblogService.service(request, response)
}
}