Search code examples
spring-bootswaggeropenapispringdocspringdoc-openapi-ui

Spring Rest Controller API with HttpEntity getting null body when testing with Open API


I'm using Spring Boot 2.6.7 and Using Open API springdoc-openapi-ui 1.6.4. I have 2 services. From first service I'm using rest template to connect to second service. In the first service, in rest controller api, I have used HttpEntity to get request object. The same is passed to rest template. The reason is with HttpEntity, I'm passing the request body as well as some other headers as well.

My controller method is as follows.

@PostMapping(value = "/submit", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "API for submit", description = "Submit data")
@ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK"),
        @ApiResponse(responseCode = "400", description = "Bad request", content = @Content(schema = @Schema(implementation = Failure.class))),
        @ApiResponse(responseCode = "500", description = "Error", content = @Content(schema = @Schema(implementation = Failure.class))), })
public ResponseEntity<Success<SubmitOpr>> submit(HttpEntity<OperationReq> httpEntity) throws Exception {
    log.info("Request Entity is {}", httpEntity);
    log.info("Request Body is {}", httpEntity.getBody());
    SuccessResponse<SubmitOpr> response = null;
    try {
        response = oprService.submit(httpEntity);
    } catch (Exception e) {
        log.error("Failure: {}", e.getMessage());
        throw e;
    }
    return ResponseEntity.ok().body(response);
}

My application works fine with this. And with postman client also it works fine. But when I use swagger UI to test, I did not get expected result. And when I debug, httpEntity.getBody() is null

If I change from HttpEntity<OperationReq> httpEntity to OperationReq httpEntity and then accordingly change subsequent service layer methods, the api works fine in swagger. But I don't want to change that. Because I want to pass HttpEntity and another thing is there are so many similar APIs and it would be very difficult to change everywhere.

Is there a better solution to this?


Solution

  • I think there is no direct solution to this. If you are looking to get headers along with request body, what you can do is, you can get RequestBody and get Headers in controller and create an HttpEntity object. And that you can pass on to your service layer methods. Change will be only in controller side and no change will be required from service layers.

    @PostMapping(value = "/submit", produces = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "API for submit", description = "Submit data")
    @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK"),
            @ApiResponse(responseCode = "400", description = "Bad request", content = @Content(schema = @Schema(implementation = Failure.class))),
            @ApiResponse(responseCode = "500", description = "Error", content = @Content(schema = @Schema(implementation = Failure.class))), })
    public ResponseEntity<Success<SubmitOpr>> submit(@RequestBody OperationReq operationReq, @RequestHeader MultiValueMap<String, String> headers) throws Exception {
        HttpEntity<OperationReq> httpEntity = new HttpEntity<>(operationReq, headers);
        log.info("Request Entity is {}", httpEntity);
        log.info("Request Body is {}", httpEntity.getBody());
        SuccessResponse<SubmitOpr> response = null;
        try {
            response = oprService.submit(httpEntity);
        } catch (Exception e) {
            log.error("Failure: {}", e.getMessage());
            throw e;
        }
        return ResponseEntity.ok().body(response);
    }