Re: Getting around in Event API Demo

October 7 2014 10:28 PM, "John Walker" <john.walker@semaku.com> wrote: 
> Hi Dietrich,
> 
> Some comments on the RDF side of things inline.
> 
> John
> 
>> On October 7, 2014 at 9:03 AM Dietrich Schulten <ds@escalon.de> wrote:
>> 
>> 
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>> 
>> Hi,
>> 
>> I'm toying with the event API demo
>> http://bit.ly/hydra-console-event-api. I want to share a few
>> observations and ideas, backed by my experience with designing ReST APIs.
>> Disclaimer: I have some basic knowledge about rdfs, but my ideas
>> simply might not work as linked data.
>> 
>> The meat of the event-api is at
>> http://www.markus-lanthaler.com/hydra/event-api/vocab.
>> Observation: the vocab is quite lengthy for a simple use case. 241
>> LOC, much of it seems repetitive.
>> 
>> We are talking about a pretty standard situation: you can POST, PUT
>> and DELETE to the /events resource. If you POST or PUT, your request
>> should contain an object that has attributes as defined by
>> http://schema.org/Event. Only some of them are required, most are not
>> supported.
>> 
> 
> Your /events page would be a hydra:Collection of schema:Event 'instances'.
> 
> As such you would presumably only allow GET and POST methods on the collection.
> 
> PUT and DELETE would be more suited for use on the schema:Event instances.
> 
>> My general feeling is: it should not be necessary to maintain such a
>> large description. Somehow we must leverage convention over
>> configuration and the existing vocabs in such a way that I only need
>> to define things I cannot take for granted. And we must be more DRY.
>> 

I find convention over configuration very noble, but I don't think it's such a good idea for one reason. Given the convention that DELETE removes a resource how do you state that a specific instance won't accept a DELETE? You would either learn that after trying or would have to add some statemets to overrule the convention.

Also how would you change the convention completely? With conventions imposed you decrease the unmatched flexibility IMO.

>> I want to keep my context short so I can embed it. With Javascript
>> clients in mind, I'd rather have everything in the resource that is
>> needed to work with it.

Why does it have to be short? If the context grows you can serve it as an external resource to keep representations concise.

>> 
>> In the following I want to discuss the EntryPoint, the EventCollection
>> and the Event.
>> 
>> - ------------------------
>> 
>> In my ideal world this could be the EntryPoint:
>> 
>> {
>> "@context": {
>> "@vocab" : "http://schema.org",
>> "hydra" : "http://www.w3.org/ns/hydra/core#"
>> },
>> "@id": "http://www.markus-lanthaler.com/hydra/event-api/",
>> "@type": "hydra:EntryPoint",
>> "event": {
>> "@id": "http://www.markus-lanthaler.com/hydra/event-api/events/",
>> "@type": "hydra:Link"
>> }
>> }
>> (I prefer full urls because they work in stock rest clients.)
>> 
>> Short, no external context, no site-specific vocab.
>> The question is, is this valid from a Linked Data point of view?
>> 
> 
> Here you are saying the resource http://www.markus-lanthaler.com/hydra/event-api/events/ has
> rdf:type hydra:Link, which does not seem correct.
>

Exactly. The event property would be the hydra:Link and not the target.

> 
> I would expect that resource to have rdf:type hydra:Collection instead.
> 
>> Note that the event property is now http://schema.org/event, no longer
>> EventCollection.
>> 
> 
> By doing this I would expect the thing you link to with schema:event is a schema:Event, but seems
> that you link to a hydra:Collection of events.
> 
>> First of all, http://schema.org/event appears on Place, Organization
>> and a number of Actions. In RDF, are we free to use schema:event on an
>> EntryPoint? Can I state
>> 
>> "schema:event rdfs:domain hydra:EntryPoint"
>> 
>> somewhere in my context to allow this usage? And do I have to, don't I
>> say that already by using schema:event on a hydra:EntryPoint? In the
>> json world no "static typing" exists that would prevent me from adding
>> any attribute.
>> 
> 
> This is not wrong per-se, but would entail that all resources this property is used on have
> rdf:type hydra:EntryPoint which does not seem correct.
> If you used the sematically weaker schema:domainIncludes property, it would be OK from an RDF
> perspective.
> However I'd have to question if/why you would want to link from an API entry point to an event,
> unless you have conferences about an API of course :) 
>
>> An alternative could be not to use hydra:EntryPoint, but Organization
>> or Place as @type of the index resource. Now that I think of it, that
>> also makes a lot of sense. Probably the owner of the events wants to
>> tell something about himself on the index resource anyway. But the
>> question remains: may we attach event to EntryPoint at all?
>> 
> 
> Indeed linking direct from an Organization or Place to an associated Event make perfect sense.
> The idea here is to link the list/collection of all registered events to the EntryPoint, not a
> specific Event instance.
> 
>> Second: Assuming that we are allowed to use http://schema.org/event:
>> Values of
>> schema:event are expected to be of type Event, not of type @id. It
>> would be easy to program clients so that they understand the
>> difference and transparently resolve links for data. But does RDF
>> allow that? Is it correct to use a link to events instead of embedding
>> the events themselves? If not, can Hydra introduce such a convention?
>> Or can I at least redefine
>> 
>> "schema:event rdfs:range jsonld:@id"
>> 
>> somewhere in my @context?
>> 
> 
> Suggest to go re-read the JSON-LD spec as it seems you misinterpret how @id is used.
> In short: yes values of schema:event are expected to have rdf:type schema:Event.
> @id is just a way to define the URI of the resource being linked to, not to give it a type.
> 
>> - -----------------------
>> 
>> On to the EventCollection. My wishful-thinking EventCollection:
>> 
>> {
>> "@context": {
>> "@vocab": "http://schema.org",
>> "hydra": "http://www.w3.org/ns/hydra/core#"
>> },
>> "@id": "http://www.markus-lanthaler.com/hydra/event-api/events/",
>> "@type": "hydra:Collection",
>> "hydra:member": [
>> {
>> "@id": "http://www.markus-lanthaler.com/hydra/event-api/events/1",
>> "@type" : "hydra:Link"
>> },
>> {
>> "@id": "http://www.markus-lanthaler.com/hydra/event-api/events/2",
>> "@type" : "hydra:Link"
>> }
>> ],
>> "hydra:operation": [
>> {
>> "method": "hydra:CreateResourceOperation",
>> "hydra:supportedProperty" : [
>> "name",
>> "description",
>> "startDate",
>> "endDate",
>> {
>> "property": "performer",
>> "required" : false,
>> "hydra:supportedProperty" : [
>> "name"
>> ]
>> }
>> ]
>> }
>> ]
>> }
>> 
> 
> I would expect the @type of the members in the collection to be schema:Event rather than
> hydra:Link.
> 
>> I assumed that we could have several conventions here.
>> 
>> 1. It is usually not necessary to know the type of the collection
>> members in order to create them, since the properties we send are by
>> definition in the domain of a Thing, e.g. Event.
>> Therefore I simply used hydra:Collection.
>> Maybe Collection could have a "hydra:of" Property so that one could say
>> "@type": {
>> "@id": "hydra:Collection",
>> "hydra:of" : "Event"
>> }
>> rather than defining a custom class.
>> But right now I do not see the need for a hydra:of or for typed
>> collections. Well, I guess there *is* a reason why you introduced the
>> EventCollection :) Could you explain?
>> 
> 
> The way I think of it is that the EventCollection class is a more specialized subtype of
> hydra:Collection.
> Then we can define additional things about instances of that class that do not apply to the more
> generic hydra:Collection.
> 
>> 2. The usual case is that an operation is supported when the resource
>> comes with the appropriate affordance. Mostly it is not something that
>> is always supported, since that does not depend on the Class, but on
>> the usage context. E.g. posting a new Event is probably not supported
>> if you do not have sufficient rights to do so. The server simply does
>> not include it if it is not supported. I can hardly imagine cases
>> where a state-changing operation is *always* supported on a resource.
>> Hence I put the operation into the resource, not in the documentation.
>> 

This is a choice you make. As much as I still have mixed feeling about ApiDocumentation it does make sense. The documentation does not have to be static. It can change depending on the user's permissions. And any operations that depend on the state of individual resources could be defined only in the representation directly. However it only helps you as long as you assume the client has up-to-date representions. If the client has stale data (such as by keeping a page open for long time) and the resource's state changed you would still have to expect invalid requests.

>> 3. It is usually only necessary to list the names of supported
>> properties for an operation, so instead of saying "property": "xxx"
>> many times I just listed the property names.
>> I assumed that by convention a supported property could be
>> automatically required and read/writable, in a similar way how
>> http://schema.org/docs/actions.html defines defaults for
>> PropertyValueSpecification. Is it possible to define default values in
>> linked data in case a property is absent?
>> The description should be the one from the source vocab, here
>> schema.org, so I can
>> leave it out normally. Note however the use of supportedProperty on
>> the optional, nested "performer" property.
>> 
>> 4. There is no need to describe the meaning of status codes in the
>> resource. I am strongly against overriding the meaning of existing or
>> defining custom HTTP status codes anyway :) The body of an error
>> response is the place to give hints how to resolve a problem, and it
>> should probably follow
>> http://tools.ietf.org/html/draft-ietf-appsawg-http-problem. Could
>> hydra:Error be redefined in such a way that a json-ld client accepting
>> ld+json could by convention get the below error response (with the
>> standard properties type, title, status, detail, instance and two
>> extension properties)?
>> 
>> HTTP/1.1 403 Forbidden
>> Content-Type: application/problem+json
>> Content-Language: en
>> 
>> {
>> "@context":
>> {
>> "@vocab" : "http://www.w3.org/ns/hydra/core#",
>> "balance" : "http://bank.example.com#balance",
>> "accounts" : "http://bank.example.com#accounts"
>> }
>> "@type": "Error",
>> "type": "http://example.com/probs/out-of-credit",
>> "title": "You do not have enough credit.",
>> "status": 403,
>> "detail": "Your current balance is 30, but that costs 50.",
>> "instance": "http://example.net/account/12345/msgs/abc",
>> "balance": 30,
>> "accounts": ["http://example.net/account/12345",
>> "http://example.net/account/67890"]
>> }
>> 
>> - ------------------------
>> 
>> Up next, Event:
>> 
>> {
>> "@context": {
>> "@vocab": "http://schema.org",
>> "hydra": "http://www.w3.org/ns/hydra/core#"
>> },
>> "@id": "http://www.markus-lanthaler.com/hydra/event-api/events/1",
>> "@type": "Event",
>> "name": "Walk off the Earth - REVO tour",
>> "description": "Live in concert",
>> "startDate": "2014-06-14T20:00:00Z",
>> "endDate": "2004-06-14T23:34:30Z"
>> "hydra:operation": [
>> {"hydra:method": "DELETE"},
>> {
>> "hydra:method": "PUT",
>> "hydra:supportedProperty" : [
>> "name",
>> "description",
>> "startDate",
>> "endDate",
>> {
>> "property": "performer",
>> "required" : false,
>> "hydra:supportedProperty" : [
>> "name"
>> ]
>> }
>> ]
>> }
>> ]
>> }
>> 

You're not meant to use hydra:SupportedProperty on a hydra:Operation. They are used with hydra:Class. And define expected request body with the hydra:expects property pointing at a class.

>> Since I have sufficient rights, I can delete and replace the event.
>> When I replace an Event, I must send the same data as for a creation.
>> 
>> Clearly our operations overlap with http://schema.org/Action.
>> I tried to add a schema:ReviewAction onto the Event above, but I ran
>> into several problems. That is worth a different discussion, however.
>> 
>> - ------------------------
>> 
>> Conclusion:
>> 
>> In my opinion, this should be all I need to say for the simple CRUD
>> use case under discussion. But I guess there are some pitfalls I fell
>> into.
>> 
>> I guess the event-api as it is today tries to solve a slightly
>> different problem, maybe to keep the
>> json resource as terse as possible. I see that quite relaxed, my idea
>> is, if you request application/json instead of ld+json, then the
>> server returns a response as terse as can be.
>> 
>> Best regards,
>> Dietrich Schulten
>> 
>> - -- 
>> Dietrich Schulten
>> Escalon System-Entwicklung
>> Bubenhalde 10
>> 74199 Untergruppenbach
>> -----BEGIN PGP SIGNATURE-----
>> Version: GnuPG v2.0.22 (MingW32)
>> 
>> iEYEARECAAYFAlQzkC0ACgkQuKLNitGfiZOhzwCfSPI+oPw96kuFz4XAUFHdqntZ
>> b5AAnj3jlPv8PoNP6k/WwR4aNZ4oq2H0
>> =Zguh
>> -----END PGP SIGNATURE-----
>>

Received on Wednesday, 8 October 2014 08:50:52 UTC