Your SlideShare is downloading. ×
Thinking restfully
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

Thinking restfully

442
views

Published on

Presentation at the Greek Java Hellenic group about the architectural principles of REST

Presentation at the Greek Java Hellenic group about the architectural principles of REST

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
442
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. REST Thinking RESTfully Stelios Gkorilas JHUG 17 Dec 2011
  • 2. Contents 1.  Types of services 2.  What is REST? 3.  Web services and the REST way 4.  Example: S3 5.  Security 6.  Jersey/JAX-RS 7.  CTR JHUG 17 Dec 2011
  • 3. Distributed services •  The everlasting need to (re-)use logic as black box •  Even across different machines and platforms •  Gave birth to distributed objects and several protocols for remoting (e.g. CORBA, DCOM, RMI) •  Web services prevailed because the web is ubiquitous and scalable •  Web services provide the means to integrate disparate systems and expose reusable business functions over HTTP •  Mostly SOAP services up to now in RPC style •  Some serve HTML, JSON, plain text, or binary documents, but most use XML •  WSDL and the WS-* specs •  HTTP is used as the transport service not the application protocol JHUG 17 Dec 2011
  • 4. Service styles •  RPC services •  Message oriented services •  Resource oriented services JHUG 17 Dec 2011
  • 5. RPC style •  The request message identifies the procedure to be executed, and the fixed set of parameters that map directly to the parameters of the remote procedure •  XML-RPC and later the WS-* stack •  Procedure arguments are tightly coupled messages •  Usually flat APIs •  Communication through proxies that have to be regenerated in case of change •  e.g. JAX-WS JHUG 17 Dec 2011
  • 6. Message oriented •  Services that have Message APIs (a.k.a. Document APIs) receive one or more self-descriptive message types at a given URI •  They are not coupled to procedure names hence they can easier change •  They can constitute commands, events or just documents •  They contain values that identify their type and/or handling JHUG 17 Dec 2011
  • 7. making a Google search the SOAP way POST search/beta2 HTTP/1.1 Host: api.google.com Content-Type: application/soap+xml SOAPAction: urn:GoogleSearchAction <?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <gs:doGoogleSearch xmlns:gs="urn:GoogleSearch"> <key>00000000000000000000000000000000</key> <q>jhug user group</q> <start>0</start> <maxResults>10</maxResults> <filter>true</filter> <restrict /> <safeSearch>false</safeSearch> <lr /> <ie>latin1</ie> <oe>latin1</oe> </gs:doGoogleSearch> </soap:Body> </soap:Envelope> JHUG 17 Dec 2011
  • 8. Resource oriented •  It’s like object oriented – Resources are objects •  Resource is the design of data; what we perceive data to be; it is what we think others might find interesting about our data •  Everything can be a resource •  Resources are accessed through a Uniform Interface •  Resources are interconnected •  Resources have multiple representations •  Communication is stateless JHUG 17 Dec 2011
  • 9. Resources •  Everything can be a resource (like everything can be an object) •  A procedure, instances of domain data, files •  Examples: •  A list of search results about ‘Mullus barbatus’ •  An article •  The jhug meeting on Dec 17 •  The latest jhug meeting •  The software version release 1.1.2.3 •  The latest release •  The list of unresolved issues of type ‘bug’ and component ‘Launcher’ •  Every resource should have a unique identifier, a URI •  http://www.jhug.gr/meetings/meet-up/17-dec-2011 JHUG 17 Dec 2011
  • 10. What is REST? •  Architectural style •  Architectural constraints •  A way to evaluate architectures •  Design principles •  Key properties of a simple (not simplistic) application •  The null style: Start with system needs as a whole, without constraints, and then incrementally identifies and applies constraints to elements of the system in order to differentiate the design space •  Representational State Transfer •  You request a resource and a representation of its state is returned JHUG 17 Dec 2011
  • 11. HTTP Example Request GET /meetups/latest HTTP/1.1 Host: www.jhug.gr Accept: application/xml Response HTTP/1.1. 200 OK Date: Sat, 17 Dec 2011 13:45:34 GMT Server: Apache/1.3.6 Content-Type: application/xml; charset=UTF-8 <?xml version="1.0" encoding="UTF-8"?> <meetup xmlns="..."> <occurred date=".."/> <presentations> ... </presentations> <next uri=".."/> </meetup> JHUG 17 Dec 2011
  • 12. HTTP, URIs & XML define the web •  Operations: GET, PUT, DELETE, POST •  And the less known HEAD, OPTIONS •  Headers •  content-type •  Accept-Language •  Media types •  text/plain •  text/xml •  application/atom+xml •  Response codes •  2xx Success •  3xx Redirect •  4xx Client Error •  5xx Server Error •  URIs and URLs define the web •  XML: content attributes and structure An Application protocol for service logic JHUG 17 Dec 2011
  • 13. REST constraints (Fielding dissertation) •  Client/server •  Uniform Interface •  Layered System •  Stateless •  Cache •  Code on Demand JHUG 17 Dec 2011
  • 14. Resources and the uniform interface •  HTTP standard methods: GET, PUT, POST, DELETE •  HEAD and GET should not modify anything •  Idempotent: PUT DELETE GET HEAD •  HTTP is the application protocol defining service behaviors •  GET /meetups/latest instead of getLatestMeetup() •  RPC verbs become REST nouns •  GET the more recent state of the resource •  PUT/POST a representation that alters the state of the resource JHUG 17 Dec 2011
  • 15. Representations •  Representations have media types •  Multiple formats for different needs •  Content negotiation •  Accept: application/json (request) •  Content-Type: application/json (response) •  URI •  /meetups/latest.json JHUG 17 Dec 2011
  • 16. Addressability •  Representations should be addressable •  Increase the surface of the service •  Client can enter the application where convenient •  A URI can never point to more than one resource JHUG 17 Dec 2011
  • 17. Interconnected Resources •  •  •  •  •  •  Resources are not just data but hypermedia Hypermedia as the engine of state Representations contain links to other resources A representation may contain links ot other states of the resource Paths a client can follow Makes clients more resilient to changes <?xml version="1.0" encoding="UTF-8"?> <meetup xmlns="..."> <occurred date="17-12-2011"/> <presentations> <presentation ref="/presentations/title/disruptor"/> <presentation ref="/presentations/title/rest"/> <presentation ref="/presentations/title/sw-dev-practices"/> </presentations> <next ref="/meetings/date/17-01-2011"/> </meetup> JHUG 17 Dec 2011
  • 18. Stateless •  HTTP is stateless •  All information needed for processing part of the request •  No session on the server •  No session ids exchanged (jsessionId, phpSessionId, etc. ) •  Application state belongs to the client •  Resource state alone belongs to the server •  Simplifies server and client logic, allows scalability e.g. http://www.google.gr/search?q=jhug&start=20 JHUG 17 Dec 2011
  • 19. Cacheability •  Conditional queries •  Cacheable when last-modified and etag are used (response headers) •  If- Modified-Since and If-None-Match (request headers) •  304 Response Code when not modified with no entity body •  Cache proxies and other commodity caching technologies JHUG 17 Dec 2011
  • 20. REST Patterns •  Paths for hierarchy •  jhug/discussions/april •  Post for not owned URIs •  Container items •  Jhug/discussions/1342 •  PUT for URIs defined by the client •  Jhug/presentations/rest •  Semicolon (;) or comma (,) for name/value or matrix values •  jhug/presentations/author,gkorilas/rest •  Query string for algorithmic resources •  Jhug/search?q=“rest” JHUG 17 Dec 2011
  • 21. Think Resource Oriented •  Define the data set •  Expose data as resources •  Assign URIs to resources •  Decide the UI commands accepted •  Decide the representations accepted •  Decide the representations served •  Add hypermedia links between them JHUG 17 Dec 2011
  • 22. REST + •  Serve representations suitable for many clients •  The uniform interface allows all http clients to easily consume a suitable representation •  Content negotiation can allow a single URL to serve content to a browser, a JS client that is interested in JSON or a mobile phone client interested in an XML representation •  Cacheable by commodity technologies •  Scalable •  Fail over •  Clients: •  Browser friendly •  Easy support by many languages •  Bookmarkable •  Data formats •  It is the natural way of the web! JHUG 17 Dec 2011
  • 23. REST Security standards JHUG 17 Dec 2011
  • 24. The Amazon S3 Service •  S3 “buckets” and S3 “objects” •  Bucket can only contain objects •  Bucket names are unique in S3 •  Object has a name (key) and content (value) •  Object has a reference to the parent bucket •  Object has metadata key-value pairs; can also be http headers like content-type or content-disposition •  Three types of resources •  List of your buckets (https://s3.amazonaws.com/) •  A particular bucket (https://s3.amazonaws.com/{name-of-bucket}/). There can be up to 100 resources of this type. •  A particular S3 object inside a bucket (https://s3.amazonaws.com/ {name-of- bucket}/{name-of-object} JHUG 17 Dec 2011
  • 25. S3 resources and methods GET HEAD PUT DELETE (/) List your buckets - - - /{bucket} List objects of bucket - Create the bucket Delete the bucket /{bucket}/ {object} Object’s value Object’s and metadata metadata Set the object’s value and metadata Delete the object JHUG 17 Dec 2011
  • 26. S3 Security •  Message digest of the canonical string of the request with a secret key (amazon knows it too) •  {http method}{content-type}{date}{amazon headers}{path} •  Add it to http Authorization: header •  Add it to query string together with expires date to make bookmarkable (https://s3.amazonaws.com/stelinio/rest.pdf# ? Signature=J%2Qu6krT3j0zaaFXjsLbowdfzExQ%3D # &Expires=1162156788&AWSAccessKeyId=0F9RBCLB5274NK TJ4DA3") •  Access policies •  Private, public-read, public-write, authenticated read JHUG 17 Dec 2011
  • 27. HTTP security, OAuth •  http basic •  http digest •  http client certificate •  OAuth •  Delegated user authentication solution - Valet key principle •  Client, server, resource owner (OAuth love triangle) •  client credentials, temporary credentials, and token credentials JHUG 17 Dec 2011
  • 28. Java REST Services •  Java EE 6 specification: JAX-RS •  Jersey: Reference implementation of JSR 311 •  Available as standalone and enterprise JHUG 17 Dec 2011
  • 29. Standalone example setup <servlet> <servlet-name>jersey</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>eu.ema.eudract.rest</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-server</artifactId> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-json</artifactId> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-atom</artifactId> </dependency> JHUG 17 Dec 2011
  • 30. JAX-RS Resources Annotate POJOs @Path("/meetups") @Singleton() public class MeetUpsResource { @GET() @Path("/latest") @Produces("text/plain") public String getLatestMeetUp() { return getDataService().getLatestMeetUp().toString(); } @GET() @Path("/next") @Produces("text/plain") public String getNextMeetUp() { return getDataService().getNextMeetUp().toString(); } @GET() @Produces(MediaType.APPLICATION_JSON) public MeetUps getAllMeetUps() { return getDataService().getAllMeetUps(); } } JHUG 17 Dec 2011
  • 31. Methods & Paths •  @javax.ws.rs.GET •  @javax.ws.rs.PUT •  @javax.ws.rs.POST •  @javax.ws.rs.DELETE •  @javax.ws.rs.HEAD •  Paths: Most specific match wins JHUG 17 Dec 2011
  • 32. JAX-RS Injection •  @javax.ws.rs.PathParam •  values from URI template parameters •  @javax.ws.rs.MatrixParam •  URI’s matrix parameters. •  @javax.ws.rs.QueryParam •  Query String parameters •  @javax.ws.rs.FormParam •  form-encoded key-value pairs •  @javax.ws.rs.HeaderParam •  HTTP request headers •  @javax.ws.rs.CookieParam •  HTTP cookies set by the client •  @javax.ws.rs.core.Context •  All-purpose injection annotation. It allows you to inject various helper and informational objects that are provided by the JAX-RS API e.g. •  @Context final HttpServletRequest request •  @Context final SecurityContext secCtx JHUG 17 Dec 2011
  • 33. JAX-RS Content Handling •  MIME types •  Automatic content negotiation •  Automatic content serialization •  Jaxb representation → XML, JSON •  Byte[] → Binary or */* •  String → text/* •  MultiValuedMap<String, String> → application/x-www-formurlencoded •  StreamingOutput •  @Providers JHUG 17 Dec 2011
  • 34. JAX-RS Error Handling •  HTTP Error Codes •  WebApplicationException •  ExceptionMapper throw new WebApplicationException(new RuntimeException (“Timeframe not an Integer"), Response.Status.NOT_ACCEPTABLE); @Provider public class EntityNotFoundMapper implements ExceptionMapper<EntityNotFoundException> { public Response toResponse(EntityNotFoundException e){ return Response.status(Response.Status.NOT_FOUND).build(); } } JHUG 17 Dec 2011
  • 35. Enforcing security •  @RolesAllowed({“admin”,”client-admin”}) •  @PermitAll •  Any authenticated user •  @SecurityContext public interface SecurityContext { public static final String BASIC_AUTH = "BASIC"; public static final String CLIENT_CERT_AUTH = "CLIENT_CERT"; public static final String DIGEST_AUTH = "DIGEST"; public static final String FORM_AUTH = "FORM"; public Principal getUserPrincipal(); public boolean isUserInRole(String role); public boolean isSecure(); public String getAuthenticationScheme(); } JHUG 17 Dec 2011
  • 36. Example @Path(”/presentations") @Singleton() public class PresentationsResource { @PUT() @Path(”/presentation/{name}”) @RolesAllowed(”admin”) public void addPresentation(@PathParam name, InputStream is){ return getDataService().addPresentation(is); } @GET() @Path(”/presentation/{name}") public StreamingOutput getPresentation(@PathParam name) { return new StreamingOutput() { @Override public void write(OutputStream output) throws IOException { stream( getDataService().getPresentation(name) , output ); } } } } JHUG 17 Dec 2011
  • 37. CTR •  Clinical Trials Register •  (https://www.clinicaltrialsregister.eu/) •  Rest services •  Data to other agency html pages •  Content to the World Health Organization •  Data to the web application users •  Rest clients •  JS code as the client •  Controller servlet •  JSP <c:import url=“/trial/2010-022009-16/GB”/> •  A guy at World Health Organization every Tuesday at 19:00 JHUG 17 Dec 2011
  • 38. Data consumed by html pages (1/3) @Path("/trials") @Singleton() public class TrialsMetaDataResource { @GET() @Path("/count/public") @Produces("text/plain") public String countPublicTrials() { return getDataService().countPublicClinicalTrials().toString(); } @GET() @Path("/count/public/under18") @Produces("text/plain") public String countUnder18PublicTrials() { return getDataService().countPublicClinicalTrialsWithSubjectsUnder18().toString(); } @GET() @Path("/landing") @Produces(MediaType.APPLICATION_JSON) public LandingPageMetadata landingPageMetadata() { Integer total = getDataService().countPublicClinicalTrials(); Integer under18 = getDataService().countPublicClinicalTrialsWithSubjectsUnder18(); } … } LandingPageMetadata metadata = new LandingPageMetadata(total, under18); return metadata; JHUG 17 Dec 2011
  • 39. Data consumed by html pages (2/3) @XmlRootElement() @XmlAccessorType(value = XmlAccessType.PROPERTY) public class LandingPageMetadata implements Serializable { private static final long serialVersionUID = -8784258618018188874L; private Integer numberOfPublicClinicalTrials; private Integer numberOfPublicClinicalTrialsWithSubjectsUnder18; public LandingPageMetadata() {…} public LandingPageMetadata(Integer numberOfPublicClinicalTrials, Integer numberOfPublicClinicalTrialsWithSubjectsUnder18) {…} @XmlElement(name="total") public Integer getNumberOfPublicClinicalTrials() {…} public void setNumberOfPublicClinicalTrials(Integer numberOfPublicClinicalTrials) {…} @XmlElement(name="under18") public Integer getNumberOfPublicClinicalTrialsWithSubjectsUnder18() {…} public void setNumberOfPublicClinicalTrialsWithSubjectsUnder18(Integer numberOfPublicClinicalTrialsWithSubjectsUnder18) {…} @Override public String toString() {…} } JHUG 17 Dec 2011
  • 40. Data consumed by html pages (3/3) function showNumbers() { $.getJSON('api/trials/landing', function(data) { var total = data['total']; var under18 = data['under18']; $("#total").text(total); $("#under18").text(under18); }); } JHUG 17 Dec 2011
  • 41. Streaming Content (1/2) @Path("/download") public class DownloadResource { @GET @Path("/summary") public Response downloadSummaryTrials(@Context final HttpServletRequest request, @QueryParam ("mode") final String mode) { return Response.ok(new SummaryStreamingOutput(request, mode),MediaType.APPLICATION_OCTET_STREAM) .header("content-disposition","attachment; filename = trials-summary.txt").build(); } @GET @Path("/full") public Response downloadFullTrials(@Context final HttpServletRequest request, @QueryParam ("mode") final String mode) { return Response.ok(new FullStreamingOutput(request, mode),MediaType.APPLICATION_OCTET_STREAM) .header("content-disposition","attachment; filename = trials-full.txt").build(); } @GET @Path("/trial/{eudractnumber}/{nca}") public Response downloadFullCta(@Context final HttpServletRequest req, @PathParam ("eudractnumber") String eudractnumber, @PathParam("nca") String nca) { return Response.ok(new CtaStreamingOutput(req, eudractnumber, nca),MediaType.APPLICATION_OCTET_STREAM) .header("content-disposition","attachment; filename = trial.txt").build(); } } JHUG 17 Dec 2011
  • 42. Streaming Content (2/2) public class CtaStreamingOutput implements StreamingOutput { public CtaStreamingOutput(HttpServletRequest request, String euNumber, String nca) {…} } public void write(OutputStream output) throws IOException { TextSerializer ser = new TextSerializer(); ser.setOutputStream(output); CtaIdentification pubCta = mapper.map (eudractNumber, nca); ser.serializeCtaFull(pubCta); } JHUG 17 Dec 2011
  • 43. RSS 2.0 instead of built in Atom (1/2) @GET @Path("/bydates”) @Produces("application/rss+xml") public SyndFeed getFeed(@Context final HttpServletRequest request) { String feedType = "rss_2.0”; SyndFeed feed = new SyndFeedImpl(); feed.setFeedType(feedType); String url = request.getRequestURL().toString().replaceFirst("/rest/ feed/bydates", ”/search") + "?" + request.getQueryString(); feed.setLink(url); feed.setTitle("EU Clinical Trials Register RSS Feed"); feed.setDescription("This provides a regular feed of new or updated clinical trial information published on the EU Clinical Trial Register and matching the search subscribed to."); List<CtrDocument> docs = search(request); for(CtrDocument doc: docs){ SyndEntry entry = buildEntry(doc, entryBasicUrl, countryUrl); feed.getEntries().add(entry); } LOG.info("Generated RSS feed {}", feed.getLink()); return feed; } JHUG 17 Dec 2011
  • 44. RSS 2.0 instead of built in Atom (2/2) @Provider @Produces("application/rss+xml") @Consumes("application/rss+xml") public class RomeRssSupport implements MessageBodyWriter<Object>{ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return (SyndFeed.class.isAssignableFrom(type)); } public long getSize(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; } } public void writeTo(Object feedOrEntry, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream outputStream) throws IOException { if (feedOrEntry instanceof SyndFeed) { SyndFeed feed = (SyndFeed)feedOrEntry; SyndFeedOutput output = new SyndFeedOutput(); doc = output.outputW3CDom(feed); Source source = new DOMSource(doc); Result result = new StreamResult(outputStream); TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); transformer.transform(source, result); } } JHUG 17 Dec 2011
  • 45. Resources •  Restful Web Services - Leonard Richardson and Sam Ruby •  Service Design Patterns - Robert Daigneau •  Restful Java - Bill Burke •  www.amazon.com •  http://icondrawer.com •  http://www.iconeden.com •  http://www.iconshock.com JHUG 17 Dec 2011