チェック処理を追加したRest APIサービスは、Spring Bootを利用したアプリケーションで呼び出し、エラー時のレスポンスを取得することができる。
今回は、STS(Spring Tool Suite)を利用したSpring Bootアプリケーション上で、特定のテーブルのデータ追加・更新を行う際にチェック処理を行うRest APIサービスを呼び出し、エラー時のレスポンスを取得してみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装がそれぞれ完了していること。
作成したサンプルプログラムの内容
作成したサンプルプログラムの構成は以下の通り。
なお、上記の赤枠は、前提条件のdemoRestApiCallプロジェクトのプログラムから追加・変更したプログラムである。
Rest APIでデータ追加・更新時にチェックエラーになる処理の呼び出しを実行するサービスクラスの内容は以下の通りで、各種エラーになった場合の戻り値をDemoExceptionResponseクラスで取得している。
package com.example.demo; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.databind.ObjectMapper; @Service public class DemoRestApiCallCheckService { /** ユーザーデータを追加するURL */ private static final String POST_USER = "http://localhost:8085/users"; /** id=3のユーザーデータを更新するURL */ private static final String PUT_USER_3 = "http://localhost:8085/users/3"; /** RestTemplateオブジェクト */ @Autowired private RestTemplate restTemplate; /** HttpHeadersオブジェクト */ @Autowired private HttpHeaders httpHeaders; /** ObjectMapperオブジェクト */ @Autowired private ObjectMapper objectMapper; /** ログ出力のためのクラス */ private static Log log = LogFactory.getLog(DemoRestApiCallCheckService.class); /** * Rest APIでデータ追加・更新時にチェックエラーになる処理の呼び出しを実行する. */ public void execRestApiCheck() { log.debug("*** USER_DATAテーブルに(名前の)チェックエラーとなるデータを" + "追加しようとした結果 ***"); try { UserData newUserData = new UserData(4, "", 2012, 2, 25, "1", "テスト4"); restTemplate.exchange(POST_USER, HttpMethod.POST , new HttpEntity<>(newUserData, httpHeaders), UserData.class); log.debug("(名前の)チェックエラーとなるため、この部分は通過しない"); } catch (HttpClientErrorException ex) { try { DemoExceptionResponse demoExceptionResponse = objectMapper.readValue( ex.getResponseBodyAsString(), DemoExceptionResponse.class); log.error("発生したエラーメッセージ : " + demoExceptionResponse.getMessage()); log.debug("エラー時のレスポンス内容 : " + demoExceptionResponse); log.debug(""); } catch (Exception ex2) { log.error(ex2); return; } } log.debug("*** USER_DATAテーブルに(生年月日の)チェックエラーとなるデータを" + "追加しようとした結果 ***"); try { UserData newUserData = new UserData(4, "テスト プリン4", 2012, 2, 30 , "1", "テスト4"); restTemplate.exchange(POST_USER, HttpMethod.POST , new HttpEntity<>(newUserData, httpHeaders), UserData.class); log.debug("(生年月日の)チェックエラーとなるため、この部分は通過しない"); } catch (HttpClientErrorException ex) { try { DemoExceptionResponse demoExceptionResponse = objectMapper.readValue( ex.getResponseBodyAsString(), DemoExceptionResponse.class); log.error("発生したエラーメッセージ : " + demoExceptionResponse.getMessage()); log.debug("エラー時のレスポンス内容 : " + demoExceptionResponse); log.debug(""); } catch (Exception ex2) { log.error(ex2); return; } } log.debug("*** USER_DATAテーブルに(性別の)チェックエラーとなるデータを" + "追加しようとした結果 ***"); try { UserData newUserData = new UserData(4, "テスト プリン4", 2012, 2, 25 , "3", "テスト4"); restTemplate.exchange(POST_USER, HttpMethod.POST , new HttpEntity<>(newUserData, httpHeaders), UserData.class); log.debug("(性別の)チェックエラーとなるため、この部分は通過しない"); } catch (HttpClientErrorException ex) { try { DemoExceptionResponse demoExceptionResponse = objectMapper.readValue( ex.getResponseBodyAsString(), DemoExceptionResponse.class); log.error("発生したエラーメッセージ : " + demoExceptionResponse.getMessage()); log.debug("エラー時のレスポンス内容 : " + demoExceptionResponse); log.debug(""); } catch (Exception ex2) { log.error(ex2); return; } } log.debug("*** USER_DATAテーブルに(名前・生年月日・性別の)チェックエラーと" + "なるデータを追加しようとした結果 ***"); try { UserData newUserData = new UserData(4, "", 2012, 2, 30, "3", "テスト4"); restTemplate.exchange(POST_USER, HttpMethod.POST , new HttpEntity<>(newUserData, httpHeaders), UserData.class); log.debug("(名前・生年月日・性別の)チェックエラーとなるため、この部分は通過しない"); } catch (HttpClientErrorException ex) { try { DemoExceptionResponse demoExceptionResponse = objectMapper.readValue( ex.getResponseBodyAsString(), DemoExceptionResponse.class); log.error("発生したエラーメッセージ : " + demoExceptionResponse.getMessage()); log.debug("エラー時のレスポンス内容 : " + demoExceptionResponse); log.debug(""); } catch (Exception ex2) { log.error(ex2); return; } } log.debug("*** USER_DATAテーブルに(名前・生年月日・性別の)チェックエラーと" + "なるデータを更新しようとした結果 ***"); try { UserData updUserData = new UserData(0, "", 2012, 2, 30, "3", "テスト4"); restTemplate.exchange(PUT_USER_3, HttpMethod.PUT , new HttpEntity<>(updUserData, httpHeaders), UserData.class); log.debug("(名前・生年月日・性別の)チェックエラーとなるため、この部分は通過しない"); } catch (HttpClientErrorException ex) { try { DemoExceptionResponse demoExceptionResponse = objectMapper.readValue( ex.getResponseBodyAsString(), DemoExceptionResponse.class); log.error("発生したエラーメッセージ : " + demoExceptionResponse.getMessage()); log.debug("エラー時のレスポンス内容 : " + demoExceptionResponse); log.debug(""); } catch (Exception ex2) { log.error(ex2); return; } } } }
また、各種エラーになった場合の戻り値を定義するクラスの内容は以下の通りで、前提条件のdemoRestApiプロジェクトのDemoExceptionResponseクラスと同じ項目を定義している。
package com.example.demo; import java.util.Date; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; //「@Data」アノテーションを付与すると、このクラス内の全フィールドに対する //Getterメソッド・Setterメソッドにアクセスができる //「@NoArgsConstructor」は、引数をもたないコンストラクタを生成するアノテーション //「@AllArgsConstructor」は、全てのメンバを引数にもつコンストラクタを生成するアノテーション @Data @NoArgsConstructor @AllArgsConstructor public class DemoExceptionResponse { /** メッセージ */ private String message; /** メッセージ詳細 */ private String details; /** 発生日時 */ private Date timestamp; }
さらに、Beanオブジェクトを定義するクラスの内容は以下の通りで、ObjectMapperクラスのBeanオブジェクトを追加している。
package com.example.demo; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.databind.ObjectMapper; @Configuration public class DemoConfigBean { /** * RestTemplateオブジェクトを作成する * @return RestTemplateオブジェクト */ @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); } /** * ContentType:JSONであるHttpHeadersオブジェクトを作成する * @return HttpHeadersオブジェクト */ @Bean public HttpHeaders getHttpHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } /** * ObjectMapperオブジェクトを作成する * @return ObjectMapperオブジェクト */ @Bean public ObjectMapper getObjectMapper() { return new ObjectMapper(); } }
また、Spring Bootのメインクラスの内容は以下の通りで、Rest APIでデータ追加・更新時にチェックエラーになる処理の呼び出しを実行するサービスクラスを呼び出している。
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 { /** Rest APIでデータ追加・更新時にチェックエラーになる処理の呼び出しを実行するサービスクラス */ @Autowired private DemoRestApiCallCheckService demoRestApiCallCheckService; public static void main(String[] args) { SpringApplication.run(DemoRestApiCallApplication.class, args); } @Override public void run(String... args) throws Exception { // Rest APIでデータ追加・更新時にチェックエラーになる処理を呼び出す demoRestApiCallCheckService.execRestApiCheck(); } }
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-call-rest-api-check/demoRestApiCall
サンプルプログラムの実行結果
Rest APIサービスのSpring Bootアプリケーションを起動後、今回作成したプロジェクトのSpring Bootアプリケーションを起動する。その結果出力されたログの内容は以下の通りで、エラー時のメッセージやレスポンスが想定通りに取得できていることが確認できる。
要点まとめ
- チェック処理を追加したRest APIサービスは、Spring Bootを利用したアプリケーションで呼び出し、エラー時のレスポンスを取得することができる。