Spring RestTemplateのエラー処理
1.概要
この短いチュートリアルでは、
RestTemplate
インスタンスに
ResponseErrorHandler
インターフェースを実装して注入し、リモートAPIから返されたHTTPエラーを適切に処理する方法について説明します。
2.デフォルトのエラー処理
デフォルトでは、HTTPエラーが発生した場合、
RestTemplate
は次のいずれかの例外をスローします。
-
HttpClientErrorException
– HTTPステータス4xxの場合 -
_HttpServerErrorException – HTTPステータスが5xxの場合は
_
-
_UnknownHttpStatusCodeException – 不明なHTTPステータスの場合は
_
これらの例外はすべて
RestClientResponseException
の拡張です。
-
明らかに、カスタムエラー処理を追加するための最も簡単な戦略は、呼び出しを
try/catch
ブロックでラップすることです。
ただし、リモートAPIまたはリモート呼び出しの数が増えると、
この単純な方法ではうまく拡張できません
。すべてのリモート呼び出しに対して再利用可能なエラーハンドラを実装できれば、さらに効率的になります。
3.
ResponseErrorHandler
を実装する
そのため、____ResponseErrorHandlerを実装するクラスは、応答からHTTPステータスを読み取ります。
-
我々のアプリケーションにとって意味のある例外を投げる
-
HTTPステータスを無視して応答フローを続行させるだけです
中断することなく
ResponseErrorHandler
実装を
RestTemplate
インスタンスに注入する必要があります。
したがって、
RestTemplateBuilder
を使用してテンプレートを構築し、応答フロー内の
DefaultResponseErrorHandler
を置き換えます。
それでは、まず__RestTemplateResponseErrorHandlerを実装しましょう。
@Component
public class RestTemplateResponseErrorHandler
implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse httpResponse)
throws IOException {
return (
httpResponse.getStatusCode().series() == CLIENT__ERROR
|| httpResponse.getStatusCode().series() == SERVER__ERROR);
}
@Override
public void handleError(ClientHttpResponse httpResponse)
throws IOException {
if (httpResponse.getStatusCode()
.series() == HttpStatus.Series.SERVER__ERROR) {
//handle SERVER__ERROR
} else if (httpResponse.getStatusCode()
.series() == HttpStatus.Series.CLIENT__ERROR) {
//handle CLIENT__ERROR
if (httpResponse.getStatusCode() == HttpStatus.NOT__FOUND) {
throw new NotFoundException();
}
}
}
}
次に、
RestTemplateResponseErrorHandlerを導入するために
RestTemplateBuilderを使用して
RestTemplate__インスタンスを構築します。
@Service
public class BarConsumerService {
private RestTemplate restTemplate;
@Autowired
public BarConsumerService(RestTemplateBuilder restTemplateBuilder) {
RestTemplate restTemplate = restTemplateBuilder
.errorHandler(new RestTemplateResponseErrorHandler())
.build();
}
public Bar fetchBarById(String barId) {
return restTemplate.getForObject("/bars/4242", Bar.class);
}
}
4.実装のテスト
最後に、サーバーをモックして
NOT
FOUND__ステータスを返すことでこのハンドラをテストしましょう。
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { NotFoundException.class, Bar.class })
@RestClientTest
public class RestTemplateResponseErrorHandlerIntegrationTest {
@Autowired
private MockRestServiceServer server;
@Autowired
private RestTemplateBuilder builder;
@Test(expected = NotFoundException.class)
public void givenRemoteApiCall__when404Error__thenThrowNotFound() {
Assert.assertNotNull(this.builder);
Assert.assertNotNull(this.server);
RestTemplate restTemplate = this.builder
.errorHandler(new RestTemplateResponseErrorHandler())
.build();
this.server
.expect(ExpectedCount.once(), requestTo("/bars/4242"))
.andExpect(method(HttpMethod.GET))
.andRespond(withStatus(HttpStatus.NOT__FOUND));
Bar response = restTemplate
.getForObject("/bars/4242", Bar.class);
this.server.verify();
}
}
5.まとめ
この記事では、HTTPエラーを意味のある例外に変換する
RestTemplate
のカスタムエラーハンドラを実装してテストするための解決策を紹介しました。
いつものように、この記事で紹介したコードはhttps://github.com/eugenp/tutorials/tree/master/spring-resttemplate[over on Github]から入手できます。