Question

Forgive me as I am still new to this RESTFUL thing, I have been reading blogs etc... and they all have got different implementations/guidelines really, only real guideline is the Richardson Maturity Model that specifies what Hypermedia is.

I know the benefits of a Hypermedia design is to have links with annotations driving machine/user interaction via a root URL, and it will be evolvable like when the links change, enhancing caching with idempotent/safe http verbs etc...

I am trying to design a RESTFUL API Webservice and I am planning to use a GENERIC MEDIA TYPE maybe like HAL or Collection+Json or Siren etc... Or possibly create my own Media Type which I do not think I want to go into right now...

With a generic media type, I would have a payload, a data structure or DTO object, whatever you call it, like "Application Model with many Applicants Models with Many Addresses etc..."

1) Do I have to specify the data structure definition somewhere? or a form template of some sort? I have seen some examples with where they put their definition of that data in a human readable format in like "someurl/doc? Or should we use something like json schema?

2) Some examples I have seen decorated their data items with a type in a link from vcard/foaf etc... eg. "name": "http://xmlns.com/foaf/0.1/name". What does that mean? Some examples I see have like references to their someurl/doc#name for describing the name object etc...

3) Does it mean that if the payload of the Application Model changes, the interpreter of the contract changes? And therefore all clients break as before, like in SOAP?

4) One other alternative, I think I can have an evolvable item structure, like the collection+json item object with Name,Value,Prompt that forms the actual structure, that way there will be minimal contract changes on the client end consuming it.

Please advice on how I should design my object, basically say I have an APPLICATION OBJECT with multiple APPLICANTS with MULTIPLE ADDRESSES to simplify the question.

Josh

Was it helpful?

Solution

The best current practice is to avoid creating new content types wherever possible, so you're right to shy away from that.

  1. Depends on your audience. Use whatever would be easiest for them to consume. Are they generic automated agents, which can understand a schema, or are they developers working specifically to your API. You will always need human-readable docs anyway, so I'd start there. If you choose to accept application/x-www-form-urlencoded request bodies, then a HTML form would be a great way of providing a working template.
  2. This defines the "type" of a field. So name is a foaf:name tells you that the field called name contains a value of type http://xmlns.com/foaf/0.1/name. You should read up about RDF, the resource description format, and look at the representations like Turtle and N3 which should make this clearer. The concept of relations that are URIs (instead of simple strings) comes from there, though link relations are not the same as RDF properties such as owl:sameAs or foaf:name. Both are represented as edges in a directed graph.
  3. Please explain more, do you mean fields added/removed or a completely different content type? I would argue that the latter is a different resource and should have a different URI. Your clients will need to either understand or be able to ignore any future changes you make to your resources.
  4. All of the content types you suggested should be evolvable in this manner. That is exactly the premise of HATEOAS.

Your design appears to me to be a simple tree structure with one root resource, containing a list of collections, each containing a list of leaf resources. I seem to be missing something here because there's nothing complicated in that.

I am going to assume that by Applicant you mean a person applying for a job, and by Address you mean somewhere they live or work (as opposed, say, to an email address). Some of the below may be obvious but I am including it for other readers who may come across this question.

An example implementation, using HAL, would be:

Request:

GET / HTTP/1.1
Host: example.com
Accept: application/hal+json

Response:

HTTP/1.1 200 OK

{ "_links": {
    "self": { "href": "/" },
    "http://example.com/docs/applicant": [
      { "href": "/applicant1" },
      { "href": "/applicant2" },
      { "href": "/applicant3" }]
} }

The client would then look for hyperlinks that have the relation http://example.com/docs/applicant, which is just a string and could be fishmonkeygiraffe if you wanted - making the string be a http URL allows client developers to find your documentation more easily, as well as scoping relationships by prefixing it with a unique string: your own domain. The response format could be any hypertext-capable format, such as HTML, as long as the client knows how to find the hyperlinks within it (<LINK> and <A> elements), or you could return them in a HTTP Link header, but then the client is responsible for storing them if it needs to write the retrieved resource to disk.

The client then requests the one it wants to look at:

GET /applicant1 HTTP/1.1
Host: example.com
Accept: application/hal+json

Response:

HTTP/1.1 200 OK

{ "_links": {
    "self": { "href": "/applicant1" },
    "http://example.com/docs/applicant-address": [
      { "href": "/applicant1/address1" },
      { "href": "/applicant1/address2" },
      { "href": "/applicant1/address3" }]
} }

Obviously "applicant1" can be anything you like, e.g. "applicants/1" or "vacancies/sweet-manager/applicants/dave-smith". The client just follows the URL it is given.

The client then picks a hyperlink of type http://example.com/docs/applicant-address to retrieve:

GET /applicant1/address1 HTTP/1.1
Host: example.com
Accept: application/hal+json

Response:

HTTP/1.1 200 OK

{ "_links": {
    "self": { "href": "/applicant1/address1" },
    "edit-form": { "href": "/applicant1/address1/edit" },
    "http://example.com/docs/applicant": { "href": "/applicant1" }
  },

  "street": "5 Dungeon Drive",
  "town": "Snotty Hill",
  "county": "London",
  "postcode": "NE5 2LT",
  "country": "GB",
}

Now the client wants to amend the address, so it follows the hyperlink with the relation "edit-form": (see IANA link relations)

GET /applicant1/address1/edit HTTP/1.1
Host: example.com
Accept: text/html

Response:

HTTP/1.1 200 OK

<!DOCTYPE HTML>
<form action="/applicant1/address1" method="POST">
  <input name="street" value="5 Dungeon Drive">
  et cetera
</form>

Resulting in:

POST /applicant1/address1 HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

street=5%20Dungeon%20Drive&...

I have used HAL because HAL is like a JSON version of XML+XLink, just simpler to type in SO examples ;) i.e. it's a hypermedia-capable common parse format, nothing more. All interaction is guided by link relations. Web browsers know what to do with a rel="stylesheet" link because it knows what that relation means. The IANA-defined list of link relations cited above are ones you should choose from first (item and collection are very useful), and then if what you are looking for is not specific enough, try to find a public list of link relations relevant to your sector (for example see what API the market leader publishes) and re-use those if possible. This will allow tools to become interoperable because they are all looking for the same link relations. Your Dublin Core example in the question is a similar repository of publicly defined RDF Properties.

For hyperlinks, the coupling (contract) is not be between the client and your site, but the client and a set of relations. The relations should be as well-known as possible (this is what Wikipedia means when it says "a generic understanding of hypermedia").
For resource fields, if you intend your resource to be processed generically, then I would recommend an RDF-based solution, using well-known RDF Properties that map closely to your domain of business. Several RDF serialisations into JSON exist but at the moment there is no clear leader. You would probably be better off supporting just XML at this point. The blog post JSON to RDF in six easy steps may be insightful as a way to learn the basics of RDF.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top