Issue
I'm trying to learn more about Spring bean scopes for use in a project. I've created a few test classes, and I am not getting the behavior I'd expect.
I created the following component, and I would like this bean to last for only the duration of the HTTP request.
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserDataContainer {
public int requestCount = 0;
}
The following controller uses that component.
@Controller
@RequestMapping("/hello")
public class HelloController {
@Autowired
private UserDataContainer userData;
@GetMapping
public String get(Model model) {
model.addAttribute("prev", userData.requestCount);
userData.requestCount++;
model.addAttribute("curr", userData.requestCount);
return "test";
}
}
My trouble is, it doesn't seem that a new instance of UserDataContainer is created for each request. Whenever I load this page, I see that the values of "prev" and "curr" keep incrementing, instead of resetting to 0 at the start of each request. Am I misunderstanding how this is supposed to work, or is something not implemented correctly.
Solution
The issue here is that the request scoped bean is not invoked directly by your controller.
Instead the controller uses a proxy to invoke the request scoped bean (in this case, the proxy is a cglib one based on your proxy mode annotation, ie: ScopedProxyMode.TARGET_CLASS
The proxy only wraps around methods of the request scoped bean and not it's variables.
So in short, encapsulate the instance variable of your request scoped bean into a method and call that method from the Controller.
something like this:
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserDataContainer {
private int requestCount = 0;
public int incrementRequestCount(){
requestCount++;
return requestCount;
}
public int getRequestCount(){
return requestCount;
}
}
then in your Controller, just invoke the public methods
@GetMapping
public String get(Model model) {
model.addAttribute("prev", userData.getRequestCount());
model.addAttribute("curr", userData.incrementRequestCount());
return "test";
}
Answered By - allkenang