2

Context

To be fully compliant with the REST principles enumerate in Fielding's dissertation, a resource must contains links that redirect to other resources that have a relation with it functionally, like for a bank account that display dynamically a withdraw link, or semantically as it could be related to an other concept related to the resource.

More generally this concept of linking is presented has HATEOAS. L. Richardson described it very well as part of its Maturity Model (specifically the level 3)

Problem

From a technical point of view, links are not so easy to implement. I'm facing particularly a problem when modeling my resources in classes. I must associate several fields that corresponds to an URI. Here is an example of what it looks (based on this example), with a BankingAccount resource describing its characteristic :

class BankingAccount() {
    Double totalAmount;
    String ownerName;
    URI uriToCloseAccount;
    URI uriToWithdrawMoney;
}

Here, the field uriToCloseAccount is a URI (=a link) that redirect to an other resource in order to close the account. In the same mind, an other URI uriToWithdrawMoney will redirect to a resource that process the withdraw.

It could be possible for a client to retrieve this resource through GET (at URI /bankingAccount/[id]) but also update only its owner name, for whatever reason.

Problem

Is it realistic to suppose that a client could update the uriToCloseAccount field of a BankingAccount's resource ? I'm not completely fine with this. I always assumed in the past, that it's not a client that is responsible of managing URI. They are here just to indicate a path to follow (or the operations to do, depending on the hypermedia format chosen) by the server itself to the client.

So the underlying question is: does links are part of resource model ? Or it is an information that is outside of the model (i don't know, maybe in the format chosen ?)

Thanks in advance !

  • I don't see why it is a problem to update a relation on a resource as long as the new related resource exists. Could you clarify ? – redben Oct 26 '15 at 11:27
  • @redben Maybe I am wrong. But IMO, the links are here to give hints to clients that they can explore the resources related to the one retrieved (through a GET or an other verbs) by following the differents links. My question is: Does the URI of these links are part of the resource model ? – AilurusFulgens Oct 26 '15 at 13:06
  • Yes they are part of the model.. on your db layer that would map to a foreign key. And generally urls in a REST are your main identifiers (they would map to primary keys and foreign keys to some extent). In your app a person is identified by an ID, on the wire the person is identified by the url – redben Oct 26 '15 at 13:14
  • Ok I see your point. My question is more related to a loosely coupled client that is not an administrator or whatever. I edit my first post for a better example. – AilurusFulgens Oct 26 '15 at 15:12
2

In the case bellow, no it should not be updated (then again is a uri to close account restful ? or withdraw money ?) class BankingAccount() { Double totalAmount; String ownerName; URI uriToCloseAccount; URI uriToWithdrawMoney; }

Suppose this is your model:

{
   "links":{
      "self": "/accounts/ACCOUNT_NUM"
      "owner":"/customers/OWNER",
      "transactions": "/transactions?account=ACCOUNT_NUM"
   }
   "number": "ACCOUNT_NUM",
   "balance": "10000 EUR"
}

changing the owner (suppose banks allow that) would be something like:

PATCH /accounts/ACCOUNT_NUM
{
   "links":{
      "owner":"/customers/NEW_OWNER",
   }
}

This of course requires /customers/NEW_OWNER to exist (the client should have checked prior to sending the update.

Now for transactions it obviously makes no sense to update that link. So the API should not allow that.

Whether or not a link is updatable depends on the meaning of the link.

Your internal Application model would of course be different, and does not have to include links

class BankingAccount() {
  int accountNumber
  Double totalAmount;
  String ownerId;
}

But you would need to add some extra mapping while marshalling/unmarshalling to your json, xml or whatever your format is :

  • accountNumber is transformed to links.self /accounts/accountNumberValue
  • ownerId is transformed to links.owner /customers/ownerIdValue
  • add links.transactions so that client can navigate to the current account's transactions => /transactions?account=accountNumberValue

closing an account

As for closing an account (which is not a resource but an operation on a resource) that would be part of the API Docs, for example: DELETE /accounts/MY_ACCOUNT or:

PATCH /accounts/MY_ACCOUNT
{
   "status":"closed"
}

But then you should add a field status to your account model.

Withdraw money

This could be modeled as an operation on transactions.

POST /transactions
{
   "links":{
      "account":"/accounts/MY_ACCOUNT"
   },
   "type":"withdraw",
   "amount": "10000 USD"
}

Notice that the target account is identified by a link.

Analogy

I know some don't like to make the analogy with databases but sometimes it makes sense to see your resources and resource collections as rows and tables:

DATABASE      | API
table         | resource collection
row           | resource
primary key   | self link
foreign key   | link to related resource 
              |   (identified by resource type name for example)
1,n relation  | link to related collection with filter query

SQL

UPDATE accounts SET owner=OWNER_ID WHERE account=ACCOUNT_ID
INSERT INTO transactions (account,type,amount) VALUE (ACCOUNT_ID,"withdrawal","10000 USD")
SELECT * FROM transactions WHERE account=ACCOUNT_ID

API

PATCH /accounts/ACCOUNT_ID
{
   "links": {
     "owner":"/owners/OWNER_ID"
   }
}

POST /transactions
{
   "links":{
      "account":"/accounts/MY_ACCOUNT"
   },
   "type":"withdraw",
   "amount": "10000 USD"
}

GET /transactions?account=MY_ACCOUNT

Why use links for relations instead of plain ids ?

Why not have field ownerId on the account resource instead of links.owner ?

Having id fields instead of links means the client knows how to construct a url for the resource which is less restful (you know... HATEOAS). But it is your choice as to how restful the API needs to be.

  • I really like the part of your answer, when you are using the terms internal (related to the Application Models), it answer nicely to my question. However, i disagree with the use of links instead of plain ids, it doesn't allow necessarily to reconstruct a uri.... as long as your URIs are opaque. – AilurusFulgens Oct 26 '15 at 16:59
  • If your URLs are opaque (which is great) and you don't provide links for related resource (only id fields) how is your client supposed to navigate to related resource with just id fields ? Of course you could provide (opaque) links AND id fields but it fees like duplication somehow (though actually that's how most APIs do it nowadays from my experience...) – redben Oct 26 '15 at 17:09
  • I was meaning: response body include id and links to others related resource (with opaque URI). But request body targeted on a opaque URI must include only id. Generally speaking, my feel is that the client play with id, and it's the responsability of the server to manage the relation between an id and a URI. – AilurusFulgens Oct 26 '15 at 17:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.