Tagbangers Blog

HATEOAS をおさらい

HATEOAS とは?


Hypermedia As The Engine Of Application State (HATEOAS) is a component of the REST application architecture that distinguishes it from other network application architectures.

With HATEOAS, a client interacts with a network application whose application servers provide information dynamically through hypermedia. A REST client needs little to no prior knowledge about how to interact with an application or server beyond a generic understanding of hypermedia.

By contrast, clients and servers in CORBA interact through a fixed interface shared through documentation or an interface description language (IDL).

The way that the HATEOAS constraint decouples client and server enables the server functionality to evolve independently.

- HATEOAS  Wikipedia -

HATEOAS は REST の一部であり、リソースに対する情報や操作について前情報なしに扱うことが出来るよ。ということです。

どういうことかというと。

Amazon みたいな EC サイトの API を考えるときに Book を操作したいとします。
Book リソースは URL で表現されます。名前みたいなもんですね。

/books/isbn

アクセスしたときの反応(レスポンス)はどんなものでしょう。

  • タイトル
  • 作者
  • 在庫数
  • 評価
  • などなど

Book に対する情報が含まれることを期待します。
HATEOAS ではさらに Book に対してなにが出来るのかがすべて表現されます

  • 購入
  • 作者の詳細をみる
  • 評価の詳細をみる
  • 評価を追加する
  • などなど

つまり、リソースにアクセスすることができる = リソースに対する操作が出来る(できないことは表現されない)。
そこが一番の特徴です。

それのなにが便利なのか??

API を使う人(多分アプリケーションの開発者)は Book に対していろんな機能を作ります。
その中には Book の購入履歴とかもあるでしょう。
このときに履歴に表示される Book がキャンセル出来るか、できないかにより画面の表示も変更したいですよね。

HATEOAS であまり難しく考える必要はありません。
キャンセルのリンクがレスポンスに含まれるときのみキャンセル出来るからです。(出来ることのみ表現する。のルールが守られる前提です)
便利ですね。素敵。

HATEOAS なんて読むの?

ヘイトオアス とか ヘイトオース とか。決まりはなく、なんでもいいと思います。

Note: Pronunciations of HATEOAS vary. Some people pronounce it as "hate-ee-os," similar to "hideous," or as "hate O-A-S". People also refer to it as a hypermedia-driven system.

- Understanding HATEOAS -

Spring HATEOAS


概要

Spring とくに Spring MVC において HATEOAS を表現するのを助けてくれる APIたち。それが Spring HATEOAS です。

Spring HATEOAS provides some APIs to ease creating REST representations that follow the HATEOAS principle when working with Spring and especially Spring MVC. The core problem it tries to address is link creation and representation assembly.

- Spring HATEOAS - Reference Documentation -

Link

HTML documet 内のこれと同じです。

<link href="theme.css" rel="stylesheet" type="text/css" />

簡単な Link を作成してみましょう。

以下は ControllerLinkBuilder を使って Link を作るサンプルです。

public class Greeting extends ResourceSupport {

    private final String content;

    @JsonCreator
    public Greeting(@JsonProperty("content") String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }
}

@RestController
public class GreetingController {

    private static final String TEMPLATE = "Hello, %s!";

    @RequestMapping("/greeting")
    public HttpEntity<Greeting> greeting(
            @RequestParam(value = "name", required = false, defaultValue = "World") String name) throws NoSuchMethodException {

        greeting.add(ControllerLinkBuilder.linkTo(ControllerLinkBuilder.methodOn(GreetingController.class).greeting(name)).withSelfRel());

        return new ResponseEntity<>(greeting, HttpStatus.OK);
    }
}

以下の箇所で Link の作成と Response への追加を行っています。

greeting.add(ControllerLinkBuilder.linkTo(ControllerLinkBuilder.methodOn(GreetingController.class).greeting(name)).withSelfRel());

/greeting にアクセスした際のレスポンスは

{
    "content": "Hello, World!",
    "_links": {
        "self": {
            "href": "http://localhost:8080/greeting?name=World"
        }
    }
}


アフォーダンス

Spring HATEOAS で使用されている Affordances はデザインの用語として使用されるそれと同じ意味合いで使われていると思われます。

あるリソースに対してどのような操作が可能なのかをレスポンスで示すことが HATEOAS におけるアフォーダンスです。

アフォーダンス - wikipedia -

以下は HAL-FORMS におけるアフォーダンスの例です。

_templates が追加されており、 put や patch リクエストの際の必須項目や項目名もレスポンスに含まれます。

このこの事により API を使用するクライアントは項目を気にする必要もなく、 API に変更があった際にもクライアントサイドは変更なしに対応が可能です。

{
  "firstName" : "Frodo",
  "lastName" : "Baggins",
  "role" : "ring bearer",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/employees/1"
    }
  },
  "_templates" : {  
    "default" : {
      "title" : null,
      "method" : "put", 
      "contentType" : "",
      "properties" : [ { 
        "name" : "firstName",
        "required" : true 
      }, {
        "name" : "lastName",
        "required" : true
      }, {
        "name" : "role",
        "required" : true
      } ]
    },
    "partiallyUpdateEmployee" : { 
      "title" : null,
      "method" : "patch", 
      "contentType" : "",
      "properties" : [ {
        "name" : "firstName",
        "required" : false 
      }, {
        "name" : "lastName",
        "required" : false
      }, {
        "name" : "role",
        "required" : false
      } ]
    }
  }
}

最後に


HAL、HAL-FORMS などの Media type の詳細については別の機会に触れたいと思います。

Spring HATEOAS は 現在(2019-04-05)のバージョンが 0.25.1 ということでまだまだ仕様が変更される余地がありますが、
Spring Data REST では積極的に採用されていたりと、面白い仕様ですのでこれからも注目していきたいと思います。

参考

Spring HATEOAS Document - 1.0.0.M1 -