Issue
I have the following Controller code using SpringMVC:
@Controller
@Scope("prototype")
@RequestMapping("/messages")
public class MessageController {
@RequestMapping(value="/index", method=RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public String displayAllMessages(ModelMap model) {
System.out.println(this.hashCode());
// processing
return "messages";
}
}
When use @Scope("prototype")
, each request comes, the output of this.hashCode()
are different, meaning that when each request comes, a new MessageController
instance will be created.
If not use @Scope("prototype")
, default will be @Scope("singleton")
, each request comes, the output of this.hashCode()
are same, meaning only one MessageController
instance is created.
I'm not sure when should use @Scope("prototype")
, when not?
Solution
Let's say you do something like this in your controller:
private List<String> allMessages;
public String displayAllMessages(ModelMap model) {
allMessages = new ArrayList<>();
fillMessages();
model.put(messages, allMessages);
return "messages";
}
private void fillMessages() {
allMessages.add("hello world");
}
Your controller would become stateful: it has a state (allMessages
) that can't be shared between two requests. The controller is not thread-safe anymore. If it was called concurrently to handle two concurrent requests, there might be a race condition.
You could avoid this problem by making the controller a prototype: each request would be handled by a separate controller.
Or you could do the right thing and make the code stateless, in which case creating a new controller for each request would be useless, since the controller would be stateless and thus thread-safe. The scope could then keep its default value: singleton.
public String displayAllMessages(ModelMap model) {
List<String> messages = fillMessages();
model.put(messages, allMessages);
return "messages";
}
private List<String> fillMessages() {
List<String> allMessages = new ArrayList<>();
allMessages.add("hello world");
return allMessages;
}
Answered By - JB Nizet