暇な日々にスパイスを

学んだ技術の備忘録

Spring Boot 17 RestTemplateのバグ対策

久々のSpring Bootです。

RestTemplateでエラー時のテスト実装中にハマりました。
RestTemplateは返り値のステータスコードが異常系の場合、HttpClientExceptionを発生させます。 このHttpClientExceptionからステータスコードやレスポンスボディを取得可能です。
しかし、BadRequest時にはレスポンスボディが入っていないというバグが有るようです。

解決策は下記記事に記載されていました。
stackoverflow.com

RestTemplateの宣言時に、デフォルトではなく、HttpComponentsClientHttpRequestFactoryを使えとのことでした。

    RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

POSTメソッドに実装した結果、以下のようになりました。

 /**
   * POSTメソッド用
   *
   * @param url 対象APIのURL
   * @param request リクエストの型(JSON変換される)
   * @param responseClass JSONをパースした型
   * @return レスポンス
   */
  public static <T1, T2> ResponseEntity<T2> post(String url, T1 request, Class<T2> responseClass)
      throws ResourceAccessException, IOException {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Type", "application/json;charset=UTF-8");

    ObjectMapper mapper = new ObjectMapper();
    HttpEntity<String> entity = new HttpEntity<String>(mapper.writeValueAsString(request), headers);

    RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
    ResponseEntity<T2> result = null;
    try {
      result = restTemplate.exchange(url, HttpMethod.POST, entity, responseClass);
    } catch (HttpClientErrorException e) {
      T2 err = mapper.readValue(e.getResponseBodyAsString(), responseClass);
      return new ResponseEntity<T2>(err, e.getStatusCode());
    }
    return result;
  }