1 of 57

bit.ly/fun-apis

APIS

2 of 57

3 of 57

4 of 57

5 of 57

Who uses REST?

Do you know that REST is dead?

6 of 57

7 of 57

8 of 57

Context!

(crazy Cyndi Lauper slides)

9 of 57

GraphQL & REST are tools

GraphQL

REST

10 of 57

Tools

Needs

11 of 57

“If all you have is a hammer, everything looks like a nail”

12 of 57

Needs

Tools

13 of 57

Common sense

  • Start from YOUR context and analyze YOUR needs
  • Know the existing tools but don’t commit to one
  • Choose the best one for your needs
  • Don’t allow other people to choose for you (no more “X is dead”)

14 of 57

The WEB in 2017

15 of 57

google.com

twitter.com

cyliconvalley.es

wecodefest.com

16 of 57

browser for

cyliconvalley.es

google.com

twitter.com

cyliconvalley.es

wecodefest.com

browser for

google.com

browser for

twitter.com

browser for

wecodefest.com

17 of 57

browser for

cyliconvalley.es

google.com

twitter.com

cyliconvalley.es

wecodefest.com

browser for

google.com

browser for

twitter.com

browser for

wecodefest.com

18 of 57

APIs in 2017

twitter.com

Twitter clients

19 of 57

Contract

API exposes data

Client consumes it

20 of 57

Google

Twitter

Cylicon

21 of 57

v1

v2

v3

22 of 57

We want evolvable APIs

23 of 57

¿How do we design APIs to be able to evolve?

24 of 57

25 of 57

These are NOT new concepts

26 of 57

REST style is an abstraction of the architectural elements within a distributed hypermedia system

-- Roy Fielding, 2000

27 of 57

What is Hypermedia?

28 of 57

Pagination (HAL)

{

"total": 43,

"count": 30,

"_links": {

"first": {

"href": "http://liferay.org.es/p/blogs?page=1&per_page=30"

},

"next": {

"href": "http://liferay.org.es/p/blogs?page=2&per_page=30"

},

"last": {

"href": "http://liferay.org.es/p/blogs?page=2&per_page=30"

}

}

29 of 57

Standard links (Link Relations IANA)

{

"total": 43,

"count": 30,

"_links": {

"first": {

"href": "http://liferay.org.es/p/blogs?...

},

"next": {

"href": "http://liferay.org.es/p/blogs?page=2&per_page=30"

},

"last": {

"href": "http://liferay.org.es/p/blogs?page=2&per_page=30"

}

}

Over 80 standard types

30 of 57

Entry URL with all the endpoints (JSON HOME)

{

"resources": {

"people": {

"href": "http://localhost/o/api/people/"

},

"web-sites": {

"href": "http://localhost/o/api/web-sites/"

},

"blogs": {

"href": "http://localhost/o/api/blogs/"

}

}

}

Clients can browse the urls.

They don’t need to know more.

31 of 57

Actions (Siren)

{

"class": "BlogPosting",

"actions": [

{

"name": "delete-item",

"title": "Delete Blog Posting",

"method": "DELETE",

"href": "http://localhost:8080/o/p/blogs/32400"

}

],

"properties": {

"headline": "Hello Valladolid!"

}

}

32 of 57

Forms (Siren)

{

"class": "BlogPosting",

"actions": [

{

"name": "add-blog-posting",

"title": "Add Blog Posting",

"method": "POST",

"href": "http://localhost:8080/o/p/blogs",

"fields": [

{

"name": "headline",

"type": "text"

},

],

Clients don’t need to know the fields in advance, just support the types.

33 of 57

Embedded fields and selection

{

"headline": "Hello CyLicon Valley!",

"_embedded": {

"author": {

"_links": {

"self": {

"href": "http://localhost:8080/o/p/people/30765"

}

},

"name": "Shalinie Kooman"

}

GET /blogs/33100?embedded=author

GET /blogs/33100?fields=[headline, author]

34 of 57

URI templates

{

"@context": "http://www.w3.org/ns/hydra/context.jsonld",

"@type": "IriTemplate",

"template": "http://api.example.com/issues{?q}",

"variableRepresentation": "BasicRepresentation",

"mapping": [

{

"@type": "IriTemplateMapping",

"variable": "q",

"property": "hydra:freetextQuery",

"required": true

}

]

}

We don’t need to hardcode “concepts” (like embedded)

35 of 57

What are shared vocabularies?

36 of 57

schema.org & ...

Internal Models

597 types

867 properties

Microformats

Never expose internal models

Customer language

37 of 57

38 of 57

Mapping internals with standards

Internal

Schema.org

BlogsEntry

BlogsPosting

headline

title

alternativeHeadline

subtitle

description

description

user

creator

user

author

articleBody

content

aggregateRating

ratings

Internal

Schema.org+custom

Group

WebSite

name

name

groupKey

alternateName

user

creator

Ratings Service

aggregateRatings

friendlyURL

_self / @id

BlogsEntry Service

blogs

manualMembership

¿?

39 of 57

What do I have to do to use it?

40 of 57

Ease development of common cases (Collection+json)

Automatic support for multiple

message formats

(representor pattern)

Documentation generated automatically

41 of 57

APIO

42 of 57

Support for

several formats

43 of 57

Representor

public Representor<Blogs, LongId> representor(

Builder<Blogs, LongId> builder) {

return builder

.types("BlogPosting")

.identifier(blogs -> blogs::getEntryId)

.addString("articleBody", Blogs::getContent)

.addString("headline", Blogs::getTitle)

.addDate("createDate", Blogs::getCreateDate)

.addLink("license", "https://creativecommons.org/licenses/by/4.0")

.addLinkedModel("creator", User.class, this::_getUserOptional)

.addRelatedCollection("comment", Comment.class, CommentableIdentifier::create)

.addBidirectionalModel("web", "blogs", Web.class, this::_getWeb, Web::getWebId)

.build();

}

44 of 57

Routes (collection)

@Override

public NestedRoutes<Blogs> collectionRoutes(

NestedRoutes.Builder<Blogs, LongIdentifier> builder) {

return builder

.addGetter(this::_getPageItems)

.addCreator(this::_addBlogs)

.build();

}

45 of 57

Routes (item)

@Override

public ItemRoutes<BlogsEntry> itemRoutes(

ItemRoutes.Builder<BlogsEntry, LongIdentifier> builder) {

return builder

.addGetter(this::_getBlogsEntry)

.addRemover(this::_deleteBlogsEntry)

.addUpdater(this::_updateBlogsEntry)

.build();

}

46 of 57

Interactive documentation generated automatically

"descriptor" : [

{

"id" : "people",

"type" : "semantic",

"href" : "http://schema.org/Person"

"doc" : { "format" : "text", "value" : "A person" },

"descriptor" : [

{

"id" : "givenName",

"type" : "semantic",

"href" : "http://schema.org/givenName"

},

{

"id" : "familyName",

"type" : "semantic",

"href" : "http://schema.org/familyName"

}

47 of 57

An hypermedia consumer is like a game loop

4 - receive user interactors and browse URL

1 - URL request

2 - Identify response

and redirect to processor

3 - render data

and controls

48 of 57

Automatic processing

of schema.org types

Implementation

of the control loop

Offline support

Visual components

49 of 57

Clients in Java (+Android), iOS & Javascript

val id =

"http://.../o/api/p/groups/5745/blogs"

thing.load(id, credentials)

50 of 57

Demo time!

51 of 57

evolvable-apis.org

Manifiesto

Guidelines/tutorials

Libraries

52 of 57

Join us!

53 of 57

questions?

54 of 57

References

55 of 57

Image References

56 of 57

Liferay

We are hiring! :D

57 of 57

Javier Gamarra / @nhpatt

APIS