20161123_API Summit:
Denk man an Web APIs, dann verbindet man das zugehörige Kommunikationsmodell meist mit RESTful Requests & Responses. Dies macht in vielen Fällen sicherlich auch Sinn. Aber eben nicht in allen! Was ist z. B., wenn auf Seiten des Clients komplexe Abfragen anstehen, die sich nicht so einfach über simple “Ressourcen” abbilden lassen. Wie geht man damit um, wenn auf dem Server lang laufende Aktionen angestoßen werden, auf deren Abarbeitung der Client nicht unbedingt warten möchte? Und muss es eigentlich immer clientseitiges “Pull” sein oder macht nicht Serverseitiges “Push” via Websockets in vielen Anwendungsfällen mehr Sinn? Die Session zeigt anhand ausgewählter, praxisnaher Use-Cases, wie man durch verschiedene Pattern das klassische RESTful Request-/Response-Modell seiner Web API sinnvoll erweitern kann und so zu deutlich eleganteren und performanteren Lösungen kommt.
3. Lars Röwekamp (a.k.a. @mobileLarson)
ÜBER MICH
LR
#WISSENTEILEN
Wer bin ich - und wen ja, wie viele?
• CIO New Technologies
• Enterprise & Mobile
• Author, Speaker, Coach & Mentor
• Snowboard & MTB Enthusiast
• mehrfacher Vater, einfacher Ehemann
5. Das kleine REST 1x1
#WISSENTEILEN
REpresentational State Transfer is about ...
• Architectural Design Style
• Client-Server
• Stateless
• Cache
• Uniform Interface
• Layered System
6. Das kleine REST 1x1
#WISSENTEILEN
REpresentational State Transfer
• Identifikation durch URL
• Manipulation durch Representation
• Selbstbeschreibende Messages
• Hypermedia
/orders/123JSON/XML
GET, POST, PUT, DELETE
Media Types, Headers, ...References
7. Das kleine REST 1x1
#WISSENTEILEN
... /orders/ ... /orders/123
Liste aller Bestellungen einzelne Bestellung 123
erzeuge neuen Bestellung ERROR
ändere „Liste“ von
Bestellung
ändere Bestellung 123 sonst ERROR
lösche alle Bestellungen lösche Bestellung 123
Nomen
GET
POST
PUT
DELETE
Single Item URIList URI
Plural
8. Das kleine REST 1x1
#WISSENTEILEN
Golden rules of REST
• „We only need two URLs“
• „Verbs are bad, nouns are good“
• „Plurals are even better“
• „The web is your friend“
• „There is always a root (associations)“
• „There is always a parameter (complex stuff)“
9. Das kleine REST 1x1
#WISSENTEILEN
„There is always a root“
• GET /orders/123/ingredients
• GET /orders/123/ingredients/456
• GET /orders/123/ingredients/milk
• PUT /orders/123/ingredients/milk
• POST /orders/123/ingredients/milk
• DELETE /orders/123/ingredients/milk
10. Das kleine REST 1x1
#WISSENTEILEN
„There is always a parameter“
• Path für Ressource Identifier
• Query für Abfrageparameter, Filter, etc.
• Body für Ressource-spezifische Logik
• Header für globale, plattformweite Parameter
12. Das kleine REST 1x1
#WISSENTEILEN
Headers? Pro Tipp: Use them!
• Version-Header
• Location-Header
• Accept-Header
• Content-Type
• Link-Header
• X-Custom-Header (Override Method, Limit, ...)
13. Das kleine REST 1x1
#WISSENTEILEN
Status Codes? Pro Tipp: Use them!
• 1xx: Hold on ...
• 2xx: Here you go!
• 3xx: Go away!
• 4xx: You f#!?ed up!
• 5xx: I f#!?ed up!
14. Das kleine REST 1x1
#WISSENTEILEN
Status Codes? Pro Tipp: Use them!
• 1xx: Hold on ...
• 2xx: Here you go!
• 3xx: Go away!
• 4xx: You f#!?ed up!
• 5xx: I f#!?ed up!
(http://restlet.com/http-status-codes-map)
15. Das kleine REST 1x1
#WISSENTEILEN
HATEOAS? Pro Tipp: ... WAIT!
• What the heck is Hateoas?
17. #WISSENTEILEN
REST & Hateoas
„If the engine of application state (and
hence the API) is not driven by hypertext,
then it cannot be RESTful and cannot be a
REST API.“
Roy Fielding
19. #WISSENTEILEN
REST & Hateoas
„A REST API should be entered with no
prior knowledge beyond the initial URI ...
From that point on, all application state
transitions must be driven by the client
selection of server-provides choices ...“
Roy Fielding
24. #WISSENTEILEN
REST & Hateoas
// Response with link header for HYPERMEDIA navigation
// after calling „GET .../orders?page=10“
HTTP/1.1. 206 Partial Content
[various other headers]
Link: <.../orders?page=1>; rel=„first“
<.../orders?page=9>; rel=„next“,
<.../orders?page=11>; rel=„prev“,
<.../orders?page=17>; rel=„last“
Wait, does this
make sense?
26. REST & Pagination
#WISSENTEILEN
Wie navigiere ich durch Ressourcen?
• Path Parameter?
• Query Parameter?
• Client Side Calculation?
• Server Side Calculation?
27. #WISSENTEILEN
REST & Pagination
// List page 4 of offers
// Is page a query parameter?
GET /offers?page=4 HTTP/1.1
// Or is page a „virtual“ resource?
GET /offers/page/4 HTTP/1.1
BTW: what does
„page 4“ mean?
28. #WISSENTEILEN
REST & Pagination
// List next 5 offers starting from offer 10
// Or is page x a result of offset and limit?
GET /offers?offset=10&limit=5 HTTP/1.1
// Response with success code and link header for
// navigation purpose
HTTP/1.1. 206 Partial content
Link: <.../orders?offset=0&limit=5>; rel=„first“
<.../orders?offset=5&limit=5>; rel=„prev“,
<.../orders?offset=15&limit=5>; rel=„next“,
<.../orders?offset=40&limit=2>; rel=„last“
BTW: What‘s about
filtering, sorting, ....
30. REST & Queries
#WISSENTEILEN
Was ist eigentlich mit ...
• komplex(er)en Anfragen?
• eingeschränkten Rückgabeobjekten?
• (alternativen) Sortierungen?
• alternativen Rückgabeformat?
Und wie sieht es mit „allgemeiner“ Suche aus?
31. #WISSENTEILEN
REST & Queries
// FILTERING: List of paid orders (2015-12-20)
// Common Style
GET /orders?date=20151220&status=payed HTTP/1.1
[various other headers]
32. #WISSENTEILEN
REST & Queries
// FILTERING: Details of order 3: product, date & status
// Facebook Style
GET /orders/3?fields=product,date,status HTTP/1.1
[various other headers]
GET /orders/3?fields=item.product,date,status HTTP/1.1
[various other headers]
// LinkedIn Style
GET /orders/3:(product, date, status) HTTP/1.1
[various other headers]
33. #WISSENTEILEN
REST & Queries
// FILTERING: Details of order 3
// without date, status
GET /orders/3?exclude=date,status HTTP/1.1
[various other headers]
// predefined payload (compact = product, date, status)
GET /orders/3?style=compact HTTP/1.1
[various other headers]
BTW: what does
„compact“ mean?
34. #WISSENTEILEN
REST & Queries
// FILTERING: Details of order 3
// using PREFER HEADER for response payload definition
GET /orders/3 HTTP/1.1
Content-Type: application/json
Prefer: return=compact-format
HTTP 1.1 200 OK
Content-Type: application/json; charset=utf-8
Preference-Applied: return=compact
35. #WISSENTEILEN
REST & Queries
// SORTING: List of 10 orders sorted by date and item
// SQL Style
GET /orders?sort=date+DESC,item+ASC&count=10 HTTP/1.1
// Sort and asc/desc combination, ascending as default
GET /orders?sort=date,item&desc=date&count=10 HTTP/1.1
// use prefix „-“ for descending, ascending as default
GET /orders?sort=-date,item&count=10 HTTP/1.1
36. #WISSENTEILEN
REST & Queries
// FORMATS: List of orders in alternative format xml
// Google style
GET /orders?alt=xml HTTP/1.1
// Foursquare style (v1)
GET /orders.xml HTTP/1.1
// Digg style
GET /orders?type=xml HTTP/1.1
Accept: application/xml
37. #WISSENTEILEN
REST & Queries
// FULL TEXT SEARCH: Fulltext search for „coffee“
// Global style
GET /search?q=coffee HTTP/1.1
// Scoped style
GET /orders/search?q=coffee HTTP/1.1
GET /orders?q=coffee HTTP/1.1
// Formatted style
GET /search.xml?q=coffee HTTP/1.1
GET /orders/search.xml?q=coffee HTTP/1.1
38. #WISSENTEILEN
REST & Queries
// ADVANCED SEARCH: „coffee with milk for 2 €“
// Query for ...
GET /orders?type=coffee&ingredient=milk&price=2 HTTP/1.1
BTW: AND or OR or
AND/OR?
39. #WISSENTEILEN
REST & Queries
// ADVANCED SEARCH: „coffee WITH milk for LESS THAN 2 €“
// Query for ...
GET /orders?
query=type=coffee+ingredient=milk+price<=2
Build your own
„Query Language“?
42. #WISSENTEILEN
RQL
// ADVANCED SEARCH: „coffee WITH milk for LESS THAN 2 €“
// RQL query ... (must possibly be encoded!)
GET /orders?query=
and(eq(type,coffee),
or(eq(ingredients,MILK),lt(price,2))
// RQL alternative query – FIQL (URI friendly) - ...
GET /orders?query=
type==coff*;(ingredients==MILK,price=lt=2)
49. GraphQL
#WISSENTEILEN
Wer genau ist eigentlich dieser „Luke“ und in
welchen Filmen hat er mitgespielt?
• GET .../film/1
• GET .../film/2
• GET .../film/3
• GET .../people/1/films (if offered via Endpoint)
50. GraphQL
#WISSENTEILEN
Wer genau ist eigentlich dieser „Luke“ und in
welchen Filmen hat er mitgespielt und auf
welchen Schiffen ist er gefahren?
• GET .../starship/12
• GET .../starship/22
• GET .../peolple/1/starship (if offered)
51. GraphQL
#WISSENTEILEN
Wie alt ist Luke und welche Haarfarbe hat er?
Mit welchem “Spruch“ wurden die Filme
eröffnet in denen er mitgespielt hat?
Und wie teuer waren überhaupt die Schiffe auf
denen er gefahren ist?
• GET .../#1?F#CKING/detail (n+1 problem?)
• GET .../#1?F#CKING/all (job problem)
53. GraphQL
#WISSENTEILEN
GraphQL Motivation
„ We see a conflict between the desire to load
all information in a single round trip while
keeping REST resources well isolated.”
(Facebook, 2012)
60. GraphQL
#WISSENTEILEN
Wie alt ist Luke und welche Haarfarbe hat er?
Mit welchem “Spruch“ wurden die Filme
eröffnet in denen er mitgespielt hat?
Und wie teuer waren überhaupt die Schiffe auf
denen er gefahren ist?
62. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
63. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
64. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name:„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
65. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name:„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
66. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name:„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
67. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name=„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
68. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name:„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
69. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name:„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
70. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name:„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
71. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name:„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
72. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name:„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
73. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name:„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
74. #WISSENTEILEN
GraphQL
Wie alt ist Luke und welche
Haarfarbe hat er?
Mit welchem “Spruch“ wurden
die Filme eröffnet in denen er
mitgespielt hat?
Und wie teuer waren
überhaupt die Schiffe auf
denen er gefahren ist?
{
person(name:„Luke“) {
haircolor,
age
films {
name,
openiningCrawl
}
starships {
name,
price
}
}
}
78. GraphQL
#WISSENTEILEN
Woher weiß das Backend was ich will?
• API Schema als gemeinsame Basis
• Query als Anfrage vom Client
• Step 1: parse (Query into AST)
• Step 2: validate (against Schema)
• Step 3: execute (Resolve Functions)
79. #WISSENTEILEN
GraphQL
// A very simple GraphQL schema example
type Character {
name: String! // non nullable
appearsIn: [Episode]! // array of ..., non nullable
}
type Starship {
id: ID! // unique ID
name: String!
length(unit: LengthUnit = METER): Float // parameter
}
83. GraphQL
#WISSENTEILEN
Muss ich das alles selber „bauen“?
• Nein! Es gibt ...
• Clients, Server, DB, Libraries, Tools ...
für Java, JavaScript, Python, Ruby, PHP,
C/C++, GO, Scala, .Net, SQL, ...
> http://graphql.org
> https://github.com/chentsulin/awesome-graphql
84. GraphQL
#WISSENTEILEN
Ist das wirklich so einfach?
• relative neue Technologie (im Fluss)
• Chaching?
• Dupletten?
• Information Hiding?
• Versionierung (vs. deprecated)
91. Sync vs. Async
#WISSENTEILEN
Asyn Kommunikation
• via Messaging und Events
• lose Kopplung durch Queues & Topics
oder durch Event Observer
• ein Sender, 0 is N Receiver
• garantierte Auslieferung möglich
• garantierte Auslieferung erzeugt Overhead
114. Web Sockets
#WISSENTEILEN
Web Sockets 1x1
• Paradigmenwechsel in der Kommunikation
• Abkehr vom klassischen Request/Response
• Client meldet sich am Server an
• Full duplex „real time“ Kommunikation
• Session kann durch beide beendet werden
122. Web Sockets
#WISSENTEILEN
Can i use Web Sockets ... (Server Side)
• Java EE 7
• Spring
• Apache ActiveMQ, Caucho Resin,
Jetty, Netty, vert.x, jWebsocket
and many more ...
(see also https://dzone.com/asset/download/253)