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)
}
}
The server side is now set up.
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)
passes a list of 5 elements to the method.
Any structured values, such as the struct parameter, are handled properly, and
get passed to the method as a Map.
Return values can be simple types or structured, and are handled correctly.
Here is the outline of the service
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
}}Obvioulsy, this can be extended to implement the full behaviour of the API.
The Controller
This is set up exactly the same way as before.
class MyController { def metaweblogService def xmlrpc = {
metaweblogService.service(request, response)
}
} Calling In
There are many tools that act as the client side for MetaWebLog, so any one of those can be used.
Other things
It is possible to have any number of XML RPC APIs implemented in a GRAILS application, as each one can have its
own controller action and own service.
To make the XML RPC Plugin work, you have to comment out the mime-type for xml in Config.groovy in parameter grails.mime.types. Otherwise Grails will automatically convert the incoming XML into params and the XML RPC Plugin will fail to receive any data from the request.inputStream.
If there are any questions, just email me.
Stuart Clayman
2 Comments
Post a Comment
Site Login