I found that when using Spring Boot 3.4.1, this version places the properties from the header into the request when handling web requests.

There is a property bu in the header of request.

code:

@GetMapping("/periodic-data")
fun periodicData(condition: MarketingBoardDataDtoV2) = marketingBoardV2Service.periodicData(condition)

data class MarketingBoardDataDtoV2(
    val category: String?,
    val subBrand: String?,
    val bu: String?,
    val startDate: LocalDate,
    val endDate: LocalDate,
)

request:

GET {{host}}/v2/marketing-board/periodic-data?startDate=2024-08-14&endDate=2024-12-14

in 3.4.1: Spring properties bound from request header to data class

in <=3.4.0 Spring properties bound from request header to data class

Comment From: bclozel

Have you tried filtering this property in the binder as explained here?

Comment From: 664623107

Have you tried filtering this property in the binder as explained here?

@bclozel I added the property bu to the header of each request in the Filter.

override fun doFilter(request: ServletRequest?, response: ServletResponse?, chain: FilterChain) {
    val httpServletRequest = request as HttpServletRequest
    // something ...
    request.setHeader(Constant.BU, "$bu")
    // something ...
}

But in the old version, there were no issues; I have always used it this way.

Comment From: bclozel

@664623107 that is not what I was suggesting. Please try the code snippet suggested here, configuring the binder to ignore the "bu" header.

Here's a class you can copy to your project that will ignore all header values. Let us know how this works for you.

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder;

@ControllerAdvice
public class MyControllerAdvice {

    @InitBinder
    public void initBinder(ExtendedServletRequestDataBinder binder) {
        binder.addHeaderPredicate(header -> false);
    }
}

Comment From: 664623107

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder;

@ControllerAdvice
public class MyControllerAdvice {

    @InitBinder
    public void initBinder(ExtendedServletRequestDataBinder binder) {
        binder.addHeaderPredicate(header -> false);
    }
}

@bclozel Thanks,It worked. But why were there no issues in versions <= 3.4.0? Is this a bug?

Comment From: bclozel

Thanks for letting us know. I think this is due to #34073, so not a bug. Your DTO class takes this argument in its constructor, which is a pretty strong signal for the binder to do the binding. I'll leave this opened for now to let Rossen comment on this, but I suspect that binding constructor arguments is the expected behavior here.

Comment From: bclozel

We have discussed this as a team, and we're going to refine this support in #34182. As for this particular case, we think that this behavior change uncovered a problem in the design of your application. Rather than using request headers as a context map, you should be adding this information as a request attribute.

We're closing this issue in favor of #34182. You can keep using the code snippet I shared but please consider refactoring this part of your application. Thanks!