RAML versus HATEOAS


#1

RAML is a static service definition while HATEOAS prones a more dynamic approach. Are there any thoughts on potentially reducing the divide in order to provide the goodness of a contract-first approach to HATEOAS-minded developers?


#2

One general approach is to look at a RAML spec is the superset of all resources and methods that clients should be prepared for, while hypermedia responses link to the actual possibilities available to a client at any given point.

But that’s just the beginning of an interesting and long discussion… :wink: One worthy of a new category, methinks.


#3

I’m not sure that I’m 100% convinced on the fact that RAML is a static service definition. IMHO RAML is just a format, and that format can either be statically generated or dynamically too. RAML in itself it is not bound to a contract-first approach. I do believe just like I believe in TDD, that APIs which are contract-first are much cleaner, easier to use, and more uniform within its own domain versus API that are code-first.

RAML is its heart is just an specification for describing APIs, and that goal is not that far from what HATEOAS is proposing. I guess the major difference between the two, is that HATEOAS promise to deliver that information on small quantities and in-band, meaning that when you perform an action on a resource, HATEOAS will also give you what other actions and resources are related so the client and keep on linking on jumping from one place to the other. HATEOAS just like REST is an idea, there is no standard backing it, and there is no standard on how those links are meant to be formatted for the client to read. This is different from the web in general in which HTML defines a specific rules on how you link one resource to another. I believe that RAML at some point in the future can help cover the format gap which HTML serves today for linking documents on the web, but for APIs.

Good discussion.


#4

So is there any way with RAML to define ACL like control over something like response links? Could we for example, use a trait or something to define a set of links that could then be used by the Java parser code (Raml object) to determine if a given body has a given trait associated with it, such that we could then some how programmatically generate code that uses that info? It may be a bit out of context, I am just trying to understand the possibilities with the raml spec itself, and how we can use the file (and in my case Java Raml object) to identify details that pertain to a specific API definition. Similar to how some documentation can now show a given method for a resource that is secured using the isSecured trait.


#5

I think one of the main characteristics of HATEAOS is that we don’t necessarily know the API a priori. For instance, a URL for a web resource may only be known after querying the API. Iif for example, one is using something like json+hal, this means that the URLs are essentially aliased to “rel” attributes inside the “_links” JSON array. I think we’d need a way to represent RAML resources as relations to other RAML resources using these “rel” attributes.

Example:

Instead of this:

#%RAML 0.8
---
title: "My Cool API"
baseUri: https://my.cool-api.com
version: v1
/info:
  /abc

we use this:

#%RAML 0.8
---
title: "My Cool API"
baseUri: https://my.cool-api.com
version: v1
/info:
  hal-rels:
    x: #rel attribute equal to "x" in the HAL _links array, which may or may not result in /abc as the path

We’re making use of the fact that rels can be know a priori where actual URLs aren’t.


#6

This begs a question: how do you generate a good documentation for such an HATEOAS API? From annotations at code level, a la Swagger?

Also, how do you tie the formal specification of your entities (XML and JSON schemas) to such an API definition?

I haven’t found convincing (ie pragmatic and applicable right now) answers for these questions so far…


#7

Couple of days ago - I found this: https://gist.github.com/adrobisch/0eb546eb877c57d67cf1


#8

This comment:

Why are we documenting this? Because this is a Documentation! 
It's at least useful from service view to know the URI strucutre / queryParameters etc. it
presented to the clients (in the links) because resource URIs might be re-requested 
and must not change anyway. 
Tell you clients to walk the service document instead of using this information directly.
If you are lucky, they even might do that.

is pretty lolz :stuck_out_tongue_closed_eyes:


#9

You can define HAL schemas quite easily. See this link for more details: http://hyperschema.org/mediatypes/hal

I believe RAML can be extended to hypermedia APIs in this way: The root must always be a real path. A sub-resource (i.e. a resource under a resource) can be defined based on a rel rather than a path. Other than that, it’s just a completely normal resource. The only problem is that the RAML document will have a definition that may or may not be returned by the REAL API as it’s based on the application state by definition of being a HAL _links item.

I really see nothing significant stopping HATEOAS being integrated into the RAML spec besides coming up with a way to define it such that it’s agnostic of what the actual JSON/XML elements and properties are named (i.e. _links or links, Href or href). This can be solved by examining a combination of the HAL json schema used.

Example:

/info:
  /details:
    ...all your resource info here...

Can be represented as:

/info:
  rels:
    - name: details
      definition:
        ...all your resource info here...

Assuming /info returns a HAL response with the following JSON (or equivalent):

{
  ...
  "_links": [
    {
        "Rel": "self",
        "Href": "/info",
        "Title": "Gets Info on something neat",
        "IsTemplated": false
    },
    {
        "Rel": "details",
        "Href": "/info/details",
        "Title": "Get some additional details on the info.",
        "IsTemplated": false
    },
    ...
  ]
}

#10

Fully agree! I also think that it would take only minor extensions to RAML to be more useful for APIs implementing HATEOAS. Since hypermedia is needed to get to Level 3 in the Richardson Maturity Model and being it is also explicitly required / mentioned by Roy Fielding, the current lack of support in RAML is one if its weak points and often mentioned in discussions I had with fellow developers. Some of them (the more purist RESTafarians) dropped RAML because of this.

Below is another proposal of how it could look like without breaking the current path-based definitions.
Key point is that a resource should a have name to make it referenceable and independent of its path (the whole point of hypermedia):

/user:
  name: User
  relations:
    - articles:
        target: Articles
/articles:
  name: Articles
  get:
    queryParameters:
      author:
  ...
/article:
  name: Article                                       # optional
  relations:                                          # optional
    - self:
    target: Article
        description: The article itself
    - author:
        target: User
        description: The author of this Article
    - comments:
        target: Comments
        description: The comments of the article      # optional
        profile: http://examples.org/article-comments # optional
  get:
    ...
  /comments:
    name: Comments
    ... 
  /comment:
    name: Comment
    relations:
      - article
          target: Article
          descirption: The Article this comment belongs to

This adds some degree of redundancy but that is necessary for the decoupling from the path. The realization of the links for the relations should than be reflected in the schema (for hal+json) or in the headers (Web Linking, RFC5988) of the response or even be assumed per convention. When specifiying links in json schema, you could provide a (non-standard) hint-property to make it possible to a create documentation where you can follow links. See my extended music api example at github for reference

How do you think about this style of resource definition?


RAML 1.0 is around the corner
#11

Hi guys,

I haven’t read everything yet - but just a QQ: Instead of introducing new language definitions, would it be useful in your opinion to use the upcoming extensions ‘x-’ to do what we need for HATEOAS? For example, you could map the relations to x-relations.

BTW, I am definitely going through your posts slowly - just wanted to give my first 2c :smiley:

Christian


#12

Having a extension first sounds good to me. This way the community could evaluate and develop the best approach. But imho some kind of solution should eventually be a part of the RAML spec, since its a core concept of REST APIs.

Do you have more information on the x- extensions? I was unable to find mentions of it which were not written by you ;)?


#13

I actually like what @adrobisch is proposing for hateos based links. You could add type, rel, description, name, etc to each relations item, and maybe even make the sort of link format it returns customizable at the top of the raml file (some people want atom like syntax, some may want to keep to what their existing response format already is and may not be identical to atom, etc).


#14

I’m not that familiar with RAML but have investigated REST (hypermedia) quite a bit. I’m still a bit confused at how your example works in a REST scenario where you still have it based on URL’s, e.g. /user, /articles, /article? In a REST service only the entry point, link relations and media type is documented.

Thanks,
Nick


#15

@nickdu what about the different stages - you need to document them as well right?


#16

For a “REST” API I need to document the hypermedia type(s), the link relations and the entry point. Are you saying RAML will help out here?

Thanks,
Nick


#17

Hi Nick - hope we can elaborate on that a little bit more. RAML might be able to do that in the future and there is nothing which is in the way. As you can see in this thread, we still try to figure out what the best approach would be to actually create a “REST” API conform specification, but in the same time document the types, relation and entry point as you said. BUT we need to find this approach first and of course need help from everyone, especially those kinds who have the experiences in this field.

Any ideas are very much appreciated :wink:


#18

In that looking at Neo4J’s REST API documentation could provide some interesting thinking material: http://neo4j.com/docs/stable/rest-api.html

Indeed they primarily document the service root: http://neo4j.com/docs/stable/rest-api-service-root.html

But they also document all the possible relations, with examples: http://neo4j.com/docs/stable/rest-api-relationships.html

And it makes sense: as a developer, I need to know everything I can do with an API by browsing a human-friendly doc. If all the would provide is the description of the root, I would have to actually use the API to discover all I can do. Not a friendly perspective.

So from a documentation perspective, having a RAML spec for REST APIs makes sense because you can derive a rich documentation from it.

The risk is of course that people will also derive static clients from it, instead of following the links all the time. But the risk of hardcoding links also exist without RAML…

From an implementation standpoint, I can see that having to describe in a static manner resources that are dynamically discoverable in a RAML spec could be an annoying contradiction. I imagine that in this case, the RAML spec would need to be assembled from the implementation itself, by introspecting it in order to find all the necessary bits (media types, JSON schemas, resource paths, examples…).

I cringe at the idea of an API spec that is a by-product of its implementation though. But in the case of level 3 REST APIs, developers are clearly expected to avoid assuming anything and rely only on dynamic discovery. So that approach makes sense.

IMO, from a practical standpoint, I think we’re not there yet, both in term of tooling and developers mindsets…


#19

Thanks. I was more just trying to clear some stuff up with respect to REST. I believe the confusion stems from the fact that people have different definitions of REST. As you can tell, I’ve taken my definition from Roy Fielding since he’s the one who has coined the term and wrote a dissertation on it. That being said, I’m not sure you want to make any changes to try to support REST API’s as I don’t believe it’s possible. A REST API is not supposed to be documented, as far as I can tell. It’s supposed to be discovered, “follow your nose”, as Roy calls it based on documenting the media types the link relations and the entry point. So I don’t see much of a point is trying to make RAML do something that’s not supposed to be done. It seems to work well at documenting Web/HTTP API’s.

Thanks,
Nick


#20

Yes, I guess it’s mainly a matter of semantics. I reckon that, because it’s slightly easier to say “REST API” than “Web/HTTP API”, people tend to use REST improperly. Even in my previous comment, I was kind of implying that something below level 3 of the RMM could be considered RESTful, which it can’t. Level 3 is actually a pre-condition for being RESTful.

So, I guess if RAML is about specification and documentation and if REST is antagonist with theses ideas, the RAML acronym has to be rethought, because by this definition a “RESTful API Modeling Language” would be an oxymoron.

We could pretend that RAML means RAML (the same way SOAP now simply means SOAP). Or maybe it should become “RESTish API Modeling Language” :stuck_out_tongue_winking_eye: