49

Are all controllers in Spring-MVC singletons and are shared among different sessions and requests?

If so, I assume that a class-variable like

public String name;

would be the same for all requests and sessions? So that if User X makes a request and name is being set to Paul, User Z also has Paul as attribute?

In my case I do NOT want that behaviour but wondered if there is a more easier, or more cleaner OOP-way to have session/request-variables then session.getAttribute()/request.getAttribute()

2 Answers 2

74

To answer your first question: yes, Spring MVC controllers are singletons by default. An object field will be shared and visible for all requests and all sessions forever.

However without any synchronization you might run into all sorts of concurrency issues (race conditions, visibility). Thus your field should have volatile (and private, by the way) modifier to avoid visibility issues.

Back to your main question: in Spring you can use request- (see 4.5.4.2 Request scope) and session-scoped (see: 4.5.4.3 Session scope) beans. You can inject them to controllers and any other beans (even singletons!), but Spring makes sure each request/session has an independent instance.

Only thing to remember when injecting request- and session-scoped beans into singletons is to wrap them in scoped proxy (example taken from 4.5.4.5 Scoped beans as dependencies):

<!-- an HTTP Session-scoped bean exposed as a proxy -->
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">

    <!-- instructs the container to proxy the surrounding bean -->
    <aop:scoped-proxy/>
</bean>
Sign up to request clarification or add additional context in comments.

4 Comments

+1 Note: "even singletons!" requires auto-proxying the injected beans
@SeanPatrickFloyd: yes, this is so important that I added an example from Spring docs, thanks!
From stackoverflow.com/questions/4503606/…, use @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) to configure aop:scoped-proxy using annotations.
We are missing one of the basis of spring: controllers are beans, hence they should not have status (beyond the injected dependencies) unless those beans are meant to store data. To avoid data sharing among requests I have seen @scope Session or request in beans supporting forms in jsf (properly configured to use spring beans). Controllers are not beans meant to carry data but classes that support view logic, hence they should be stateless and consequently singleton
13

Yes, controllers in Spring-MVC are singletons. Between multiple requests your class variable get shared and might result into ambiguity. You can use @Scope("request") annotation above your controller to avoid such ambiguity.

5 Comments

Some example with explanation would be great.
@Controller public class TestClass { private String name; @RequestMapping("/") public String displayName(){ if(this.name != null){ this.name = "ABC"; }else{ this.name = "XYZ"; } SystemOut.println(name); return this.name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
In Continuation to my previous edit.. For first request it will print XYZ but for another parallel request it will print ABC but ideally if two users are issuing two different request they both should see XYZ. By making @Scope("request") will give us the desired result. Please let me know if I went wrong somewhere
Yes that works perfectly. What does that @Scope("request") annotation does actually ? Does that create a new controller object for every request? What if two request reach the same requestMapping at exactly same time?
@New Bee, yes it will create new instance for each http request and if the 2 requests comes at a time then for both it will create separate instance and handle the request.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.