SpringRestTemplateエラー処理
1. 概要
この短いチュートリアルでは、ResponseErrorHandlerインターフェースをRestTemplateインスタンスに実装して挿入し、リモート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();
}
}
}
}
次に、RestTemplateBuilderを使用してRestTemplate インスタンスを構築し、 RestTemplateResponseErrorHandler :を導入します。
@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 ステータスを返すことにより、このハンドラーをテストしてみましょう。
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { NotFoundException.class, Bar.class })
@RestClientTest
public class RestTemplateResponseErrorHandlerIntegrationTest {
@Autowired
private MockRestServiceServer server;
@Autowired
private RestTemplateBuilder builder;
@Test
public void givenRemoteApiCall_when404Error_thenThrowNotFound() {
Assertions.assertNotNull(this.builder);
Assertions.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));
Assertions.assertThrows(NotFoundException.class, () -> {
Bar response = restTemplate.getForObject("/bars/4242", Bar.class);
});
}
}
5. 結論
この記事では、HTTPエラーを意味のある例外に変換するRestTemplateのカスタムエラーハンドラーを実装およびテストするためのソリューションを紹介しました。
いつものように、この記事で紹介するコードは、Githubでから入手できます。