Home > Back-end >  Spring WebFlux. How to get the request body in two different formats using @RequestBody annotation?
Spring WebFlux. How to get the request body in two different formats using @RequestBody annotation?

Time:11-02

I'm using Spring Boot 2.5.6 and Spring WebFlux. In my business case, I need to use the HTTP request body in two different forms:

  1. Raw JSON string
  2. Already parsed Java DTO

There are my RestContoller:

@PostMapping("/play")
public Mono<PlayResponse> play(@RequestBody PlayCommand parsedBody,
                               @RequestBody String jsonBody) {
    //code here
}

When I run tests I get the next exception:

java.lang.IllegalStateException: Only one connection receive subscriber allowed.
    at reactor.netty.channel.FluxReceive.startReceiver(FluxReceive.java:182) ~[reactor-netty-core-1.0.12.jar:1.0.12]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ HTTP POST "/play" [ExceptionHandlingWebHandler]

When I use the next method signature:

@PostMapping("/play")
public Mono<PlayResponse> play(PlayCommand playCommand,
                               @RequestBody String body){
    //code here
}

PlayCommand parsedBody has all fields is set to 'null'. I can't find a way to receive the body properly.

I understand, that I can use objectMapper and convert playCommand back to JSON, but this is additional work that does not need to be done. Is it possible to receive the request body in two different forms? Or maybe, I'm doing something wrong in my examples?

CodePudding user response:

Having multiple @RequestBody is not possible. If you really need both original JSON and its serialized version the best you can do is receive the request body as a plain String and then convert it to the corresponding Java object as follows:

@Autowired
private ObjectMapper objectMapper;

@PostMapping("/play")
public Mono<PlayResponse> play(@RequestBody String body){
    PlayCommand playCommand = objectMapper.readValue(body, PlayCommand.class);
}
  • Related