Spring RestTemplateエラー処理
1. 概要
この短いチュートリアルでは、RestTemplateインスタンスにResponseErrorHandlerインターフェースを実装して挿入する方法について説明します。これにより、リモートAPIから返されるHTTPエラーを適切に処理できます。
2. デフォルトのエラー処理
デフォルトでは、HTTPエラーの場合、RestTemplateは次のいずれかの例外をスローします。
-
HttpClientErrorException –HTTPステータス4xxの場合
-
HttpServerErrorException – HTTPステータス5xxの場合
-
不明なHTTPステータスの場合のUnknownHttpStatusCodeException – in
これらの例外はすべて、RestClientResponseExceptionの拡張です。
Obviously, the simplest strategy to add a custom error handling is to wrap the call in a try/catch block.次に、キャッチされた例外を適切と思われる方法で処理します。
ただし、リモートAPIまたは呼び出しの数が増えるとthis simple strategy doesn’t scale wellになります。 すべてのリモート呼び出しに再利用可能なエラーハンドラーを実装できれば、より効率的です。
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 to を使用して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ステータスを返すことにより、このハンドラーをテストしましょう。
@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のカスタムエラーハンドラーを実装してテストするためのソリューションを紹介しました。
いつものように、この記事で紹介されているコードはover on Githubで利用できます。