SlideShare a Scribd company logo
1 of 82
Download to read offline
Hypermedia APIs for headless
platforms and Data Integration
David Gómez G.
@dgomezg
Why are APIs important?
One user, many devices, multiple apps
APIs enable multiple consumers
@dgomezg@liferayeng
Why do WE need APIs?
API
Backend
Frontends
Liferay APIs in 2018
SOAP-WS
JSONWS API
REST/JAX-RS
A Simple JAX-RS Service Endpoint.
@GET @Path("/blogs/{id}")
@Produces(APPLICATION_JSON)
public Response getBlogsEntry(long id) {
BlogsEntry blogsEntry = _blogsEntryService.getEntry(id);
return Response.ok(blogsEntry).build();
}
JAX-RS Service Building Blocks
‣ Application
‣ Resources
‣ Extensions
Application (Mandatory)
@Component
@ApplicationPath(“api")
public class RecipesApplication extends Application {
public Set<Class<?>> getSingletons() {
return Collections.singleton(new RecipeResource());
}
}
‣ Manages the API resources
@dgomezg@liferayeng
Resources
@Path("recipe")
public class RecipeResource {
@GET @Path("{id}")
public RecipeDTO retrieveRecipe(@PathParam("id") long id) {
return new RecipeDTO(_recipeService.getRecipe(id).getName());
}
@Reference
private RecipeService _recipeService;
}
‣ Manages the endpoints in a specific Path
Data Objects
@XmlRootElement
public class RecipeDTO {
@XmlElement
public List<String> getSteps() {
return steps;
}
@XmlElement
public long getId() {
return id;
}
‣ Annotated with binding info
Data Objects
public class RecipeDTO {
@JsonGetter(value = "steps")
public List<String> getSteps() {
return steps;
}
@JsonGetter(value = “id")
public long getId() {
return id;
}
‣ Annotated with binding info
Extensions
@PreMatching
public class AuthFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext ctx) throws IOException {
String authHeader = ctx.getHeaderString(HttpHeaders.AUTHORIZATION);
if (!verifyUser(authHeader)) {
throw new NotAuthorizedException("Not Authorized!");
}
}
private boolean verifyUser(String authHeader) {}
}
‣ Adds additional logic to the API
JAX-RS & OSGi
JAX-RS Whiteboard
‣ Aries JAX-RS whiteboard
‣ OSGi JAX-RS Whiteboard Specification RI
‣ Component-property based.
Thanks to @csierra & @rotty3000 !!!!
JAX-RS Whiteboard
‣ Component property based
@Component(
property = {
"osgi.jaxrs.application.select=(osgi.jaxrs.name=recipes-application)",
“osgi.jaxrs.resource=true"
},
service=Object.class)
@Path("recipe")
public class RecipeResource {
@GET @Path("{id}")
public RecipeDTO retrieveRecipe(@PathParam("id") long id) throws PortalException {
/* ... */
}
}
Plain JSON result
[
{
"address": {
"countryName": "united-states",
"regionName": "Alabama",
"street": "69108 Murphy Lights",
"zipCode": 11839
},
"chefId": 34212,
"id": 34203,
"logoURL": "/image/organization_logo?img_id=34209&t=1542808587173",
"name": "Chopping Victory"
}
]
Challenges of a Headless platform
Discoverable &
Documented
Consumption
Helpers
APIs Security
Mechanisms
Are we capable of
solving these
challenges?
Is REST still a valid
solution?
The Web is still a case of success
On the other side
REST style is an abstraction of
the architectural elements within
a distributed hypermedia system
-- Roy Fielding, 2000
Hypermedia Controls
Consumers must only know
ONE URL
And how to navigate from it
Contract with consumer defines
affordance types
(relations, actions, …)
Start with IANA’s 80 relation types
Home URL Link TypesAffordance Types
Home URL
$ curl -H "Accept: application/json-home" 
http://localhost:8080/o/api
{
"_links": {
"self": {
"href": "https://apiosample.wedeploy.io"
},
"blog-postings": {
"href": "https://apiosample.wedeploy.io/p/blog-postings"
},
"people": {
"href": "https://apiosample.wedeploy.io/p/people"
}
}
}
JSON-HOME
How to use it?
[
{
"address": {
"countryName": "united-states",
"regionName": "Alabama",
"street": "69108 Murphy Lights",
"zipCode": 11839
},
"chefId": 34212,
"id": 34203,
"logoURL": “...”,
"name": "Chopping Victory"
}
]
{

"_embedded": { /* Here, our RecipeDTO serialised in JSON */ },

"total": 43,

"count": 30,

"_links": {

"first": {

"href": "http://localhost:8080/o/api/p/person?page=1&per_page=30"

},

"next": {

"href": "http://localhost:8080/o/api/p/person?page=2&per_page=30"

},

"last": {

"href": "http://localhost:8080/o/api/p/person?page=2&per_page=30"

}

}

}
HAL
Pagination
Affordance Types
{

"_embedded": {/* Here, our RecipeDTO serialised in JSON */},

"total": 43,

"count": 30,

"_links": {

"first": {

"href": "http://localhost:8080/o/api/p/groups?page=1&per_page=30"

},

"next": {

"href": "http://localhost:8080/o/api/p/groups?page=2&per_page=30"

},

"last": {

"href": "http://localhost:8080/o/api/p/groups?page=2&per_page=30"

}

}

}
HAL
Pagination
Affordance Types
Defined by 

IANA Link Relations
Pagination
Affordance Types
{

"properties" : { /* Here, our RecipeDTO serialised in JSON */}, 

"actions": [

{

"name": "delete-item",

"title": "Delete recipe",

"method": "DELETE",

"href": "http://localhost:8080/o/p/recipe/abcdef",

}

{

"name": "publish",

"title": "Publish recipe",

"method": "POST",

"href": “http://localhost:8080/o/p/recipe/123URLs4123AREabcdeOPAQUEf",

}
…
Actions
SIREN
Affordance Types
{

..., 

"operation": [

{

"method": "DELETE",

"@id": "_:person/delete",

"@type": "Operation"

},

{

"expects": "http://localhost:8080/o/api/f/u/recipe",

"method": "PUT",

"@id": “_:recipe/update",

"@type": "Operation"

}

],
...
Actions
JSON+LD
Affordance Types
Operations
Affordance Types
Fields
{

...

"actions": [

{

"name": "add-recipe",

"title": "Add a new recipe",

"method": "POST",

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

"type": "application/json",

"fields": [

{ "name": “name", "type": "text" },

{ "name": "Chef", "type": "Person" },

]

}
…
SIREN
Affordance Types
{

..., 

"operation": [

{

"method": "DELETE",

"@id": "_:recipe/delete",

"@type": "Operation"

},

{

"expects": “http://localhost:8080/o/api/f/u/recipe",

"method": "PUT",

"@id": "_:recipe/update",

"@type": "Operation"

}

],
...
From Actions...
JSON+LD
Affordance Types
{

"@id": "http://localhost:8080/o/api/f/u/recipe",

"title": "The recipe updater form",

"description": "This form can be used to update a recipe",

"supportedProperty": [

{

"@type": "SupportedProperty",

"property": "alternateName",

"readable": false,

"required": false,

"writeable": true

},

{

"@type": "SupportedProperty",

"property": “password”,

"readable": false,

"required": true,

"writeable": true

},

...To Forms
JSON+LD
Affordance Types
Shared Vocabularies
Standard types
schema.org: 597 types y 867
properties
ActivityStreams, microformats,
…
Never expose internal models
Custom types must be
consumer focused
Well defined custom types
Schema.org
Inheritance-based
model
All attributes are
optional
Standard types
How to use it?
[
{
"address": {
"countryName": "united-states",
"regionName": "Alabama",
"street": "69108 Murphy Lights",
"zipCode": 11839
},
"chefId": 34212,
"id": 34203,
"logoURL": “...”,
"name": "Chopping Victory"
}
]
JSONWS API &
Plain JAX-RS
Richardson Maturity Model - Martin Fowler
Climbing the ladder easily
(Our recipes with Apio)
Apio Components
‣ Representor
‣ Actions
‣ Permisions
‣ Affordances
Representor Pattern
https://www.flickr.com/photos/xwl/4936781806/
Hypermedia formats
{

"gender": "female",

"familyName": "Hart",

"givenName": "Sophia",

"jobTitle": "Senior Executive",

"name": "Sophia Hart",

"alternateName": "sophia.hart",

"birthDate": "1965-04-12T00:00Z",

"email": "sophia.hart@example.com",

"_links": {

"self": {

"href": "http://host/o/api/p/people/30723"

}

}

}
{

"class": "BlogPosting",

"properties": {

"headline": "Hello DEVCON!",

"content": "The content of this blog posting"

},

"actions": [

{

"name": "delete-blog-posting",

"title": "Delete Blog Posting",

"method": "DELETE",

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

}

],

"links": [

{

"rel": [ "self" ],

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

},

]

}
{

"gender": "female",

"familyName": "Hart",

"givenName": "Sophia",

"jobTitle": "Senior Executive",

"name": "Sophia Hart",

"alternateName": "sophia.hart",

"birthDate": "1965-04-12T00:00Z",

"email": "sophia.hart@example.com",

"@id": "http://localhost:8080/o/api/p/people/30723",

"@type": [

"Person"

],

"@context": {

"@vocab": "http://schema.org"

}

}
SIREN
JSON+LD
HAL
Content Negotiation
Accept: application/ld+json
Content-Type: application/ld+json
Accept: application/vnd.siren+json
Content-Type: application/
vnd.siren+json
Accept: application/hal+json
Content-Type: application/
hal+json
Representor +
ContentNegotiation
Creating Types (I)
@Type(“Restaurant")
public interface RestaurantType extends Identifier<Long> {
@Id
public long getId();
@Field(“chefId”) @LinkedModel(PersonType.class)
public Long getChefId();
@Field("name")
public String getName();
@Field("logoUrl")
public String getLogoURL();
@Field("address")
public PostalAddressType getAddress();
}
Making DTO implement Types
@Type(“Restaurant")
public class OrganizationDTO implements RestaurantType {
}
And get rid of all those JAXB or Jackson annotations!!!
Representor Pattern
https://www.flickr.com/photos/xwl/4936781806/
With the Representor Pattern internal models are
transformed to types and stored as a generic
representation that can be then mapped
to the representation format chosen by the user
Apio Componentes
‣ Representor
‣ Actions
‣ Permisions
‣ Affordances
ActionRouter
@Component
public class RestaurantActionRouter implements ActionRouter<RestaurantType> {
@Retrieve
@EntryPoint
public List<RestaurantType> retrieve(User user) throws PortalException {
List<Organization> organizations =
_organizationService.getUserOrganizations(user.getUserId());
return organizations.stream()
.map(OrganizationDTO::new)
.collect(Collectors.toList());
}
}
Action (no URL mapping)EntryPoint
(appears in the Home URL)
ActionRouter
ActionRouter action annotations
import com.liferay.apio.architect.annotation.Actions.*;
@Create
@Remove
@Replace
@Retrieve
@EntryPoint
Method mapping annotations
@Remove
public void remove(@Id long id) {...}
@Id indicates an Identifier
@Body parses the body content
@Create
public BlogPostiong create(@Body BlogPosting blogPosting) {...}
@ParentId links to the Id of a parent resource
@Retrieve
public List<BlogPosting> retrieveBlogPosts(
@ParentId(Organization.class) long groupId)
Special context parameters
@Retrieve
public List<BlogPosting> retrieveBlogPosts(
@ParentId(Organization.class) long groupId, User user)
User extracted from Context, logged User
Pagination & PageItems to handle pagination
@EntryPoint @Retrieve
public PageItems<BlogPosting> retrievePage(Pagination pagination)
A more complex ActionRouter
@Component
public class BlogPostingActionRouter implements ActionRouter<BlogPosting> {
@Create
public BlogPosting create(@Body BlogPosting blogPosting) {...}
@Remove
public void remove(@Id long id) {...}
@Replace
public BlogPosting replace(@Id long id, @Body BlogPosting blogPosting) {...}
@Retrieve
public BlogPosting retrieve(@Id long id) {...}
@EntryPoint @Retrieve
public PageItems<BlogPosting> retrievePage(Pagination pagination) {return null;}
@Subscribe
public BlogSubscription subscribe(@Id long id, @Body BlogSubscription subscrption){...}
Resource embedding and Sparse field sets
http://localhost:8080/o/api/restaurant
?embedded=creator
&fields[Person]=name,image
&sort=datePublished:desc
&filter=name eq ‘Chopping Victory’
&page=1
&per_page=10
Search, Sort and filter (Affordances w URL templates)
http://localhost:8080/o/api/restaurant
?embedded=creator
&fields[Person]=name,image
&sort=datePublished:desc
&filter=name eq ‘Chopping Victory’
&page=1
&per_page=10
Pagination
http://localhost:8080/o/api/restaurant
?embedded=creator
&fields[Person]=name,image
&sort=datePublished:desc
&filter=name eq ‘Chopping Victory’
&page=1
&per_page=10
More out-of-the-box features
● Bean Validation (JSR 330) support
● Open API generated
● Discoverability from Home URL
● Vocabulary
Key scenarios
P a b l o A g u l l a
1
Backend of a
custom frontend
2
Enabler of
omnichannel
experiences
3
Data integration &
platform
management
P a b l o A g u l l a
3
Data integration &
platform
management
Data integration and platform administration
Other sources
Liferay JSON
schema
Headless APIs
Content Management API
Management
UI
Liferay Commerce
CRM
Navigability & auto-discovery
Final Lessons!|
Spend time defining your vocabulary
It is the most important design activity
for an API
Make consumers & their
developers the focus of your
API design strategy
● Provide features that make their job easier
● APIs should speak their language, not yours
Enable clients and tools to
discover and navigate your API
● Same code could work for different scenarios
Thanks
David Gómez G.
@dgomezg

More Related Content

What's hot

HATEOAS: The Confusing Bit from REST
HATEOAS: The Confusing Bit from RESTHATEOAS: The Confusing Bit from REST
HATEOAS: The Confusing Bit from REST
elliando dias
 
Representational State Transfer (REST)
Representational State Transfer (REST)Representational State Transfer (REST)
Representational State Transfer (REST)
David Krmpotic
 

What's hot (20)

GraphQL - gdy API RESTowe to za mało
GraphQL - gdy API RESTowe to za małoGraphQL - gdy API RESTowe to za mało
GraphQL - gdy API RESTowe to za mało
 
From CRUD to Hypermedia APIs with Spring
From CRUD to Hypermedia APIs with SpringFrom CRUD to Hypermedia APIs with Spring
From CRUD to Hypermedia APIs with Spring
 
Building Awesome API with Spring
Building Awesome API with SpringBuilding Awesome API with Spring
Building Awesome API with Spring
 
HATEOAS: The Confusing Bit from REST
HATEOAS: The Confusing Bit from RESTHATEOAS: The Confusing Bit from REST
HATEOAS: The Confusing Bit from REST
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
Building sustainable RESTFul services
Building sustainable RESTFul servicesBuilding sustainable RESTFul services
Building sustainable RESTFul services
 
API Design Tour: Dell
API Design Tour: DellAPI Design Tour: Dell
API Design Tour: Dell
 
SharePoint REST vs CSOM
SharePoint REST vs CSOMSharePoint REST vs CSOM
SharePoint REST vs CSOM
 
Beautiful REST+JSON APIs with Ion
Beautiful REST+JSON APIs with IonBeautiful REST+JSON APIs with Ion
Beautiful REST+JSON APIs with Ion
 
Sigfox API Documentation
Sigfox API DocumentationSigfox API Documentation
Sigfox API Documentation
 
Design Beautiful REST + JSON APIs
Design Beautiful REST + JSON APIsDesign Beautiful REST + JSON APIs
Design Beautiful REST + JSON APIs
 
Building Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET CoreBuilding Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET Core
 
Representational State Transfer (REST)
Representational State Transfer (REST)Representational State Transfer (REST)
Representational State Transfer (REST)
 
Getting into ember.js
Getting into ember.jsGetting into ember.js
Getting into ember.js
 
Rest API
Rest APIRest API
Rest API
 
The REST And Then Some
The REST And Then SomeThe REST And Then Some
The REST And Then Some
 
Cross-Platform Data Access for Android and iPhone
Cross-Platform Data Access for Android and iPhoneCross-Platform Data Access for Android and iPhone
Cross-Platform Data Access for Android and iPhone
 
RESTful Architecture
RESTful ArchitectureRESTful Architecture
RESTful Architecture
 
Javascript Frameworks for Well Architected, Immersive Web Apps
Javascript Frameworks for Well Architected, Immersive Web AppsJavascript Frameworks for Well Architected, Immersive Web Apps
Javascript Frameworks for Well Architected, Immersive Web Apps
 
Rest and Rails
Rest and RailsRest and Rails
Rest and Rails
 

Similar to David Gómez G. - Hypermedia APIs for headless platforms and Data Integration - Codemotion Milan 2018

The liferay case: lessons learned evolving from RPC to Hypermedia REST APIs
The liferay case: lessons learned evolving from RPC to Hypermedia REST APIsThe liferay case: lessons learned evolving from RPC to Hypermedia REST APIs
The liferay case: lessons learned evolving from RPC to Hypermedia REST APIs
Jorge Ferrer
 
Java Script Based Client Server Webapps 2
Java Script Based Client Server Webapps 2Java Script Based Client Server Webapps 2
Java Script Based Client Server Webapps 2
kriszyp
 

Similar to David Gómez G. - Hypermedia APIs for headless platforms and Data Integration - Codemotion Milan 2018 (20)

The liferay case: lessons learned evolving from RPC to Hypermedia REST APIs
The liferay case: lessons learned evolving from RPC to Hypermedia REST APIsThe liferay case: lessons learned evolving from RPC to Hypermedia REST APIs
The liferay case: lessons learned evolving from RPC to Hypermedia REST APIs
 
Introduction to GraphQL and AWS Appsync on AWS - iOS
Introduction to GraphQL and AWS Appsync on AWS - iOSIntroduction to GraphQL and AWS Appsync on AWS - iOS
Introduction to GraphQL and AWS Appsync on AWS - iOS
 
The Glory of Rest
The Glory of RestThe Glory of Rest
The Glory of Rest
 
Switch to Backend 2023
Switch to Backend 2023Switch to Backend 2023
Switch to Backend 2023
 
APIs, Web Services, and Mashups: What they are and how they can be used
APIs, Web Services, and Mashups: What they are and how they can be usedAPIs, Web Services, and Mashups: What they are and how they can be used
APIs, Web Services, and Mashups: What they are and how they can be used
 
REST easy with API Platform
REST easy with API PlatformREST easy with API Platform
REST easy with API Platform
 
Ibm_interconnect_restapi_workshop
Ibm_interconnect_restapi_workshopIbm_interconnect_restapi_workshop
Ibm_interconnect_restapi_workshop
 
AppSync and GraphQL on iOS
AppSync and GraphQL on iOSAppSync and GraphQL on iOS
AppSync and GraphQL on iOS
 
Java Script Based Client Server Webapps 2
Java Script Based Client Server Webapps 2Java Script Based Client Server Webapps 2
Java Script Based Client Server Webapps 2
 
RESTful Web APIs – Mike Amundsen, Principal API Architect, Layer 7
RESTful Web APIs – Mike Amundsen, Principal API Architect, Layer 7RESTful Web APIs – Mike Amundsen, Principal API Architect, Layer 7
RESTful Web APIs – Mike Amundsen, Principal API Architect, Layer 7
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API Platform
 
How APIs Can Be Secured in Mobile Environments
How APIs Can Be Secured in Mobile EnvironmentsHow APIs Can Be Secured in Mobile Environments
How APIs Can Be Secured in Mobile Environments
 
Vital AI MetaQL: Queries Across NoSQL, SQL, Sparql, and Spark
Vital AI MetaQL: Queries Across NoSQL, SQL, Sparql, and SparkVital AI MetaQL: Queries Across NoSQL, SQL, Sparql, and Spark
Vital AI MetaQL: Queries Across NoSQL, SQL, Sparql, and Spark
 
Supercharging Applications with GraphQL and AWS AppSync
Supercharging Applications with GraphQL and AWS AppSyncSupercharging Applications with GraphQL and AWS AppSync
Supercharging Applications with GraphQL and AWS AppSync
 
apidays LIVE New York - API Code First vs Design First by Phil Sturgeon
apidays LIVE New York - API Code First vs Design First by Phil Sturgeonapidays LIVE New York - API Code First vs Design First by Phil Sturgeon
apidays LIVE New York - API Code First vs Design First by Phil Sturgeon
 
Hi5 Open Social
Hi5   Open SocialHi5   Open Social
Hi5 Open Social
 
Develop iOS and Android apps with SharePoint/Office 365
Develop iOS and Android apps with SharePoint/Office 365Develop iOS and Android apps with SharePoint/Office 365
Develop iOS and Android apps with SharePoint/Office 365
 
Take Mobile and Web Apps to the Next Level with AWS AppSync and AWS Amplify
Take Mobile and Web Apps to the Next Level with AWS AppSync and AWS Amplify Take Mobile and Web Apps to the Next Level with AWS AppSync and AWS Amplify
Take Mobile and Web Apps to the Next Level with AWS AppSync and AWS Amplify
 
ICONUK 2016: REST Assured, Freeing Your Domino Data Has Never Been That Easy!
ICONUK 2016: REST Assured, Freeing Your Domino Data Has Never Been That Easy!ICONUK 2016: REST Assured, Freeing Your Domino Data Has Never Been That Easy!
ICONUK 2016: REST Assured, Freeing Your Domino Data Has Never Been That Easy!
 
aip-workshop1-dev-tutorial
aip-workshop1-dev-tutorialaip-workshop1-dev-tutorial
aip-workshop1-dev-tutorial
 

More from Codemotion

More from Codemotion (20)

Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...
 
Pompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending storyPompili - From hero to_zero: The FatalNoise neverending story
Pompili - From hero to_zero: The FatalNoise neverending story
 
Pastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storiaPastore - Commodore 65 - La storia
Pastore - Commodore 65 - La storia
 
Pennisi - Essere Richard Altwasser
Pennisi - Essere Richard AltwasserPennisi - Essere Richard Altwasser
Pennisi - Essere Richard Altwasser
 
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 

Recently uploaded

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Recently uploaded (20)

DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 

David Gómez G. - Hypermedia APIs for headless platforms and Data Integration - Codemotion Milan 2018

  • 1. Hypermedia APIs for headless platforms and Data Integration David Gómez G. @dgomezg
  • 2. Why are APIs important?
  • 3.
  • 4. One user, many devices, multiple apps
  • 5. APIs enable multiple consumers @dgomezg@liferayeng
  • 6. Why do WE need APIs?
  • 7.
  • 8.
  • 11.
  • 12.
  • 13.
  • 18. A Simple JAX-RS Service Endpoint. @GET @Path("/blogs/{id}") @Produces(APPLICATION_JSON) public Response getBlogsEntry(long id) { BlogsEntry blogsEntry = _blogsEntryService.getEntry(id); return Response.ok(blogsEntry).build(); }
  • 19. JAX-RS Service Building Blocks ‣ Application ‣ Resources ‣ Extensions
  • 20. Application (Mandatory) @Component @ApplicationPath(“api") public class RecipesApplication extends Application { public Set<Class<?>> getSingletons() { return Collections.singleton(new RecipeResource()); } } ‣ Manages the API resources @dgomezg@liferayeng
  • 21. Resources @Path("recipe") public class RecipeResource { @GET @Path("{id}") public RecipeDTO retrieveRecipe(@PathParam("id") long id) { return new RecipeDTO(_recipeService.getRecipe(id).getName()); } @Reference private RecipeService _recipeService; } ‣ Manages the endpoints in a specific Path
  • 22. Data Objects @XmlRootElement public class RecipeDTO { @XmlElement public List<String> getSteps() { return steps; } @XmlElement public long getId() { return id; } ‣ Annotated with binding info
  • 23. Data Objects public class RecipeDTO { @JsonGetter(value = "steps") public List<String> getSteps() { return steps; } @JsonGetter(value = “id") public long getId() { return id; } ‣ Annotated with binding info
  • 24. Extensions @PreMatching public class AuthFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext ctx) throws IOException { String authHeader = ctx.getHeaderString(HttpHeaders.AUTHORIZATION); if (!verifyUser(authHeader)) { throw new NotAuthorizedException("Not Authorized!"); } } private boolean verifyUser(String authHeader) {} } ‣ Adds additional logic to the API
  • 26. JAX-RS Whiteboard ‣ Aries JAX-RS whiteboard ‣ OSGi JAX-RS Whiteboard Specification RI ‣ Component-property based. Thanks to @csierra & @rotty3000 !!!!
  • 27. JAX-RS Whiteboard ‣ Component property based @Component( property = { "osgi.jaxrs.application.select=(osgi.jaxrs.name=recipes-application)", “osgi.jaxrs.resource=true" }, service=Object.class) @Path("recipe") public class RecipeResource { @GET @Path("{id}") public RecipeDTO retrieveRecipe(@PathParam("id") long id) throws PortalException { /* ... */ } }
  • 28. Plain JSON result [ { "address": { "countryName": "united-states", "regionName": "Alabama", "street": "69108 Murphy Lights", "zipCode": 11839 }, "chefId": 34212, "id": 34203, "logoURL": "/image/organization_logo?img_id=34209&t=1542808587173", "name": "Chopping Victory" } ]
  • 29. Challenges of a Headless platform Discoverable & Documented Consumption Helpers APIs Security Mechanisms
  • 30. Are we capable of solving these challenges?
  • 31. Is REST still a valid solution?
  • 32. The Web is still a case of success On the other side
  • 33. REST style is an abstraction of the architectural elements within a distributed hypermedia system -- Roy Fielding, 2000
  • 34.
  • 35. Hypermedia Controls Consumers must only know ONE URL And how to navigate from it Contract with consumer defines affordance types (relations, actions, …) Start with IANA’s 80 relation types Home URL Link TypesAffordance Types
  • 36. Home URL $ curl -H "Accept: application/json-home" http://localhost:8080/o/api { "_links": { "self": { "href": "https://apiosample.wedeploy.io" }, "blog-postings": { "href": "https://apiosample.wedeploy.io/p/blog-postings" }, "people": { "href": "https://apiosample.wedeploy.io/p/people" } } } JSON-HOME
  • 37. How to use it? [ { "address": { "countryName": "united-states", "regionName": "Alabama", "street": "69108 Murphy Lights", "zipCode": 11839 }, "chefId": 34212, "id": 34203, "logoURL": “...”, "name": "Chopping Victory" } ]
  • 38. {
 "_embedded": { /* Here, our RecipeDTO serialised in JSON */ },
 "total": 43,
 "count": 30,
 "_links": {
 "first": {
 "href": "http://localhost:8080/o/api/p/person?page=1&per_page=30"
 },
 "next": {
 "href": "http://localhost:8080/o/api/p/person?page=2&per_page=30"
 },
 "last": {
 "href": "http://localhost:8080/o/api/p/person?page=2&per_page=30"
 }
 }
 } HAL Pagination Affordance Types
  • 39. {
 "_embedded": {/* Here, our RecipeDTO serialised in JSON */},
 "total": 43,
 "count": 30,
 "_links": {
 "first": {
 "href": "http://localhost:8080/o/api/p/groups?page=1&per_page=30"
 },
 "next": {
 "href": "http://localhost:8080/o/api/p/groups?page=2&per_page=30"
 },
 "last": {
 "href": "http://localhost:8080/o/api/p/groups?page=2&per_page=30"
 }
 }
 } HAL Pagination Affordance Types Defined by 
 IANA Link Relations
  • 41. {
 "properties" : { /* Here, our RecipeDTO serialised in JSON */}, 
 "actions": [
 {
 "name": "delete-item",
 "title": "Delete recipe",
 "method": "DELETE",
 "href": "http://localhost:8080/o/p/recipe/abcdef",
 }
 {
 "name": "publish",
 "title": "Publish recipe",
 "method": "POST",
 "href": “http://localhost:8080/o/p/recipe/123URLs4123AREabcdeOPAQUEf",
 } … Actions SIREN Affordance Types
  • 42. {
 ..., 
 "operation": [
 {
 "method": "DELETE",
 "@id": "_:person/delete",
 "@type": "Operation"
 },
 {
 "expects": "http://localhost:8080/o/api/f/u/recipe",
 "method": "PUT",
 "@id": “_:recipe/update",
 "@type": "Operation"
 }
 ], ... Actions JSON+LD Affordance Types
  • 44. Fields {
 ...
 "actions": [
 {
 "name": "add-recipe",
 "title": "Add a new recipe",
 "method": "POST",
 "href": "http://localhost:8080/o/p/recipe",
 "type": "application/json",
 "fields": [
 { "name": “name", "type": "text" },
 { "name": "Chef", "type": "Person" },
 ]
 } … SIREN Affordance Types
  • 45. {
 ..., 
 "operation": [
 {
 "method": "DELETE",
 "@id": "_:recipe/delete",
 "@type": "Operation"
 },
 {
 "expects": “http://localhost:8080/o/api/f/u/recipe",
 "method": "PUT",
 "@id": "_:recipe/update",
 "@type": "Operation"
 }
 ], ... From Actions... JSON+LD Affordance Types
  • 46. {
 "@id": "http://localhost:8080/o/api/f/u/recipe",
 "title": "The recipe updater form",
 "description": "This form can be used to update a recipe",
 "supportedProperty": [
 {
 "@type": "SupportedProperty",
 "property": "alternateName",
 "readable": false,
 "required": false,
 "writeable": true
 },
 {
 "@type": "SupportedProperty",
 "property": “password”,
 "readable": false,
 "required": true,
 "writeable": true
 },
 ...To Forms JSON+LD Affordance Types
  • 47. Shared Vocabularies Standard types schema.org: 597 types y 867 properties ActivityStreams, microformats, … Never expose internal models Custom types must be consumer focused Well defined custom types
  • 49. How to use it? [ { "address": { "countryName": "united-states", "regionName": "Alabama", "street": "69108 Murphy Lights", "zipCode": 11839 }, "chefId": 34212, "id": 34203, "logoURL": “...”, "name": "Chopping Victory" } ]
  • 50. JSONWS API & Plain JAX-RS Richardson Maturity Model - Martin Fowler
  • 51. Climbing the ladder easily (Our recipes with Apio)
  • 52. Apio Components ‣ Representor ‣ Actions ‣ Permisions ‣ Affordances
  • 54. Hypermedia formats {
 "gender": "female",
 "familyName": "Hart",
 "givenName": "Sophia",
 "jobTitle": "Senior Executive",
 "name": "Sophia Hart",
 "alternateName": "sophia.hart",
 "birthDate": "1965-04-12T00:00Z",
 "email": "sophia.hart@example.com",
 "_links": {
 "self": {
 "href": "http://host/o/api/p/people/30723"
 }
 }
 } {
 "class": "BlogPosting",
 "properties": {
 "headline": "Hello DEVCON!",
 "content": "The content of this blog posting"
 },
 "actions": [
 {
 "name": "delete-blog-posting",
 "title": "Delete Blog Posting",
 "method": "DELETE",
 "href": "http://localhost:8080/o/p/blogs/32400"
 }
 ],
 "links": [
 {
 "rel": [ "self" ],
 "href": "http://localhost:8080/o/p/blogs/32400"
 },
 ]
 } {
 "gender": "female",
 "familyName": "Hart",
 "givenName": "Sophia",
 "jobTitle": "Senior Executive",
 "name": "Sophia Hart",
 "alternateName": "sophia.hart",
 "birthDate": "1965-04-12T00:00Z",
 "email": "sophia.hart@example.com",
 "@id": "http://localhost:8080/o/api/p/people/30723",
 "@type": [
 "Person"
 ],
 "@context": {
 "@vocab": "http://schema.org"
 }
 } SIREN JSON+LD HAL
  • 55. Content Negotiation Accept: application/ld+json Content-Type: application/ld+json Accept: application/vnd.siren+json Content-Type: application/ vnd.siren+json Accept: application/hal+json Content-Type: application/ hal+json Representor + ContentNegotiation
  • 56. Creating Types (I) @Type(“Restaurant") public interface RestaurantType extends Identifier<Long> { @Id public long getId(); @Field(“chefId”) @LinkedModel(PersonType.class) public Long getChefId(); @Field("name") public String getName(); @Field("logoUrl") public String getLogoURL(); @Field("address") public PostalAddressType getAddress(); }
  • 57. Making DTO implement Types @Type(“Restaurant") public class OrganizationDTO implements RestaurantType { } And get rid of all those JAXB or Jackson annotations!!!
  • 58. Representor Pattern https://www.flickr.com/photos/xwl/4936781806/ With the Representor Pattern internal models are transformed to types and stored as a generic representation that can be then mapped to the representation format chosen by the user
  • 59. Apio Componentes ‣ Representor ‣ Actions ‣ Permisions ‣ Affordances
  • 60. ActionRouter @Component public class RestaurantActionRouter implements ActionRouter<RestaurantType> { @Retrieve @EntryPoint public List<RestaurantType> retrieve(User user) throws PortalException { List<Organization> organizations = _organizationService.getUserOrganizations(user.getUserId()); return organizations.stream() .map(OrganizationDTO::new) .collect(Collectors.toList()); } } Action (no URL mapping)EntryPoint (appears in the Home URL) ActionRouter
  • 61. ActionRouter action annotations import com.liferay.apio.architect.annotation.Actions.*; @Create @Remove @Replace @Retrieve @EntryPoint
  • 62. Method mapping annotations @Remove public void remove(@Id long id) {...} @Id indicates an Identifier @Body parses the body content @Create public BlogPostiong create(@Body BlogPosting blogPosting) {...} @ParentId links to the Id of a parent resource @Retrieve public List<BlogPosting> retrieveBlogPosts( @ParentId(Organization.class) long groupId)
  • 63. Special context parameters @Retrieve public List<BlogPosting> retrieveBlogPosts( @ParentId(Organization.class) long groupId, User user) User extracted from Context, logged User Pagination & PageItems to handle pagination @EntryPoint @Retrieve public PageItems<BlogPosting> retrievePage(Pagination pagination)
  • 64. A more complex ActionRouter @Component public class BlogPostingActionRouter implements ActionRouter<BlogPosting> { @Create public BlogPosting create(@Body BlogPosting blogPosting) {...} @Remove public void remove(@Id long id) {...} @Replace public BlogPosting replace(@Id long id, @Body BlogPosting blogPosting) {...} @Retrieve public BlogPosting retrieve(@Id long id) {...} @EntryPoint @Retrieve public PageItems<BlogPosting> retrievePage(Pagination pagination) {return null;} @Subscribe public BlogSubscription subscribe(@Id long id, @Body BlogSubscription subscrption){...}
  • 65. Resource embedding and Sparse field sets http://localhost:8080/o/api/restaurant ?embedded=creator &fields[Person]=name,image &sort=datePublished:desc &filter=name eq ‘Chopping Victory’ &page=1 &per_page=10
  • 66. Search, Sort and filter (Affordances w URL templates) http://localhost:8080/o/api/restaurant ?embedded=creator &fields[Person]=name,image &sort=datePublished:desc &filter=name eq ‘Chopping Victory’ &page=1 &per_page=10
  • 68. More out-of-the-box features ● Bean Validation (JSR 330) support ● Open API generated ● Discoverability from Home URL ● Vocabulary
  • 70. P a b l o A g u l l a 1 Backend of a custom frontend 2 Enabler of omnichannel experiences 3 Data integration & platform management
  • 71. P a b l o A g u l l a 3 Data integration & platform management
  • 72. Data integration and platform administration Other sources Liferay JSON schema Headless APIs Content Management API Management UI Liferay Commerce CRM
  • 73.
  • 74.
  • 75.
  • 76.
  • 79. Spend time defining your vocabulary It is the most important design activity for an API
  • 80. Make consumers & their developers the focus of your API design strategy ● Provide features that make their job easier ● APIs should speak their language, not yours
  • 81. Enable clients and tools to discover and navigate your API ● Same code could work for different scenarios