RestTemplate クラスの doExecute() 内には、次のコードがあります。
...
response = request.execute();
if (!getErrorHandler().hasError(response)) {
logResponseStatus(method, url, response);
}
else {
handleResponseError(method, url, response);
}
if (responseExtractor != null) {
return responseExtractor.extractData(response);
}
else {
return null;
}
...
OAuth2RestTemplate を使用する場合、ResponseErrorHandler は OAuth2ErrorHandler に設定されます。私の特定のユースケースでは、(oauth トークンを取得した後の) リクエストは、コード内で処理したい 400 エラーを返しています。そのため、何もしないように DefaultResponseHandler.handleError() をオーバーライドするカスタム ハンドラーを渡して OAuth2ErrorHandler を作成しました。これにより、RestTemplate.postForEntity() を呼び出すコードが ResponseEntity を取得できるようになり、それに対してさらに評価を行うことができます。
今私が見ている問題は、上記のコードの handleResponseError 内で、それが OAuth2ErrorHandler.handleError() に入り、そのコード内に次の注意事項があることです。
...
// Need to use buffered response because input stream may need to be consumed multiple times.
ClientHttpResponse bufferedResponse = new ClientHttpResponse() {
...
これは、OAuth2ErrorHandler がデリゲート errorHandler を呼び出したときにうまく機能します。これは、errorHandler が応答も読み取ることができるためです。残念ながら、そのメソッドが bufferedResponse を返すと、もはや利用できず、 responseExtractor.extractData(response) が呼び出されると、入力ストリームが閉じられます。
私が見ている例外は次のとおりです。
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Attempted read from closed stream.; nested exception is java.io.IOException: Attempted read from closed stream.
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:228)
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.read(MappingJackson2HttpMessageConverter.java:220)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:95)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:788)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:773)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:553)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.doExecute(OAuth2RestTemplate.java:128)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:506)
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:361)
Caused by: java.io.IOException: Attempted read from closed stream.
at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:167)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:137)
at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.ensureLoaded(ByteSourceJsonBootstrapper.java:503)
at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.detectEncoding(ByteSourceJsonBootstrapper.java:129)
at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.constructParser(ByteSourceJsonBootstrapper.java:224)
at com.fasterxml.jackson.core.JsonFactory._createParser(JsonFactory.java:1242)
at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:753)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2158)
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:225)
... 31 common frames omitted
この問題を回避する方法はありますか? 私のユース ケースでは、OAuth2RestTemplate を使用して OAuth ハンドシェイクを処理し、ResponseEntity に対して独自のコード ロジックを実行できるようにしたいと考えています。