« DevCentral: Comprehensive Article on BigIP Load-Balancing Algorithms | Main | Microsoft Store Offer: 40% Off Coupon »

01/10/2010

Making XMLRPC Requests with Google App Engine Java

I started playing with Google App Engine - Java and thought an interesting place to start would be xmlrpc requests.   I soon learned though that the inability of app engine applications to open sockets imposed a severe limitation (i.e. "It won't work") on the Groovy XMLRPC module and I was left with figuring out a new way to do it.  Thinking that there really isn't anything too special about xmlrpc requests and that it is still just an http post, I again wondered, "how hard could this really be?"  Two frustration-filled weeks later, a solution!

Initially, I thought about using the URLFetch service built in to GAE because it is built-in but trying and failing to override the user-agent prompted a switch to HTTPBuilder, (and specifically, HttpUrlClient).

After running some wireshark traces of my bling script in action and also reviewing the specification, XMLRPC requests all contain the following elements:

  • A User-Agent must be set.
  • The content-type must be set to "text/xml"
  • Obviously, the http request method is a POST
  • content-length must be specified and correct

HTTPBuilder takes care of the first and last bullet while providing all the functionality needed to customize the request as needed.  Below is a sample HttpUrlClient request:

def url = 'http://blogsearch.google.com/ping/RPC2'
def http = new HttpURLClient(url: url)
def resp = http.request( )

Line 3 above is where all the customization needed to go. From the bullets above, I know I need to specify that this request's method is an http post, that the content type needs to be set to 'text/xml', and to satisfy my vanity, I specify a custom User-Agent. I also want to take advantage of keep-alives if possible and I'm also specifying an Accept header.

 

One other item that I need to specify is the post body. The post body contains the actual method call that the XMLRPC endpoint is supposed to process. Initially, I thought it would be fine if I were to simply set a variable named xmlreq to the string below and then set a body property in the request.

xmlreq = """
<?xml version="1.0"?>
<methodCall>
<methodName>weblogUpdates.ping
<params>
<param>
<value>Someblog</value>
</param>
<param>
<value>http://spaces.msn.com/someblog</value>
</param>
</params>
</methodCall>
"""

This, however, wound up failing because the XMLRPC servers (in many but not all cases) hated the xml in my request. Instead, I ended up using MarkupBuilder to create the XML Request. Below is the markup builder code used to generate the XML request:

def xmlreq = new StringWriter()
xml = new MarkupBuilder(xmlreq).methodCall {
    methodName { mkp.yield ( 'weblogUpdates.ping' ) }
    params {
        param { value { string { mkp.yield ( "${blogTitle}" ) } } }
        param { value { string { mkp.yield ( "${blogUrl}") } } }
    }
}

Now I have completed the customization and I am now using a request similar to the one below:

def resp = http.request(method: POST, contentType: 'text/xml', body: xmlreq, requestContentType: XML, headers:['Accept':'text/xml','User-Agent':'Bling!','Connection':'keep-alive'] )

The final version of a working XMLRPC ping request using Gaelyk and Google App Engine - Java:

def xmlreq = new StringWriter()
xml = new MarkupBuilder(xmlreq).methodCall {
    methodName { mkp.yield ( 'weblogUpdates.ping' ) }
    params {
	param { value { string { mkp.yield ( "${blogTitle}" ) } } }
	param { value { string { mkp.yield ( "${blogUrl}") } } }
    }
}

def url = 'http://blogsearch.google.com/ping/RPC2'
def http = new HttpURLClient(url: url)
def resp = http.request(method: POST, contentType: 'text/xml', body: xmlreq, requestContentType: XML, headers:['Accept':'text/xml','User-Agent':'Bling!','Connection':'keep-alive'] )

TrackBack

TrackBack URL for this entry:
https://www.typepad.com/services/trackback/6a01156fbc6fe6970c0120a7bccdd2970b

Listed below are links to weblogs that reference Making XMLRPC Requests with Google App Engine Java:

Comments