Quick announcement that I’m writing a book! Learning Django REST Framework will be published by Packt Publishing around the middle of next year. Excited!
REST
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
- asemble url with query string
- select the http request verb
- select the content type
- transmit request
- 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
Session Notes – RESTful Grails
Presenter: Scott Davis
Author:
- Groovy Recipes
- GIS for Web Developers (all open source, REST based)
- Groovy/Grails articles on IBM developerworks
- Google “Mastering Grails” or “Practically Groovy”
- Getting Started With Grails, 2d edition — free PDF on InfoQ available soon
RESTful Web Services in Grails
- ebay
- obviously have the web site, but have RESTful services as well
- how much revenue comes in via web services?
- 70%
- only 30% comes through web site itself
- big point here–allowing people to write third-party apps that interface with your “web site” will open up access/revenue
- twitter
- twitter.com only accounts for about 15% of traffic
- 85% of traffic coming through APIs
- programmableweb.com
- list of APIs for major web properties
- important to allow people to access the model without dealing with the view
- more and more, SOAP-based APIs are going away
- It’s all about the data
- don’t bound up the data in a proprietary silo
- view/web site is really just an implementation detail
- web services
- knee-jerk reaction is still to think about SOAP
- SOAP is one implementation of web services
- wasn’t even the first–had XML-RPC
- many successors (RSS, ATOM, REST, etc.)
- technologies have a lifecycle and SOAP is on the decline–been around for 10 years
- Dave Winer, creator of SOAP, said in an interview on ITConversations that SOAP is a failure
- “how long are we supposed to wait for the magic of soap to happen?”
- “With SOAP we tried really hard to create a level playing field for small developers and large developers”
- wanted SOAP to fade into the woodwork and just be how things are done, but never happened
- amazon.com has both SOAP and REST
- REST accounts for 85% of the web service calls
- democracy in action–developers can choose either and they choose REST
- simpler technologies win over time–XML over HTTP much simpler than SOAP
- 12/06 — google officially deprecated their SOAP API
- GData APIs are all REST
- http://code.google.com/apis/gdata
- google calendar api documentation is particularly good
- private/public data, encrypted, etc.
- the ui is important, but don’t ignore the value of the raw data
- question: with REST how do you handle authentication?
- it’s all HTTP with REST so you handle it the same way you would with any other HTTP resource
- SOAP was supposed to be protocol agnostic, but everyone uses HTTP so this is kind of pointless
- only real example is using SOAP over JMS since it’s asynchronous, also guarantees delivery
- but here again, if the web service will never be used on anything OTHER than JMS, why use SOAP instead of straight JMS?
- REST is …
- REpresentational State Transfer
- SOAP used to be “Simple Object Access Protocol”
- acronym has been deprecated–“no longer simple”
- Roy Fielding coined REST term in doctoral dissertation (2000)
- SOAP is a specification
- one implementation of a service-oriented architecture
- RPC, verb-oriented
- not really dealing with objects but actions taken on data
- REST is a set of architectural principles
- resource-oriented, noun-oriented — object oriented
- payload could be in XML, JSON, etc.–format of payload doesn’t matter
- wikipedia has a great comparison between SOAP and REST
- HTTP already has the right verbs available for CRUD
- get, post, put, delete
- REST is the SQL of the internet
- URIs are unique identifiers for resources on the web
- GETful Grails
- lots of REST APIs only support get
- important thing is to make sure you only expose idempotent requests via get
- idempotent — repeat calls can’t change state of data on server
- get requests get cached, bookmarked, etc.
- e.g. using google maps–can pick a point on the map, set zoom level, etc. and email a link that contains the exact state of the map as a get request
- can render objects as XML or JSON easily
- render Airport.list() as XML
- render Airport.list() as JSON
- can also easily customize XML with Groovy Markup Builder
- Content negotiation and the HTTP header
- MIME types used to uniquely identify data types in internet calls
- curl very handy tool for working with REST APIs
- if you grab xml and output to a file, can use tidy to cleanup/indent the xml
- accept header by default is */*
- if want to get back resources in different formats, URI stays the same, but the return type could be text, html, xml, mp3, whatever
- in conf/Config.groovy file can specify whether or not to pay attention to accept header passed by client
- can also specify mime types
- rather common to specify format type in URI (e.g. twitter.com/search.atom returns atom)
- withFormat block used in controller to correspond to data types specified as action.format in url
- e.g. list.xml would return whatever is specified in the withFormat/xml block in the controller
- RESTful Grails
- URI remains the same for resources
- in Grails, can map closures to various HTTP verbs as actions
- e.g. action = [POST:’create’, GET:’retrieve’, PUT:’update’, DELETE:’delete’]
- this is still an XML-RPC approach since we’re still customizing things and saying “they’re asking for this, but this is what they really want”
- can also hijack the index method and switch based on the request type
- switch (request.method) and then have cases for each request type
- can specify the allowed methods by action
- static allowedMethods = [delete:’POST’, save:’POST’]
- goal is to keep uri identical but vary the verb
- curl –request PUT http://myuri
- curl –request POST http://myuri etc.
- can post XML and still use params as long as the xml node names match the domain class property names
- good practice to get into is to always include the response.status code in the response
- 200 for succesful get, 201 for successful create, etc.
- also common to send back a representation of the created resource in 201 responses
- if you have to post custom XML, have to go line-by-line and map nodes and attributes from XML to the domain class properties
- e.g. airport.iata = request.XML.@iata
- check out Castor — like Hibernate for XML
- can set up mapping files to map between XML and POGOs
- Summary
- ui is important, but it’s the raw data that’s important
- owe it to our constituency not to wrap data in a proprietary UI
- future-proofs the application
- nothing wrong with SOA and SOAP, but make sure this is what you really need
- SOAP is on its way out–downside of adoption curve
- REST is the way things are done today