« December 2009 | Main | February 2010 »

11 posts from January 2010

01/20/2010

Bling v0.7 Released - Google App Engine Edition

Bling now runs in the cloud, hosted on google app engine.  Although I've only been playing with Groovy for the past couple of months, I thought it would be interesting to try and write a web application.  It seemed like a good evolution path for bling as most folks looking for a service to send out xmlrpc pings will most likely not download Groovy, the XMLRPC module, and the HTTPBuilder module as a first choice.   Although still written with Groovy and HTTPBuilder, Bling now uses Gaelyk as a web application framework.  

No new functionality was added except Bling now sends pings out to Ping-o-matic and FeedBurner again.  It can be reached by pointing your browser to tools.techstacks.com/bling/.  Please let me know what you think.  I am still working on developing a feedback page so this blog is the only mechanism in place right now for questions, comments, concerns, or any other types of feedback for this application.

It is still a little rough around the edges but it works.  It is a port of the bling command line script to a templates and groovlet-based web application.  After submitting, the results page responds back with "Thanks" or "Failed" responses just like the script, which I will probably look at cleaning up.  The stylesheet used on the site is OK but not good enough for me to redesign this blog around.  It takes roughly 10 seconds to get the response once submitted, which I need to see if there is a way to cut that down.  Despite these items, it is the first web application I've ever written and I'm still pretty happy about it.  The previous article I wrote, "Making XMLRPC Requests with Google App Engine Java", details a technique I used to work around an inability to use the XMLRPC module built into Groovy and instead all requests are built on HTTPBuilder's HttpUrlClient.  

The bling command line client will remain on the downloads site.  There will now be two links for bling—one for the console-based version and one for the web application version.

01/17/2010

Microsoft Store Offer: 40% Off Coupon

This offer expired. Please visit Techstacks Promos for the latest promotions and events

If you are a Windows user and are in the market for a new machine, I just got an offer that is worth sharing for 40% select laptops when purchased through the Microsoft Store.  These are listed as "Microsoft Signature PCs" which means, among other things, that these are free of the crapware that typically slows down Windows boxes bought through other retailers or direct from the vendors.

Use Coupon Code MSStore2-PC-40% at checkout.  The offer expires on January 25, 2010.

The coupon is valid on the following models:

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'] )