SlideShare uma empresa Scribd logo
1 de 82
Baixar para ler 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

Mais conteúdo relacionado

Semelhante a Cdm mil-18 - hypermedia ap is for headless platforms and data integration

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
 

Semelhante a Cdm mil-18 - hypermedia ap is for headless platforms and data integration (20)

Ams adapters
Ams adaptersAms adapters
Ams adapters
 
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 Hydra
Introduction to HydraIntroduction to Hydra
Introduction to Hydra
 
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
 
Together Cheerfully to Walk with Hypermedia
Together Cheerfully to Walk with HypermediaTogether Cheerfully to Walk with Hypermedia
Together Cheerfully to Walk with Hypermedia
 

Mais de David Gómez García

Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
David Gómez García
 

Mais de David Gómez García (20)

Leverage CompletableFutures to handle async queries. DevNexus 2022
Leverage CompletableFutures to handle async queries. DevNexus 2022Leverage CompletableFutures to handle async queries. DevNexus 2022
Leverage CompletableFutures to handle async queries. DevNexus 2022
 
Building Modular monliths that could scale to microservices (only if they nee...
Building Modular monliths that could scale to microservices (only if they nee...Building Modular monliths that could scale to microservices (only if they nee...
Building Modular monliths that could scale to microservices (only if they nee...
 
Leveraging Completable Futures to handle your query results Asynchrhonously
Leveraging Completable Futures to handle your query results AsynchrhonouslyLeveraging Completable Futures to handle your query results Asynchrhonously
Leveraging Completable Futures to handle your query results Asynchrhonously
 
What's in a community like Liferay's
What's in a community like Liferay'sWhat's in a community like Liferay's
What's in a community like Liferay's
 
Java9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadJava9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidad
 
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTRT3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
T3chFest2016 - Uso del API JavaScript de Photoshop para obtener fotos HDTR
 
Managing user's data with Spring Session
Managing user's data with Spring SessionManaging user's data with Spring Session
Managing user's data with Spring Session
 
Parallel streams in java 8
Parallel streams in java 8Parallel streams in java 8
Parallel streams in java 8
 
Construccion de proyectos con gradle
Construccion de proyectos con gradleConstruccion de proyectos con gradle
Construccion de proyectos con gradle
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.
 
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
 
Measuring Code Quality in WTF/min.
Measuring Code Quality in WTF/min. Measuring Code Quality in WTF/min.
Measuring Code Quality in WTF/min.
 
Spring4 whats up doc?
Spring4 whats up doc?Spring4 whats up doc?
Spring4 whats up doc?
 
Gradle como alternativa a maven
Gradle como alternativa a mavenGradle como alternativa a maven
Gradle como alternativa a maven
 
El poder del creador de Software. Entre la ingeniería y la artesanía
El poder del creador de Software. Entre la ingeniería y la artesaníaEl poder del creador de Software. Entre la ingeniería y la artesanía
El poder del creador de Software. Entre la ingeniería y la artesanía
 
Geo-SentimentZ
Geo-SentimentZGeo-SentimentZ
Geo-SentimentZ
 
HDTR images with Photoshop Javascript Scripting
HDTR images with Photoshop Javascript ScriptingHDTR images with Photoshop Javascript Scripting
HDTR images with Photoshop Javascript Scripting
 
Wtf per lineofcode
Wtf per lineofcodeWtf per lineofcode
Wtf per lineofcode
 
A real systemwithjms-rest-protobuf-mongodb
A real systemwithjms-rest-protobuf-mongodbA real systemwithjms-rest-protobuf-mongodb
A real systemwithjms-rest-protobuf-mongodb
 
Spring Data y Mongo DB en un proyecto Real
Spring Data y Mongo DB en un proyecto RealSpring Data y Mongo DB en un proyecto Real
Spring Data y Mongo DB en un proyecto Real
 

Último

+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@
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Último (20)

Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
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
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
+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...
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
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
 
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
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 

Cdm mil-18 - hypermedia ap is for headless platforms and data integration

  • 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