HATEOASを利用すると、RestAPIサービスにおいて、例えば、データ追加後に、追加したデータを取得するURL情報も合わせて返却することができる。
HATEOASについては、以下のサイトを参照のこと。
https://blog.tagbangers.co.jp/2019/04/05/HATEOAS
今回は、STS(Spring Tool Suite)を利用したSpring Bootアプリケーション上で、HATEOASを利用して、データ追加後に、追加したデータを取得するURL情報も合わせて返却してみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装がそれぞれ完了していること。
作成したサンプルプログラム(APIサービス)の内容
作成したサンプルプログラム(APIサービス)の構成は以下の通り。
なお、上記の赤枠は、前提条件のプログラムから変更したプログラムである。
pom.xmlの内容は以下の通りで、URL情報を追加するHATEOASのライブラリを追加している。
1 2 3 4 5 | <!-- HATEOASを利用するためのライブラリを追加 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-hateoas</artifactId> </dependency> |
また、Restコントローラクラスの内容は以下の通りで、ユーザー情報を追加後、追加したデータを取得するURLを返却するsaveUserDataHateoasメソッドを追加している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | package com.example.demo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; import java.util.List; import java.util.Optional; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; /** * Rest API定義クラス */ @RestController public class DemoRestController { /** ユーザーデータテーブル(user_data)アクセス用リポジトリ */ @Autowired private UserDataRepository repository; /** * ユーザーデータリストを取得する. * @return ユーザーデータリスト */ @GetMapping("/users") public List<UserData> getAllUserData() { return repository.findAll(); } /** * 指定したIDをもつユーザーデータを取得する. * @param id ID * @return 指定したIDをもつユーザーデータ */ @GetMapping("/users/{id}") public UserData getOneUserData(@PathVariable long id) { Optional<UserData> userData = repository.findById(id); // 指定したIDをもつユーザーデータがあればそのユーザーデータを返す if(userData.isPresent()) { return userData.get(); } // 指定したIDをもつユーザーデータがなければnullを返す return null; } /** * 指定したユーザーデータを登録する. * @param userData ユーザーデータ * @return 登録したユーザーデータ */ @PostMapping("/users") public UserData saveUserData(@Valid @RequestBody UserData userData) { return repository.save(userData); } /** * 指定したユーザーデータを更新する. * @param id ID * @param userData ユーザーデータ * @return 更新したユーザーデータ */ @PutMapping("/users/{id}") public UserData updateUserData(@PathVariable long id , @Valid @RequestBody UserData userData) { userData.setId(id); return repository.save(userData); } /** * 指定したIDをもつユーザーデータを削除する. * @param id ID */ @DeleteMapping("/users/{id}") public void deleteUserData(@PathVariable long id) { Optional<UserData> userData = repository.findById(id); // 指定したIDをもつユーザーデータがあればそのユーザーデータを削除する if(userData.isPresent()) { repository.deleteById(id); } } /** * 指定したユーザーデータを登録し、登録したデータを取得するURLを返却する. * @param userData ユーザーデータ * @return 登録したデータとそれを取得するURLを含むエンティティモデル */ @PostMapping("/users/hateoas") public EntityModel<UserData> saveUserDataHateoas( @Valid @RequestBody UserData userData) { UserData addUserData = repository.save(userData); if(addUserData == null) { return null; } EntityModel<UserData> entityModel = EntityModel.of(addUserData); WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).getOneUserData(addUserData.getId())); entityModel.add(linkTo.withRel("getAddUserDataUrl")); return entityModel; } } |
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-rest-api-hateoas/demoRestApi
作成したサンプルプログラム(API呼び出し)の内容
作成したサンプルプログラム(API呼び出し)の構成は以下の通り。
なお、上記の赤枠は、前提条件のプログラムから追加・変更したプログラムである。
pom.xmlの内容は以下の通りで、URL情報を追加するHATEOASのライブラリを追加している。
1 2 3 4 5 | <!-- HATEOASを利用するためのライブラリを追加 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-hateoas</artifactId> </dependency> |
また、Rest APIでユーザー情報を追加後、追加したデータを取得するURLを返却する処理の呼び出しを実行するサービスクラスの内容は以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | package com.example.demo; import java.util.Optional; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.ParameterizedTypeReference; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class DemoRestApiHateoasService { /** ユーザーデータを追加し、追加したデータを取得するURLも返却可能となるURL */ private static final String POST_USER_HATEOAS = "http://localhost:8085/users/hateoas"; /** RestTemplateオブジェクト */ @Autowired private RestTemplate restTemplate; /** HttpHeadersオブジェクト */ @Autowired private HttpHeaders httpHeaders; /** ログ出力のためのクラス */ private static Log log = LogFactory.getLog(DemoRestApiHateoasService.class); public void execRestApiHateoas() { log.debug("*** USER_DATAテーブルにid=4のデータを追加し、" + "追加したデータを取得するURLも返却した結果 ***"); // user_dataテーブルに、id=4であるデータを追加 UserData newUserData = new UserData(4, "テスト プリン4", 2014, 10, 11, "1", "テスト4"); ResponseEntity<EntityModel<UserData>> response = restTemplate.exchange(POST_USER_HATEOAS, HttpMethod.POST , new HttpEntity<>(newUserData, httpHeaders) , new ParameterizedTypeReference<EntityModel<UserData>>() {}); // 戻り値を「EntityModel<UserData>」型で取得 EntityModel<UserData> entityModel = response.getBody(); // user_dataテーブルで、追加されたデータを出力 UserData addUserData = entityModel.getContent(); log.debug("追加されたuser_dataテーブルの値: " + addUserData); // 追加したデータを取得するURLを出力 Optional<Link> optLink = entityModel.getLink("getAddUserDataUrl"); if(optLink.isPresent()) { String getAddUserDataUrl = optLink.get().toUri().toString(); log.debug("追加したデータを取得するURL : " + getAddUserDataUrl); } } } |
さらに、Spring Bootのメインクラスの内容は以下の通りで、Rest APIでユーザー情報を追加後、追加したデータを取得するURLを返却する処理の呼び出しを実行するサービスクラスを呼び出している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoRestApiCallApplication implements CommandLineRunner { /** ユーザーデータを追加し、追加したデータを取得するURLも返却する処理の呼び出しを 実行するサービスクラス */ @Autowired private DemoRestApiHateoasService demoRestApiHateoasService; public static void main(String[] args) { SpringApplication.run(DemoRestApiCallApplication.class, args); } @Override public void run(String... args) throws Exception { // ユーザーデータを追加し、追加したデータを取得するURLも返却する処理を呼び出す demoRestApiHateoasService.execRestApiHateoas(); } } |
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-rest-api-hateoas/demoRestApiCall
サンプルプログラムの実行結果
サンプルプログラムの実行結果は、以下の通り。
1) 接続先となるOracleデータベース上に、以下のUSER_DATAテーブルとデータを作成しておく。
2) 作成したサンプルプログラム(APIサービス)のSpring Bootアプリケーションと、Postmanを起動する。その後。リクエストを「POST」、URLを「http://localhost:8085/users/hateoas」、リクエストボディに追加するデータをJSON形式で設定して「Send」ボタンを押下する。
3) 実行した結果、以下のように、追加したデータと追加したデータを取得するURLが返却されることが確認できる。
4) 2)~3)までの操作を実行後に、接続先となるOracleデータベース上のUSER_DATAテーブルを確認すると、id=4のデータが追加されていることが確認できる。
6) 作成したサンプルプログラム(API呼び出し)のSpring Bootアプリケーションを起動する。その結果出力されたログの内容は以下の赤枠の部分で、追加したデータと追加したデータを取得するURLが返却されることが確認できる。
7) 5)~6)までの操作を実行後に、接続先となるOracleデータベース上のUSER_DATAテーブルを確認すると、id=4のデータが追加されていることが確認できる。
要点まとめ
- RestAPIサービスにおいて、HATEOASを利用すると、返却する情報にURL情報を追加することができる。