Groovy Web Services, Part I: REST #s2gx

Speaker: Ken Kousen – Kousen IT, Inc.

  • currently working on book for Manning: "Java and Groovy: The Sweet Spots"
  • "Java is really good for tools and infrastructure. Groovy is good for pretty much everything else."

Two Flavors of Web Services

  • SOAP based
    • SOAP wrapper for payload
    • much like an XML API on a system
    • makes header elements available
    • lots of automatic code generation–tools are very mature
      • stubs, skeletons, proxies, etc. are all written for you
      • sprinkle annotations into your codebase to get a web service out of it
  • REST based
    • everything is an addressable resource (uri)
    • leverage http transport
    • uniform interface (get, post, put, delete)
      • a lot of rest web services available today aren't truly restful–e.g. amazon web services where you have to specify the operation name
      • just invoking methods over the web using URLs, but the request type doesn't matter
  • REST -> Representational State Transfer
    • term coined by Roy Fielding in PhD thesis (2000), "Architectural Styles and Design of Network-Based Software Architectures" (available in HTML online; very readable and thought-provoking)
    • one of the founders of the Apache Software Foundation
    • on the team that came up with the spec for HTTP
  • Idempotent
    • repeated requests give the same result
    • get, put, and delete requests are meant to be idempotent
    • POST is not meant to be idempotent
    • e.g. on put–if you're supposed to get the same result every time, the assumption is that you'd know the uri you're applying this to every time
      • the ID will be in the request somehow
      • assumption here is that you know what the ID is going to be before you do the insert
      • having the ID ahead of time probably isn't going to happen in the real world
    • most people wind up doing POST for inserts and PUT for updates
    • "safe" is another term that comes into play–requests do not change the state of the server
      • GET requests should never change the state of the server
  • Content negotiation
    • each resource can have multiple representaitons
      • e.g. xml or json?
    • request will state which representation it wants
  • RESTful client
    1. asemble url with query string
    2. select the http request verb
    3. select the content type
    4. transmit request
    5. process results
  • Steps for rest above are more cumbersome than SOAP since SOAP does a lot of this for you. With REST you have to deal with all of this yourself.
    • where groovy comes into play, is that it's augmented a lot of these classes to make this easier
    • groovy also shines when you get the results back

EXAMPLE: Google Geocoder

  • The Google Geocoding API — converts address info for latitude, longitude
  • Base URL is http://maps.googleapis.com/maps/api/geocode/output?parameters
    • output is XML or JSON
    • parameters include
      • url encoded physical address
      • sensor = true | false (indicates whether or not the request is coming from a GPS-enabled device)
  • Groovy makes it easy to assemble a query string
    • map of parameters, then collect and join, then deal with the xml


def url = base + [sensor:false, address:[loc.street, loc.city, loc.state].collect { v -> URLEncoder.encode(v, 'UTF-8') }.join(',+')].collect {k,v -> "$k=$v"}.join('&')

def response = new XmlSlurper().parse(url)

  • simple read-only web services are a natural fit for REST, even if a lot of other web services in your organization are SOAP
  • get, post, put, and delete also map very naturally to sql verbs, so simple data management apps are natural for rest
  • content negotiation based on URL, e.g. http://…/xml for xml, http://…/json for json

Twitter API

  • closer to true REST
  • in the middle of changing their API again
  • have been supporting basic authentication with base64 encoding for years, which isn't encrypted
  • twitter API is http://dev.twitter.com/doc
  • twitter is oauth only now

HTTP Clients

  • simple http client in groovy — java.net.URL class
  • get is easy, just access the url
  • def xml = new URL(base).text — returns the text of the entire page
  • post, put, and delete in groovy are similar to java

Building a RESTful Service

  • design your URL strategy
    • what are URLs going to mean, what are http verbs going to mean
  • sample url strategy
    • http://…/songs
      • get returns all songs
      • post adds a new song
      • put, delete not used on this url
    • http://…/songs/id
      • get — return a specific song
      • post — not used
      • put — update song with given id
      • delete — remove song with given id

Groovlet

  • groovy servlet — groovy class that responds to an http request
  • easy to configure
  • provides access to the http methods
  • markup builder called html
  • set up the groovy servlet in web.xml
  • showing code for the various operations in the groovlet
  • main tools we have in groovy for restful web services are the xml slurper and markup builder–makes all this very simple

What does Java bring to the table?

  • one of groovy's principles is to not reinvent stuff that's available in java
  • inevitable that there's a performance penalty for using groovy
  • nice thing is you can mix and match groovy with java and use what's appropriate for individual portions of the application
  • JSR311 – JAX-RS
  • currently JAX-WS is part of Java EE 5 but also part of Java SE 1.6
  • specification for JAX-RS — part of Java EE 6

Libraries for HTTP

  • apache http client
  • groovy http builder
  • rest client available in the groovy http builder
  • typical for groovy: take a java library and make it easier/build on it

Grails

  • grails apps make REST easy
  • can set up mappings to map urls to controllers/methods — this is built in
  • xml marhsalling is dead simple in grails — just use "render foo as XML"
    • works great for xml that doesn't go too deep
    • can always use the markup builder

Downside to REST

  • No WSDL, therefore no proxy generation tools
    • all hand-written code for the plumbing
  • WADL: Web Application Description Language
    • attempt to create WSDL for REST
    • slowly gaining acceptance but not common yet

JAX-RS

  • attempt to do for REST what JAX-WS does for SOAP
  • Jersey — reference implementation for JAX-RS
  • annotation based

Conclusions

  • groovy makes it very easy to build URLs with query strings, invoke urls and get responses, and parse xml response
  • groovy works with JAX-RS reference implementation