0

( NOT Premature end of Content-Length delimited message body (expected:)
I have a set up of 3 apps talking to each other and each of them is sitting behind an apache http server in the following format
App A (Monolithic Spring app)
App B (Spring boot microservice - acting as intermediate)
App C (Spring boot microservice - serving some data)

App A makes a GET request to App B, App B reads the request and Invokes a GET request to App C, App C gets the data and sends a ResponseEntity to App B, and finally App B sends that ResponseEntity to App A as show in the code below.

//Service A making a request to Service B.
public static Response executeGetMethod(CustomRestTemplate restTemplate, String microServiceURL) {
    Response returnedResponse = null;
    ResponseEntity<?> msResponse = null;
    try {
        // special handling for octet-stream
        if (restTemplate.getAccepts().stream().anyMatch(accept -> MediaType.APPLICATION_OCTET_STREAM_TYPE.equals(accept))) {
            msResponse = restTemplate.getRestTemplate().getForEntity(microServiceURL, byte[].class);
        } else {
            msResponse = restTemplate.getRestTemplate().getForEntity(microServiceURL, Object.class);
        }

        returnedResponse = Response.status(msResponse.getStatusCode().value()).entity(msResponse.getBody()).build();
        //Just reading the headers from msResponse and adding it to returnedResponse.
        addHeaderToReturnedResponse(returnedResponse.getHeaders(), msResponse.getHeaders());

    } catch (HttpClientErrorException ex) {
        returnedResponse = Response.serverError().status(ex.getStatusCode().value()).entity(ex.getResponseBodyAsString()).build();
    } catch (HttpServerErrorException ex) {
        returnedResponse = Response.serverError().status(ex.getStatusCode().value()).entity(ex.getResponseBodyAsString()).build();
    }
    return returnedResponse;
}
    

// Service B making request to Service C
@GetMapping(value = "/templates", produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<?> getReportTemplate() throws Exception {
    validateUser();

    // route to reporting-microservices
    Map<String, String> headers = new HashMap<>();
    headers.put(RestServiceConstants.CONTENT_TYPE, RestServiceConstants.APPLICATION_JSON);
    ResponseEntity<?> response = restService.invokeGetApi(headers,
            REPORT_MS_URL.concat(REPORT_TEMPLATE_URL));

    return response;
}


// Service C get the data and returning it to Service B
@GetMapping(value = "/templates", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<List<ReportTemplate>> getReportTemplate() throws Exception {
    List<ReportTemplate> reportTemplates = reportService.getAllReportTemplates();

    return ResponseEntity.ok(reportTemplates);
}
// Advice in Service C to add Content-Length and Connection headers before sending response
@Slf4j
@ControllerAdvice
public class ResponseFilter implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

        if(mediaType.equals(MediaType.APPLICATION_JSON)){
            ObjectMapper mapper = new ObjectMapper();
            try {
                String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
                log.info("===========================================================================");
                log.info(String.valueOf(json.length()));

                serverHttpResponse.getHeaders().add("Content-Length", String.valueOf(json.length()));
                serverHttpResponse.getHeaders().add("Connection", "keep-alive");
                log.info(serverHttpResponse.getHeaders().toSingleValueMap().toString());

                log.info("===========================================================================");
            } catch (JsonProcessingException e) {
                log.error(e.getOriginalMessage());
            }
        }

        return o;
    }
}
    

Now the problem is, I get the following error when I try to run it Error while extracting response for type [class java.lang.Object] and content type [application/json;charset=UTF-8]; nested exception is org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body (expected: 1,493; received: 1,111)"
When I have the three apps talking together directly without using httpd as proxy it works fine, but as soon as I enable it, I get that error.
Any help is very appreciated.

Bisho Adam
  • 191
  • 1
  • 2
  • 12

0 Answers0