thinking restfully

45
JHUG 17 Dec 2011 REST Thinking RESTfully Stelios Gkorilas

Upload: stelios-gorilas

Post on 10-May-2015

474 views

Category:

Technology


3 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Thinking restfully

JHUG 17 Dec 2011

REST Thinking RESTfully Stelios Gkorilas

Page 2: Thinking restfully

JHUG 17 Dec 2011

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

Page 3: Thinking restfully

JHUG 17 Dec 2011

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

Page 4: Thinking restfully

JHUG 17 Dec 2011

Service styles • RPC services • Message oriented services • Resource oriented services

Page 5: Thinking restfully

JHUG 17 Dec 2011

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

Page 6: Thinking restfully

JHUG 17 Dec 2011

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

Page 7: Thinking restfully

JHUG 17 Dec 2011

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>

Page 8: Thinking restfully

JHUG 17 Dec 2011

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

Page 9: Thinking restfully

JHUG 17 Dec 2011

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

Page 10: Thinking restfully

JHUG 17 Dec 2011

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

Page 11: Thinking restfully

JHUG 17 Dec 2011

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>

Page 12: Thinking restfully

JHUG 17 Dec 2011

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

Page 13: Thinking restfully

JHUG 17 Dec 2011

REST constraints (Fielding dissertation) • Client/server • Uniform Interface •  Layered System • Stateless • Cache • Code on Demand

Page 14: Thinking restfully

JHUG 17 Dec 2011

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

Page 15: Thinking restfully

JHUG 17 Dec 2011

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

Page 16: Thinking restfully

JHUG 17 Dec 2011

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

Page 17: Thinking restfully

JHUG 17 Dec 2011

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>

Page 18: Thinking restfully

JHUG 17 Dec 2011

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

Page 19: Thinking restfully

JHUG 17 Dec 2011

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

Page 20: Thinking restfully

JHUG 17 Dec 2011

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”

Page 21: Thinking restfully

JHUG 17 Dec 2011

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

Page 22: Thinking restfully

JHUG 17 Dec 2011

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!

Page 23: Thinking restfully

JHUG 17 Dec 2011

REST Security standards

Page 24: Thinking restfully

JHUG 17 Dec 2011

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}

Page 25: Thinking restfully

JHUG 17 Dec 2011

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 and metadata

Object’s metadata

Set the object’s value and metadata

Delete the object

Page 26: Thinking restfully

JHUG 17 Dec 2011

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=0F9RBCLB5274NKTJ4DA3")

•  Access policies •  Private, public-read, public-write, authenticated read

Page 27: Thinking restfully

JHUG 17 Dec 2011

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

Page 28: Thinking restfully

JHUG 17 Dec 2011

Java REST Services •  Java EE 6 specification: JAX-RS •  Jersey: Reference implementation of JSR 311 • Available as standalone and enterprise

Page 29: Thinking restfully

JHUG 17 Dec 2011

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>

Page 30: Thinking restfully

JHUG 17 Dec 2011

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();}

}

Page 31: Thinking restfully

JHUG 17 Dec 2011

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

Page 32: Thinking restfully

JHUG 17 Dec 2011

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

Page 33: Thinking restfully

JHUG 17 Dec 2011

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-form-

urlencoded

• StreamingOutput • @Providers

Page 34: Thinking restfully

JHUG 17 Dec 2011

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(); }

}

Page 35: Thinking restfully

JHUG 17 Dec 2011

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();}

Page 36: Thinking restfully

JHUG 17 Dec 2011

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 ); } }

}

}

Page 37: Thinking restfully

JHUG 17 Dec 2011

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

Page 38: Thinking restfully

JHUG 17 Dec 2011

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;}

…}

Page 39: Thinking restfully

JHUG 17 Dec 2011

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) {…}

@Overridepublic String toString() {…}

}

Page 40: Thinking restfully

JHUG 17 Dec 2011

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);});

}

Page 41: Thinking restfully

JHUG 17 Dec 2011

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();}

}

Page 42: Thinking restfully

JHUG 17 Dec 2011

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);}

}

Page 43: Thinking restfully

JHUG 17 Dec 2011

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;

}

Page 44: Thinking restfully

JHUG 17 Dec 2011

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); }

}}

Page 45: Thinking restfully

JHUG 17 Dec 2011

Resources

ptg6899256

•  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