Would appreciate any help regarding my issue on one of my maven projects.
Exception in thread "main" org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://test-services.domain.ph/campaign/": Premature EOF; nested exception is java.io.IOException: Premature EOF
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:666)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:407)
at homecredit.ph.CampaignConnector.call(CampaignConnector.java:46)
Caused by: java.io.IOException: Premature EOF
at sun.net.www.http.ChunkedInputStream.readAheadBlocking(ChunkedInputStream.java:565)
at sun.net.www.http.ChunkedInputStream.readAhead(ChunkedInputStream.java:609)
at sun.net.www.http.ChunkedInputStream.read(ChunkedInputStream.java:696)
at java.io.FilterInputStream.read(FilterInputStream.java:133)
Origin:
ResponseEntity<ApiResponse> response = restTemplate.postForEntity(url, entity, ApiResponse.class);
Destination:
@RequestMapping(value="/campaign", method = RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ApiResponse> insertCampaignRecord(
@Valid @RequestBody CampaignRecordInsertRequest campaignRecordInsertRequest){
logInfo("Incoming insert request. " + DescriptorUtility.convertToString(campaignRecordInsertRequest));
campaignDataService.insertNewRecord(CampaignRecordConverter.convertToCampaignRecord(campaignRecordInsertRequest));
return ResponseUtility.defaultResponse();
}
ResponseUtility
public static ResponseEntity<ApiResponse> defaultResponse(){
ApiResponse apiResponse = new ApiResponse();
apiResponse.setTimestamp(DateUtility.currentDateString());
apiResponse.setMessage(ResponseMessages.SUCCESS);
return new ResponseEntity<>(apiResponse, HttpStatus.OK);
}
CampaignData Service
@Async("AsyncExecutor")
public void insertNewRecord(CampaignRecord campaignRecord) {
try {
campaignRecordRepository.save(campaignRecord);
} catch (Exception e) {
logError(e);
}
}
Server Log
2017-09-11 11:11:11 INFO 18383 [http-nio-8773-exec-10] [CampaignRecordController] - Incoming insert request. {"dateCampaign":1504656000000,"cuid":...
2017-09-11 11:11:11 WARN 18383 [http-nio-8773-exec-10] [SqlExceptionHelper] - SQL Error: 1062, SQLState: 23000
2017-09-11 11:11:11 ERROR 18383 [http-nio-8773-exec-10] [SqlExceptionHelper] - Duplicate entry 'CMP_CLX##1208637#20170906' for key 'UNIQUE_KEY'
2017-09-11 11:11:11 ERROR 18383 [http-nio-8773-exec-10] [CampaignDataService] - could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
2017-09-11 11:11:11 ERROR 18383 [http-nio-8773-exec-10] [CampaignDataService] - could not execute statement
PS. Server logs is normal(return a successful response either record successfully saved or not)
Issue is intermittent. Occurs randomly when sending bulk requests.
Thanks in advance! :)
I had the same problem in Spring Boot 2.1. In my case I had 3 apps (call them A, B, and C) where B was really just a proxy between A and C:
A --> B --> C
The Premature EOF
was occurring on the response from B to A. All indications were a successful HTTP response (200), but inspecting the body of the response using a debugger revealed it had a new line character in the middle of the serialized DTO data, instead of at the end where I expected it:
(Notice the return character after the id
field, and lack of any content length; ignore the unreadable boxes at the end, they're part of the byte array that are not initialized/used)
In my case, Service B is both a server and a client. The code looked something like this:
public ResponseEntity<String> handle(String request, HttpHeaders headers) {
// Do some validation and then call Service C, and pass the response
// back to Service A
return restTemplate.postForEntity(
urlForServiceC,
new HttpEntity<>(request, headers),
String.class);
}
I didn't dive too far into the guts of RestTemplate
or its message converters, but what tipped me off that there might be an issue with the response buffering is that I was using a Spring filter to log the responses of each service. This filter has to copy the response stream to avoid exceptions from other filters related to the body already being consumed.
What I noticed is that when I ran with this filter enabled, the Premature EOF
exceptions went away. And when I disabled it, the exceptions came back. Something about copying the response stream had solved the Premature EOF
errors.
This led me to try the following in Service B:
public ResponseEntity<String> handle(String request, HttpHeaders headers) {
// Do some validation and then call Service C, and pass the response
// back to Service A
String response = restTemplate.postForEntity(
urlForServiceC,
new HttpEntity<>(request, headers),
String.class).getBody();
return ResponseEntity.ok(response);
}
The subtle change is that I'm saving the response first to a local variable, which requires me to call ResponseEntity.getBody()
. This forces the entire response body from Service C to be consumed before returning to Service A. After making this change my Premature EOF
errors have not returned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With