Skip to content

Improve documentation on reading form data via Servlet request parameters vs @RequestBody #33409

@membersound

Description

@membersound

I upgraded from spring-boot v2 -> v3. My tests could not detect the following issue, even though I tested the scenario.
The following problem does only occur in live, but not in tests:

In the following example, the @RequestBody parameters are missing in case when using additional query parameters.

@RestController
public class ExampleServlet {
    @PostMapping(value = "/example", consumes = APPLICATION_FORM_URLENCODED_VALUE)
    public Mono<String> namedsqlPostForm(
            @RequestParam(name = "metadata", required = false) String metadata,
            @RequestBody(required = false) MultiValueMap<String, String> params) {
        if (params == null || params.isEmpty())
            throw new RuntimeException("params missing");

        return Mono.just("OK");
    }
}

The following works (body params are filled in controller):

curl --location --request POST 'localhost:8080/example' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'test=junit'

The following fails (body params are missing in controller):

curl --location --request POST 'localhost:8080/example?format=json' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'test=junit'

Result LIVE:

{
    "timestamp": "2024-08-20T09:37:04.078+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "path": "/example"
}

I attached a sample, which fails in live mode, but succeeds in junit test mode.
Switching the example back to spring-boot 2.x, also the live mode works.

Test:

@SpringBootTest
@AutoConfigureMockMvc
public class ExampleServletTest {
    @Autowired
    private WebTestClient webTestClient;

    //this is NOT true in real world! this only succeeds in junit test!
    @Test
    public void testBodyParamsWithQueryParam() throws JsonProcessingException {
        webTestClient.post()
                .uri("/example?metaadat=v1")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                .bodyValue(new ObjectMapper().writeValueAsString(Map.of("Test", "junit")))
                .exchange()
                .expectStatus().isEqualTo(200)
                .expectBody(String.class).isEqualTo("OK");
    }
}

spring-web-example.zip

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: documentationA documentation task

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions