简体   繁体   中英

Generating a HATEOAS client library

Suppose I have a RESTful API for managing orders which uses HAL to facilitate HATEOAS:

GET /orders/2
  {
    "_links": {
      "self": "/orders/2",
      "items": "/orders/2/items"
    },
    "subtotal": 30.0,
    "shipped": false
  }

I want to write my client (application) using a set of interfaces so that, assuming that implementations of these interfaces are DI-d/built by DI-d factories, etc., I don't really (want to) have to care that they're backed by my RESTful API. As an example (pseudo C#/Java):

public interface Order {
  public void addItem(Item item);
  public float getSubtotal();
  public boolean getShipped();
}

Order order = ...;
Item item = ...;
order.addItem(item);
...(order.getSubtotal())...;

My question is : can I/does it make sense to generate implementations of the Order / Item interface from the API? By this I mean in a manner similar to that offered with C#/web services which export WSDLs.

I've been thinking about implementing OPTIONS for resources such as /orders and /orders/{id} so that I'd effectively have a HATEOAS API for traversing the schema of the API:

GET /orders/* (I'd need a suitable wildcard of course)
  {
    "_links": {
      "addItem": {
        "href": "/orders/{id}/items",
        "templated": true,
        "type": "method"
      }
    }
  }

Of course I could make this part of the _links object returned with any given resource ( /orders/2 , for instance) but that precludes static code generation.

I'm wondering if there's a sensible way to encapsulate the fact that if a particular link is provided, the related action should be available/performed, otherwise not.

Note: In case it matters, I'm actually working in JavaScript (specifically with AngularJS). However, I'd still like to write my application using a set of conceptual interfaces/contracts.

My question is: can I/does it make sense to generate implementations of the Order/Item interface from the API? By this I mean in a manner similar to that offered with C#/web services which export WSDLs.

It partially makes sense. By a simple CRUD API you can map the resources to the entities. By complex applications it does not work, because you map URI s to resource s and METHOD URI pairs to operation s. So every time if you need an operation not defined by HTTP, you have to create a new resource or at least a new URI for an already existing resource.

Some examples:

  • transfer money from one account to another: POST /transfer [acc1, acc2, amount, currency] - the transfer does not necessary exist as an entity in your domain logic (don't try that kind of solution in production code unless you want bankruptcy :D)
  • sending an email to another user: POST /messages [recipient, message]
  • you can map resources to value objects too: GET /users/123/address
  • you can use URIs to map reduce a collection: GET /users?name="John"
  • you can use PUT /users/123 [details] instead of POST /users [details] to create a new user
  • you can use POST /player/123/xp/increment 10 instead of PUT /player/123/xp [xp+10] to update the experience points of a player

About the WSDL like solutions you can read alot more here: Third Generation Web APIs - Markus Lanthaler .

My personal opinion that it does not worth the effort to build such a system, because it has more drawbacks than advantages.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM