Skip to content

Commit

Permalink
Use schema.org actions in use cases (#125)
Browse files Browse the repository at this point in the history
... and add JSON-LD context to snippets.
  • Loading branch information
elf-pavlik authored and lanthaler committed Jun 26, 2017
1 parent 153a68f commit 7c1dd24
Show file tree
Hide file tree
Showing 11 changed files with 302 additions and 253 deletions.
1 change: 1 addition & 0 deletions drafts/use-cases/0.intro.md
Expand Up @@ -42,6 +42,7 @@ These would be:
"xsd": "http://www.w3.org/2001/XMLSchema#",
"owl": "http://www.w3.org/2002/07/owl#",
"schema": "http://schema.org/",
"examplevocab": "http://example.com/vocab#",
"title": {
"@id": "hydra:title",
"@type": "xsd:string"
Expand Down
29 changes: 15 additions & 14 deletions drafts/use-cases/1.1.security-considerations.md
Expand Up @@ -10,23 +10,24 @@ There are several possibilities here. One of them would be to use a *@graph* not

```json
{
"@context": "/api/context.jsonld",
"@graph": [
{
"@id": "/api",
"operation": [
{
"@type": "hydra:Operation",
"title": "List events",
"method": "GET",
"returns": "hydra:Collection"
},
{
"@type": "hydra:Operation",
"title": "Create new event",
"method": "POST",
"expects": "schema:Event"
}
]
"@type": "hydra:EntryPoint",
"examplevocab:events": {
"@id": "/api/events",
"title": "List of events",
"@type": "hydra:Collection",
"operation": [
{
"@type": ["hydra:Operation", "schema:CreateAction"],
"title": "Create new event",
"method": "POST",
"expects": "schema:Event"
}
]
}
},
{
"rdfs:label": "Some other resource somehow related to the main one."
Expand Down
22 changes: 14 additions & 8 deletions drafts/use-cases/1.entry-point.md
Expand Up @@ -23,23 +23,29 @@ details on what else can be done with that API from that very point.

```http
GET /api
```

```http
HTTP 200 OK
```

```json
{
"@context": "/api/context.jsonld",
"@id": "/api",
"@type": "hydra:EntryPoint",
"events": {
"@id": "/api/events",
"examplevocab:events": {
"@id": "/api/events",
"title": "List of events",
"@type": "hydra:Collection",
"operation": {
"@type": "hydra:Operation",
"title": "Create new event",
"method": "POST",
"expects": "schema:Event"
}
"operation": [
{
"@type": ["hydra:Operation", "schema:CreateAction"],
"title": "Create new event",
"method": "POST",
"expects": "schema:Event"
}
]
}
}
```
Expand Down
6 changes: 6 additions & 0 deletions drafts/use-cases/2.api-documentation.md
Expand Up @@ -20,16 +20,22 @@ thus client is expected to store it temporarily at least for the current session

```http
GET /
```

```http
HTTP 200 OK
Link: </api?documentation>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"
GET /api?documentation
```

```http
HTTP 200 OK
```

```json
{
"@context": "/api/context.jsonld",
"@id": "/api?documentation",
"supportedClass": [
{
Expand Down
11 changes: 3 additions & 8 deletions drafts/use-cases/3.1.extensions-considerations.md
Expand Up @@ -23,6 +23,7 @@ Again, named graphs would come in handy in this situation, i.e.:

```json
{
"@context": "/api/context.jsonld",
"@graph": [
{
"@id": "meta:data",
Expand All @@ -31,13 +32,7 @@ Again, named graphs would come in handy in this situation, i.e.:
"@id": "/api/events",
"operation": [
{
"@type": "hydra:Operation",
"title": "List events",
"method": "GET",
"returns": "hydra:Collection"
},
{
"@type": "hydra:Operation",
"@type": ["hydra:Operation", "schema:CreateAction"],
"title": "Create new event",
"method": "POST",
"expects": "schema:Event"
Expand Down Expand Up @@ -66,4 +61,4 @@ Again, named graphs would come in handy in this situation, i.e.:
}
```

Alternatives would involve some mixed content type payloads or linking.
Alternatives would involve some mixed content type payloads or linking
4 changes: 4 additions & 0 deletions drafts/use-cases/3.obtaining-events.md
Expand Up @@ -25,11 +25,15 @@ events, it sends a GET request to that URL and fetches the events:

```http
GET /api/events
```

```http
HTTP 200 OK
```

```json
{
"@context": "/api/context.jsonld",
"@id": "/api/events",
"totalItems": 1,
"member": [
Expand Down
16 changes: 10 additions & 6 deletions drafts/use-cases/4.obtaining-single-event.md
Expand Up @@ -22,13 +22,17 @@ It wouldn't be possible for the calendar to show all of the event's attributes,
thus there is a need to show those outstanding ones in a separate view (i.e. popup, new screen, etc.).
The application sends a GET request to the selected event's resource identifier:

```
```http
GET /api/events/1
```

```http
HTTP 200 OK
```
```javascript

```json
{
"@context": "/api/context.jsonld",
"@id": "/api/events/1",
"@type": "schema:Event",
"eventName": "Event 1",
Expand All @@ -50,15 +54,15 @@ whole resource, properties with literal values only, or some other subset.
Including (or excluding) those additional details would be extremly useful
for obtaining related resources, i.e. in case of an event application might
want to expand attendees (or at least some of their details).
This way some optimizations can be achieved when a single request obtains
This way some optimizations can be achieved when a single request obtains
details that feed more than a single screen which may improve user experience.

#### Projection
Another interesting feature would be a possibility of projecting a resource.
It is a commont situation when an application shows an edit form for
a given resource - in order to assign a value to the i.e. event's attendee property, some kind of
a given resource - in order to assign a value to the i.e. event's attendee property, some kind of
UI element should be presented (let's say a search-as-you-type like input)
which would display projected resources - concatenation of the first and last name.

The issue here is that the syntax for such a feature would make the spec
incredibly complex.
The issue here is that the syntax for such a feature would make the spec
incredibly complex.
55 changes: 29 additions & 26 deletions drafts/use-cases/5.creating-new-event.md
Expand Up @@ -12,6 +12,7 @@ So I can produce content.
### Usage
```javascript
var event = {
"@context": "/api/context.jsonld",
"@type": "schema:Event",
"eventName": "My brand new event",
"eventDescription": "Hope it will work",
Expand All @@ -22,25 +23,27 @@ var client = new HydraClient();
var operation = client.get("http://example.com")
.getApiDocumentation()
.getEntryPoint()
.getOperations()
.filter(op => op.method == "POST" && op.expects == "Event")[0];
.getLink('http://example.com/vocab#events')
.getOperationOfType('http://schema.org/CreateAction');
client.invoke(operation, event);
```

### Details
The application has to be aware of how it can create a new resource.
It could get that information either from the API documentation or entry point
or last response's hypermedia controls. It also have to understand the type
of resource in scope (unless it is provided from outside of the application,
or last response's hypermedia controls. It also have to understand the type
of resource in scope (unless it is provided from outside of the application,
i.e. pass-through import from external data source).

Anyway, assuming all the requirements are met, a request would look like this:

```
```http
POST /api/events
```
```javascript

```json
{
"@context": "/api/context.jsonld",
"@type": "schema:Event",
"eventName": "My brand new event",
"eventDescription": "Hope it will work",
Expand All @@ -49,7 +52,7 @@ POST /api/events
}
```

```
```http
HTTP 201 Created
Location: /api/events/2
```
Expand All @@ -59,38 +62,38 @@ Brand new event should be now added to the calendar.
### Considerations

#### Protocol agnostic specification
While the most popular protocol in use is currently HTTP, ReST API can be implemented
on top of other protocols. The example above has a weakneses of being strictly bound to
HTTP by referring to HTTP POST method. This has also another weaknes - server may also
While the most popular protocol in use is currently HTTP, ReST API can be implemented
on top of other protocols. The example above has a weakneses of being strictly bound to
HTTP by referring to HTTP POST method. This has also another weaknes - server may also
allow to create resources using HTTP PUT, or it may go event further - it can forbid
the POST method in favour of PUT.
Specification could be protocol agnostic and give some hints on the logical functions
of the operations. Possible solution could be to use i.e. schema.org actions, but
without specification being clear about that, using schema.org actions is just one of
Specification could be protocol agnostic and give some hints on the logical functions
of the operations. Possible solution could be to use i.e. schema.org actions, but
without specification being clear about that, using schema.org actions is just one of
possible solutions. There is nothing against using other vocabularies causing the HyDrA
Core Vocabylary to be prone to dialects and variations.
This leads to another weakneses - first thoughs can go in the CRUD direction, but these
are not the only approaches available in the wilderness (not to mention that there are
This leads to another weakneses - first thoughs can go in the CRUD direction, but these
are not the only approaches available in the wilderness (not to mention that there are
voices that put using CRUD in ReST API to question).

#### Creating user interfaces
It is common that rich UI applications allows their users to create/edit resources
via some forms full of inputs, lists etc. The question is - how these should be created.

The easiest approach is to hard-code these in the application. Well, if the application
knows how to handle resources of type *Event*, it would have some of the logic
and views already prepared. The issue here is that it somehow puts the whole idea of
The easiest approach is to hard-code these in the application. Well, if the application
knows how to handle resources of type *Event*, it would have some of the logic
and views already prepared. The issue here is that it somehow puts the whole idea of
meta-data to question. If we have tools to fully drive the client, why not use them?

Another, slightly better solution would be to embed some of that logic within the
hypermedia controls. This is what happens when an HTML page has JavaScripts, CSS's and
HTML forms embedded - client receives extra stuff to be used to show the form so it
sends the resource back to the server. In our case though, it somehow puts on to our
Another, slightly better solution would be to embed some of that logic within the
hypermedia controls. This is what happens when an HTML page has JavaScripts, CSS's and
HTML forms embedded - client receives extra stuff to be used to show the form so it
sends the resource back to the server. In our case though, it somehow puts on to our
API a burden of being aware of the client UI capabilities, which seems to be a dead end.

Ultimate solution would be to give the client all the details possible about the resource
Ultimate solution would be to give the client all the details possible about the resource
itself, it's structure, data types etc., so the client can use these on it's own.

We need to mention also a hybrid-like solution for non-UI applications. Server side
could provide a *template* of a resource to be filled with data. Still, the client would
need some more details so the template receives correct values.
We need to mention also a hybrid-like solution for non-UI applications. Server side
could provide a *template* of a resource to be filled with data. Still, the client would
need some more details so the template receives correct values.
32 changes: 19 additions & 13 deletions drafts/use-cases/6.updating-event.md
Expand Up @@ -14,25 +14,28 @@ So I can amend content.
var client = new HydraClient();
var event = client.get("/api/events/1")
event.eventName = "Some new event name.";
client.invoke(
event.getOperations()
.filter(op => op[@type].find(type => type === schema.ReplaceAction)[0], event);
var operation = event.getOperationOfType('http://schema.org/ReplaceAction')
client.invoke(operation, event)
```

### Details
Application needs to be able to modify existing resources. This use case relies on the fact, that
Application needs to be able to modify existing resources. This use case relies on the fact, that
the resource is first obtained from the server, amended and sent back, but this is not always true.
Additionaly, the operation used for the update is taken from the hypermedia controls embedded in the
Additionaly, the operation used for the update is taken from the hypermedia controls embedded in the
resource and the target method is dicovered with an anti-patter binding it to HTTP protocol.
Regardles all of these, the communication would look like the example below:

```
```http
GET /api/events/1
```

```http
HTTP 200 OK
```
```javascript

```json
{
"@context": "/api/context.jsonld",
"@id": "/api/events/1",
"@type": ["schema:Event", "hydra:Resource"],
"eventName": "My brand new event",
Expand All @@ -41,7 +44,7 @@ HTTP 200 OK
"endDate": "2017-04-19",
"operation": [
{
"@type": "hydra:Operation",
"@type": ["hydra:Operation", "schema:ReplaceAction"],
"title": "Update an existing event",
"method": "PUT",
"expects": "schema:Event"
Expand All @@ -53,8 +56,10 @@ HTTP 200 OK
```
PUT /api/events/1
```
```javascript

```json
{
"@context": "/api/context.jsonld",
"@id": "/api/events/1",
"@type": "schema:Event",
"eventName": "Some new event name.",
Expand All @@ -63,6 +68,7 @@ PUT /api/events/1
"endDate": "2017-04-19"
}
```

```
HTTP 204 No Content
```
Expand All @@ -71,12 +77,12 @@ The event should be now updated.
### Considerations

#### What does the term "update" means?
As mentioned in the [previous use case](/4.obtaining-single-event.md), application is not aware
As mentioned in the [previous use case](/4.obtaining-single-event.md), application is not aware
of what kind of data will be provided by the server, thus a simple question may be asked:

*What gets updated?*

The simplest answer would be that whole resource is replaced with new incoming data.
But it is easy to imagine a situation, where a client may explicitely state what kind of data to
include when obtaining a resource, thus server won't know which data to update and which to leave
untouched. These considerations could multiplied, thus some explicit directions may be needed.
But it is easy to imagine a situation, where a client may explicitely state what kind of data to
include when obtaining a resource, thus server won't know which data to update and which to leave
untouched. These considerations could multiplied, thus some explicit directions may be needed.

0 comments on commit 7c1dd24

Please sign in to comment.