Tuesday, February 16, 2010

Minimalistic HTTP Clients with Groovy

The Rocky Mountain Oracle Users Group (RMOUG) Training Days 2010 main technical sessions are going to be held tomorrow and Thursday of this week and I will be presenting two presentations on Groovy and JAX-RS/REST at this conference. It seems like a good time to use Groovy and JAX-RS/REST in the same blog post.

In my previous blog posts on JAX-RS and REST, I have often used RESTClient as the client for testing my deployed services. RESTClient provides a nice graphical user interface and is easy to use. However, if I only need command line test, Groovy is one easy option.

With Groovy, it is easy to take advantage of Java's URI and URL classes. Groovy makes it even easier to use these than in traditional Java because the Groovy GDK-provided String class provides the very convenient toURI() and toURL methods. This is such an easy process that it's actually easier to demonstrate it than to attempt to describe it. So, here is an example in two lines of Groovy code (really one line if you don't count the shebang line):


#!/usr/bin/env groovy
println "http://localhost:8080/rest/resources/movies/2/2".toURL().text


The URL incorporated in the String in the above code points to a JAX-RS-powered REST-based web service I discussed in a previous blog post. The simple service behind that URL returns a "movie of the day" for the month and date given by the two integers at the end of the URL. When the above Groovy code is executed, the output appears as shown in the next screen snapshot.



That simple Groovy code of one real executable line leveraged the power of the Groovy GDK's String and a standard Java class to easily provide the text provided by the resource at the other end of the URL. It doesn't get any easier than that.

The next example is slightly more interesting, but still only requires a small number of lines of Groovy code:


#!/usr/bin/env groovy
address = "http://localhost:8080/rest/resources/movies/2/2"
println "URL: ${address.toURL().text}"
println ""
println "URI: ${address.toURI().toURL().text}"


The output from the above script is shown next.



Because Java's URL class provides significantly more details than just the text available from accessing that URL, this information is readily accessed in a Groovy script. An example of some of this additional information being retrieved is shown in the next code listing and associated output screen snapshot.


#!/usr/bin/env groovy
def NEW_LINE = System.getProperty("line.separator")
def address = "http://localhost:8080/rest/resources/movies/2/2"
def urlInfo = address.toURL()
println "URL: ${address}${NEW_LINE}"
println "URL Text: ${urlInfo.text}${NEW_LINE}"
println "Host/Port: ${urlInfo.host}/${urlInfo.port}${NEW_LINE}"
println "Protocol: ${urlInfo.protocol}${NEW_LINE}"
println "User Info: ${urlInfo.userInfo}${NEW_LINE}"
println "File: ${urlInfo.file}${NEW_LINE}"




For the final simple example in this post, I make the simple script above a little more dynamic by using the first argument to the script as the URL from which to access details.


#!/usr/bin/env groovy
def NEW_LINE = System.getProperty("line.separator")
if (args.length < 1)
{
println "Enter a URL as an argument."
System.exit(-1)
}
def address = args[0]
def urlInfo = address.toURL()
println "URL: ${address}${NEW_LINE}"
println "URL Text: ${urlInfo.text}${NEW_LINE}"
println "Host/Port: ${urlInfo.host}/${urlInfo.port}${NEW_LINE}"
println "Protocol: ${urlInfo.protocol}${NEW_LINE}"
println "User Info: ${urlInfo.userInfo}${NEW_LINE}"
println "File: ${urlInfo.file}${NEW_LINE}"


The corresponding output is shown in the next screen snapshot.



In this post, I have demonstrated how easy it is to mix the best of Groovy with the best of Java to put together a very simple client for accessing HTTP-exposed services such as one finds in many REST applications. I didn't even get to the URL.openConnection() method here, but this method opens up a great deal more information that might be useful for simple testing tools when using HTTP-exposed services.

No comments: