我正在使用Apache HTTP Client进行HTTPPost调用,然后我尝试使用Jackson从响应中创建一个对象。 这是我的代码:
private static final Logger log = Logger.getLogger(ReportingAPICall.class);
ObjectMapper mapper = new ObjectMapper();
public void makePublisherApiCall(String jsonRequest)
{
String url = ReaderUtility.readPropertyFile().getProperty("hosturl");
DefaultHttpClient client = new DefaultHttpClient();
try {
HttpPost postRequest = new HttpPost(url);
StringEntity entity = new StringEntity(jsonRequest);
postRequest.addHeader("content-type", "application/json");
log.info("pub id :"+ExcelReader.publisherId);
postRequest.addHeader("accountId", ExcelReader.publisherId);
postRequest.setEntity(entity);
HttpResponse postResponse = client.execute(postRequest);
log.info(EntityUtils.toString(postResponse.getEntity()));
// Response<PublisherReportResponse> response = mapper.readValue(postResponse.getEntity().getContent(), Response.class);
// log.info("Reponse "+response.toString());
} catch (UnsupportedEncodingException ex) {
log.error(ex.getMessage());
log.error(ex);
Assert.assertTrue(false, "Exception : UnsupportedEncodingException");
} catch (ClientProtocolException ex) {
log.error(ex.getMessage());
log.error(ex);
Assert.assertTrue(false, "Exception : ClientProtocolException");
} catch (IOException ex) {
log.error(ex.getMessage());
log.error(ex);
Assert.assertTrue(false, "Exception : IOException");
}
方法makePublisherApiCall()将在循环中调用,该循环运行100次。 当我取消注释该行时,基本上会出现问题:
// Response<PublisherReportResponse> response = mapper.readValue(postResponse.getEntity().getContent(), Response.class);
// log.info("Reponse "+response.toString());
取消注释后,我得到例外:
Attempted read from closed stream.
17:26:59,384 ERROR com.inmobi.reporting.automation.reportingmanager.ReportingAPICall - java.io.IOException: Attempted read from closed stream.
否则它工作正常。 有人可以让我知道我做错了什么。
答案 0 :(得分:31)
EntityUtils.toString(postResponse.getEntity())
对响应实体做了什么?我怀疑它正在消耗实体的内容流。 HttpClient javadoc状态,只有可重复的实体可以被多次使用。因此,如果实体不可重复,则无法再次将内容流提供给映射器。为避免这种情况,您应该只让映射器使用流 - 如果需要记录内容,请记录已解析的Response对象。
答案 1 :(得分:3)
我遇到了同样的问题。确保您没有在IDE的“监视”或“检查”部分中使用实体的内容流。它被消耗(阅读)后关闭。
抱歉我的英语。
答案 2 :(得分:1)
我遇到了同样的问题。
这个想法是,如果你使用postResponse,那么你应该把它放在一个变量中,以便在不同的地方再次使用它。 否则,连接已关闭,您再也无法再使用相同的响应。
我曾经记录它(出于调试目的)并且总是失败。
答案 3 :(得分:0)
我认为此问题与任何回应均无关, 我收到此问题是因为我没有使用
closeableresponce=client.Getmethod(FinalUrl);
在我的第一个Test1中,提到了它,但是当我错过了Test2时,我忘记了放这段代码,这就是为什么流关闭消息显示的原因...
public void getapiwithheader() throws ParseException, IOException
{
client = new RestClient();
closeableresponce=client.Getmethod(FinalUrl);
HashMap<String, String> headermap = new HashMap<>();
headermap.put("content-type", "application/json");
//****************************************************************************
//Status code
//****************************************************************************
int statuscode =closeableresponce.getStatusLine().getStatusCode();
System.out.println("Status code "+statuscode);
Assert.assertEquals(statuscode,RESPONSE_STATUS_CODE_200, "Status code is not 200");
//****************************************************************************
// Json String
//****************************************************************************
String responsestring= EntityUtils.toString(closeableresponce.getEntity(),"UTF-8");
JSONObject respjsonobj = new JSONObject(responsestring);
System.out.println("Respose Json API"+respjsonobj);
//****************************************************************************
// Verify the value of the JSON
//****************************************************************************
String Email =TestUtil.getValueByJPath(respjsonobj,"/email");
System.out.println("******************************************");
System.out.println("Print the value of Email "+Email);
Assert.assertEquals(Email, "johndoe@google.com");
}
答案 4 :(得分:0)
我在这里找到了与Spring RestTemplate类似问题的答案:https://www.baeldung.com/spring-rest-template-interceptor
如果我们希望拦截器充当请求/响应记录器,那么我们需要对其进行两次读取-第一次由拦截器读取,第二次由客户端读取。 默认实现使我们只能读取一次响应流。为了满足这种特定情况,Spring提供了一个特殊的类BufferingClientHttpRequestFactory。顾名思义,此类将请求/响应缓冲在JVM内存中以供多种使用。
以下是使用BufferingClientHttpRequestFactory初始化RestTemplate对象以启用请求/响应流缓存的方法:
RestTemplate restTemplate = new RestTemplate( new BufferingClientHttpRequestFactory( new SimpleClientHttpRequestFactory() ) );
答案 5 :(得分:-1)
我有同样的问题。
对于我来说,我需要通过AOP /
获取响应内容