CentrodeInformtica UniversidadeFederaldePernambuco
Vanilson Burgio
[www:vanilson.com] [email:vaab@cin.ufpe.br] A August t2011
Part of this presentation was based on the high quality material gently provided by Dr. Jim Webber, author of the book REST in Practice: Hypermedia and Systems Architecture, for educational purposes.
Agenda
Motivation WebArchitecture IntroductiontoREST PracticalExample WebTunneling CRUDweb bservices i
Motivation
Thewebhasradicallytransformedthewayweproduceand shareinformation
Internationalecosystem ofapplicationandsevices
Wecansearch,combine,aggregate,transform,replicate,cacheandarchive informationthatunderpinstodaysdigitalsociety!
WebArchitecture
Acaotic place:mixof business, research government, research, government social, social and individualinterests Anarchicarchitecture:thousands ofsimple,smallscaleinteractions betweenagents andresources thatusethefounding technologies h l i of fHTTPand dthe h URI
WebArchitecture
Principles and technologies
URI andresources playingaleading role Caches forscalability Services boundaries support
Isolation so at o and a dIndependent depe de tevolution e o ut o o of functionality encouraging loose coupling
WebAsan ApplicationPlatform
The most pervasive middleware!!
D Despite it the th amount t of fresearch hand ddevelopment d l tthat th thas h gone intoseveralplatforms,noneofthemhasmanagedtobecomeas pervasive astheWebistoday
WebsMiddleware:setofwidelydeployedand commoditizedelements:webserversthathostresources, proxies,caches,contentdeliverynetworks,etc Together,theseelementssupportthedeploymentofa planetary l t scale l network t kof fsystems t without ith tresorting ti to t intricateobjectmodelsorcomplexmiddlewaresolutions.
7
Loose Coupling
Services change without notification There isnoexplicity mechanisms tosupport information integrity HTTPusesstatuscode...Broken links.
8
H How t building to b ildi computer t systems t in i awebcentric way (embracing the webs architectural principals)? principals)?
10
REST!!
But, But ,what doesitmean mean? ?
11
Architectural Style
RESTisasetofprinciplesthatdefinehowWebstandards,suchas HTTPandURIs,aresupposedtobeused
12
Key RESTPrinciples
IfyouadheretoRESTprincipleswhiledesigningyour application youwillendupwithasystemthatexploitsthe application, Websarchitecturetoyourbenefit
KeyPrinciples
Identification d f of f resources (URI) ( ) ManipulationofresourcesthroughREPRESENTATIONS Hypermediaastheengineofapplicationstate Uniform Interfaceconstraint
13
14
AURItakestheform<scheme>:<schemespecificstructure>
Thescheme defineshowtherestoftheidentifieristobeinterpreted
15
TermsusedontheWebtorefertoidentifiers
16
Resource Representations
Eachidentifierisassociatedwithoneormorerepresentations ARepresentation isatransformationoraviewofaresource resources sstateataninstant intime Resource representation formats
The resources view isencodedinoneormoretransferableformats,suchasXHTML,Atom,XML, JSON,plaintext,commaseparatedvalues,MP3,or JPEG.
Humanfriendly
machinefriendly
17
Resource Representations
Content negotiation mechanism
Thereisamisconceptionthatdifferentresourcerepresentations shouldeachhavetheir own URI(notion popularizedbytheRails framework)
resourceterminateURIswith.xmlor.json toindicateapreferredformat http://restbucks.com/order.xml orhttp://example.org/order.json
MultipleresourcerepresentationsaddressedbyasingleURI
18
19
20
Uniform InterfaceConstraint
ThesetofverbssupportedbyHTTPGET,POST,PUT,DELETE, OPTIONS HEAD, OPTIONS, HEAD TRACE TRACE,CONNECT CONNECT,andPATCHformsasufficiently generalpurposeprotocoltosupportawiderangeofsolutions
UsestandardMethods
GET:retrieveinformation,possiblycached PUT:UpdateorcreatewithknownID POST:Createorappendsubresource DELETE:(logically) (l i ll )remove
21
Functionalities listorders
listcustomers getorderdetails Listordersforcustomer Deletecustomer Addorderitem
g getcustomerdetails
Updatecustomer Cancelorder Addcustomer Submitorder Updateorder
Example:onlineshop
24
Approachdifferences Thefirstapproach
Many
Many
25
Approachdifferences Thesecondapproach
Many
Many
26
RichardsonmaturitymodelfortheWeb, notjustREST...
RESTisabrilliant architecturalstyle ButtheWeballowsfor morethanj justRESTful systems Theresaspectrumof maturityofservicestyles
Fromcompletelybonkers tocompletelyRESTful
WebTunnelling
WebTunnelling
WebServicestunnelSOAPoverHTTP
UsingtheWebasatransportonly Ignoringmanyofthefeaturesforrobustnessthe Webhasbuiltin
ManyWebpeopledothesame!
URItunnelling,POXapproachesarethemost popularstylesontodaysWeb WorsethanSOAP! Butthey yclaimto
Lessmetadata!
belightweight andRESTful
RichardsonModelLevel1
LotsofURIs
Butreallyhasamore level0mindset
Doesntunderstand HTTP
Otherthanasa transport
Nohypermedia
URITunnellingPattern
WebserversunderstandURIs URIshavestructure Methodshavesignatures CanmatchURIstructuretomethodsignature
http://restbucks.com/PlaceOrder?coffee=latte&size=large&milk=whole&comsumelocation=togo
service
method
arguments
mapsto
OnTheWire
ServerSideURITunnellingExample
public void ProcessGet(HttpListenerContext context) { // Parse the URI Order order = ParseUriForOrderDetails(context.Request.QueryString); string response = string.Empty; if (order != null) { // Process the order by calling the mapped method var orderConfirmation = RestbucksService.PlaceOrder(order); response = "OrderId=" + orderConfirmation.OrderId.ToString(); } else { response = "Failure: Could not place order."; } // Write to the response stream using (var sw = new StreamWriter(context.Response.OutputStream)) { sw.Write(response); } }
ClientSideURITunnelling
public OrderConfirmation PlaceOrder(Order order) { // Create the URI var sb = new StringBuilder("http://restbucks.com/PlaceOrder?"); StringBuilder("http://restbucks com/PlaceOrder?"); sb.AppendFormat("coffee={0}", order.Coffee.ToString()); sb.AppendFormat("&size={0}", order.Size.ToString()); pp ( { } , order.Milk.ToString()); g()); sb.AppendFormat("&milk={0}", sb.AppendFormat("&consume-location={0}", order.ConsumeLocation.ToString()); // Set up the GET request var request = HttpRequest.Create(sb.ToString()) as HttpWebRequest; request.Method = "GET"; // Get the response var response = request.GetResponse(); // Read the contents of the response OrderConfirmation orderConfirmation = null; using (var sr = new StreamReader(response.GetResponseStream())) { var str = sr.ReadToEnd(); // Create an OrderConfirmation object from the response orderConfirmation = new OrderConfirmation(str); } return orderConfirmation; }
URITunnellingStrengths
Veryeasytounderstand Greatforsimpleprocedurecalls Simpletocode
Doitwiththeservlet API,HttpListener, IHttpHandler,RAILS,whatever!
Interoperable p
ItsjustURIs!
URITunnellingWeaknesses
ItsbrittleRPC! Tightcoupling,nometadata
NotypingorreturnvaluesspecifiedintheURI
POXPattern
Webserversunderstandhowtoprocess requestswithbodies
Becausetheyunderstandforms
Andhowtorespondwithabody
Becausethats howtheWebworks
POXusesHTTPPOSTtotransferXML documentsbtwsystems
RichardsonModelLevel0
Singlewellknown endpoint
NotreallyURIfriendly
Doesntunderstand HTTP
Otherthanasa transport
Nohypermedia
POXontheWire
POST/Pl /PlaceOrder O d HTTP/1 1 HTTP/1.1 ContentType: application/xml Host: restbucks.com ContentLength: 361
clientapplication domain
<Order xmlns="http://restbucks.com"> <CustomerId>abcd</CustomerId> <ConsumeAt>takeAway</ConsumeAt> <Items> <Item> <Name>latte</Name> <Quantity>1</Quantity> <Milk>whole</Milk> <Size>small</Size> </Item> <Item> <Name>cookie</Name> <Kind>chocolate chip</Kind> <Quantity>2</Quantity> </Item> </Items> </Order>
HTTP/1.1 200 OK ContentLength: 93 ContentType: application/xml; charset=utf8 Server: MicrosoftHTTPAPI/2.0 Date: Mon, 04 Aug 2008 18:16:49 GMT <OrderConfirmation xmlns="http://restbucks.com"> <OrderId>1234</OrderId> </OrderConfirmation>
POXArchitecture
client li application li i domain d i savas
1
Localmethodcall
jim
ian
10
Localmethod return
waiter
6
Localmethodcall return
clientside dispatcher
2
XMLdocument intoHTTPclient
XMLdocument fromHTTPclient
XMLdocument intoHTTPresponse
serverside dispatcher
4
XMLdocument fromHTTPclient
200OK+XML payload
HTTP client
HTTPPOST+XML payload
HTTP server
object
dispatchercode
communication
.NetPOXServiceExample
private void ProcessRequest(HttpListenerContext context) { g verb = context.Request.HttpMethod.ToLower().Trim(); q p string switch (verb) { case "post": CheckHTTPVerb(we { // Everything's Everything s done with post in this case wantPOST) XmlDocument request = new XmlDocument(); Dispatchitforprocessing request.Load(XmlReader.Create(context.Request.InputStream));
} ...
GetXMLresult,andgetbytes
ReturnXMLbytestoclient
JavaPOXServlet
public class RestbucksService extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Initialization code omitted for brevity try { requestReader = request.getReader(); request getReader(); responseWriter = response.getWriter(); String xmlRequest = extractPayload(requestReader); Order order = createOrder(xmlRequest); OrderConfirmation confirmation = restbucksService.placeOrder(order); embedPayload(requestWriter, confirmation.toString()); } finally { // Cl Cleanup code d omitted itt d f for b brevity it } }
C#POXClientExample
public OrderConfirmation PlaceOrder(string customerId, Item[] items) { // Serialize our objects XmlDocument requestXml = CreateXmlRequest(customerId, items); var client = new WebClient(); var ms = new MemoryStream(); requestXml.Save(ms); client.Headers.Add("Content-Type", "application/xml"); ms = new MemoryStream(client.UploadData("http://restbucks.com/PlaceOrder", null, ms.ToArray())); var responseXml = new XmlDocument(); responseXml.Load(ms); return CreateOrderConfirmation(responseXml); }
JavaApacheCommonsClient
public class OrderingClient { private static final String XML XML_HEADING HEADING = "<?xml <?xml version=\"1.0\"?>\n"; private static final String NO_RESPONSE = "Error: No response."; public String placeOrder(String customerId, customerId String[] itemIds) throws Exception { // XML string creation omitted for brevity // ... String response = sendRequestPost(request, "http://restbucks.com/PlaceOrder"); Document xmlResponse l = DocumentBuilderFactory.newInstance() .newDocumentBuilder().parse( new InputSource(new StringReader(response))); // XML response handling omitted for brevity }
private String sendRequestPost(String request, String uri) th throws IOException, HttpException { PostMethod method = new PostMethod(uri); method setRequestHeader("Contentmethod.setRequestHeader( Content type", "application/xml"); method.setRequestBody(XML_HEADING + request); String g responseBody p y = NO_RESPONSE; try { new HttpClient().executeMethod(method); responseBody = new String(method.getResponseBody(), "UTF8"); } finally { method.releaseConnection(); } return responseBody; } }
POXStrengths
Simplicity justuseHTTPPOSTandXML Reuseexistinginfrastructureandlibraries Interoperable
ItsjustXMLandHTTP
Canusecomplexdatastructures
ByencodingtheminXML
POXWeaknesses
ClientandservermustcolludeonXML payload
Tightlycoupledapproach
Nometadatasupport
Unlessyoure usingaPOXtoolkitthatsupports WSDLwithHTTPbinding(likeWCF)
CRUDWebServices:Embracing HTTPasanApplicationProtocol
UsingtheWeb
URItunnellingandPOXusetheWebasa t transport t
JustlikeSOAPwithoutmetadatasupport
CRUDResourceLifecycle
Theresourceiscreated withPOST Itsread withGET Andupdated viaPUT Finallyitsremoved usingDELETE
RichardsonModelLevel2
LotsofURIs UnderstandsHTTP! Nohypermedia
CreatewithPOST
POST /orders <order /> 201 Created Location: /1234 /1234 Ordering Client Ordering Service
POSTSemantics
POSTcreatesanewresource ButtheserverdecidesonthatresourcesURI CommonhumanWebexample:postingto Weblog
ServerdecidesURIofpostingandanycomments madeonthatpost
ProgrammaticWebexample:creatinganew employeerecord
Andsubsequentlyaddingtoit
POSTRequest
POST /orders HTTP/1.1 Host: restbucks.com Content-Type:application/vnd.restbucks+xml Content-Length: 225 RestbucksspecificXML <order xmlns="http://schemas.restbucks.com/order"> <location>takeAway</location> <items> <item> <name>latte</name> < <quantity>1</quantity> tit >1</ tit > <milk>whole</milk> Content <size>small</size> (againRestbucks XML) </item> </items> </order>
content Verb,path,andHTTP version
POSTResponse
HTTP/1.1 201 Created Location: /orders/1234
POSTImplementationwithaServlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) { t try { Order order = extractOrderFromRequest(request); String internalOrderId = OrderDatabase.getDatabase().saveOrder(order); response.setHeader("Location", response.setHeader( Location , computeLocationHeader(request, internalOrderId)); response.setStatus(HttpServletResponse.SC_CREATED); } catch(Exception ex) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } }
ReadwithGET
GET /orders/1234
GETSemantics
GETretrievestherepresentationofaresource Shouldbeidempotent
SharedunderstandingofGETsemantics Dontviolatethatunderstanding!
GETExemplified
GETResponse
HTTP/1.1 200 OK Content-Length: 232 Content-Type: application/vnd.restbucks+xml Date: Wed, 19 Nov 2008 21:48:10 GMT <order d xmlns="http://schemas.restbucks.com/order"> l "htt // h tb k / d " <location>takeAway</location> <items> <item> <name>latte</name> <quantity>1</quantity> <milk>whole</milk> milk whole /milk <size>small</size> </item> </items> <status>pending</pending> </order>
WhenGETGoeswrong
Simple!
Just404 theresourceisnolongeravailable
HTTP/1.1 /1 1 404 Not Found d Content-Type: application/vnd.restbucks+xml Content-Length: 952 Date: Sat, 20 Dec 2008 19:01:33 GMT
Areyousure?
GETagain!
GETissafeandidempotent
Greatforcrashrecovery yscenarios!
IdempotentBehaviour
Anactionwithnosideaffects
Comesfrommathematics
Inpracticemeanstwothings:
Asafeoperationisonewhichchangesnostateatall
E.g.HTTPGET
Anidempotentoperationisonewhichupdatesstateinan absoluteway
E.g.x=4ratherthanx+=2
Andarefaulttolerantbecauseofidempotent b h i behaviour
Justretryinfailurecases
GETJAXRSImplementation
@Path("/") public class OrderingService { @GET @Produces("application/xml") @Path("/{orderId}") public String getOrder(@PathParam( getOrder(@PathParam("orderId") orderId ) String orderId) { try { Order order = OrderDatabase.getDatabase().getOrder(orderId); if (order != null) { return xstream.toXML(order); } else { throw new WebApplicationException(404); } } catch (Exception e) { throw new WebApplicationException(500); } } // Remainder of implementation omitted for brevity }
UpdatewithPUT
PUT /orders/1234 <order />
200 OK
Ordering Client
Ordering Service
409 Conflict
PUTSemantics
PUTcreatesanewresourcebuttheclient decidesontheURI
Providingtheserverlogicallowsit
Butisnotsafe
Itchangesstate!
PUTRequest
PUT /orders/1234 HTTP/1 HTTP/1.1 1 Host: restbucks.com Content-Type: application/xml Content-Length: 386 <order xmlns="http://schemas.restbucks.com/order"> <location>takeAway</location> <items> <item> <milk>whole</milk> <name>latte</name> <quantity>2</quantity> <size>small</size> </item> Updatedcontent <item> <milk>whole</milk> <name>cappuccino</name> <quantity>1</quantity> <size>large</size> </item> </items> <status>preparing</preparing> </order>
PUTResponse
HTTP/1.1 200 OK Date: Sun, 30 Nov 2008 21:47:34 GMT g 0 Content-Length:
Minimalistresponsecontainsno entitybody
WhenPUTgoeswrong
Ifweget5xxerror,or some4xx 4 errorssimply i l PUTagain!
PUTi isid idempotent t t
HTTP/1.1 409 Conflict Date: Sun, 21 Dec 2008 16:43:07 GMT C t t L Content-Length:382 th 382 <order xmlns="http://schemas.restbucks.com/or der"> <location>takeAway</location> <items> <item> <milk>whole</milk> <name>latte</name> / <quantity>2</quantity> <size>small</size> </item> <item> <milk>whole</milk> <name>cappuccino</name> <quantity>1</quantity> <size>large</size> g / </item> </items> <status>served</status> </order>
RemovewithDELETE
DELETE /orders/1234
200 OK
Ordering Client
Ordering Service
DELETESemantics
Stoptheresourcefrombeingaccessible
Logicaldelete,notnecessarilyphysical
Request
DELETE /orders/1234 HTTP/1.1 Host: restbucks.com
Response p
HTTP/1.1 200 OK Content Length: 0 Content-Length: Date: Tue, 16 Dec 2008 17:40:11 GMT
WhenDELETEgoeswrong
Simplecase,DELETEagain!
Deleteisidempotent! DELETEonce,DELETE10timeshasthesame effect:onedeletion HTTP/1.1 404 Not Found Content-Length: 0 Date: Tue, 16 Dec 2008 17:42:12 GMT
WhenDELETEgoesReallyWrong
Some4xx responses i di indicate that h d deletion l i isntpossible
Th Thestate t t of fthe th resource isntcompatible Tryforward/backward compensationinstead
HTTP/1.1 409 Conflict Content-Length: 379 D t Date: T Tue, 16 D Dec 2008 17:53:09 17 53 09 GMT <order xmlns="http://schemas.restbucks.com/or der"> <location>takeAway</location> <items> <item> <name>latte</name> <milk>whole</milk> i / i <size>small</size> <quantity>2</quantity> </item> <item> <name>cappuccino</name> <milk>skim</milk> <size>large</size> <quantity>1</quantity> q y /q y </item> </items> <status>served</status> </order>
CRUDdoesnotmeanWorthless
CRUDisGood?
CRUDisgood
Butits it snotgreat
CRUDstyleservicesusesomeHTTPfeatures Buttheapplicationmodelislimited
OnlysuitabletoCRUDScenarios Suitsdatabasestyleapplications Hence frameworkslikeMicrosoftsAstoria
CRUDhaslimitations
CRUDignoreshypermedia CRUDencouragestightcouplingthroughURItemplates CRUDencouragesserverandclienttocollude
TheWebsupportsmoresophisticatedpatternsthan CRUD!
ResearchActivity
Compare: p
RESTVs SOAP RESTVs SOA RESTVs WS*
Sendareporttovaab@cin.ufpe.br Discussiononthenextclass!!
References
RESTinPractice HypermediaandSystemsArchitecture JimWebber,Savas Parastatidis,IanRobinson Published by OReilly,2010 RESTinPractice ATutorialonWebbasedServices JimWebber,Savas Parastatidis,IanRobinson PresentationforUniversities,sharedbyJimWebber Somesslidesadapted from apresentation forUniversities (RESTin Practice ATutorial lonWeb bbased b dServices) ) shared h d by b Jim Ji W Webber bb
[http://jim.webber.name]
ABriefIntroductiontoRESThttp://www.infoq.com/articles/rest introduction