37

If you use Spring, must your component classes (@Controller, @Service, @Repository) be thread safe? Or does Spring use them in a thread-safe manner so you don't have to worry about thread safety?

That is, if I have a @RequestMapping method in my @Controller, could that method be called simultaneously for the same controller object by more than one thread?

(This has sort-of been asked before, but not answered as such).

Raedwald
  • 43,666
  • 36
  • 142
  • 227
  • Regarding the edit. Spring will call the same method on the same `@Controller` class instance for a request with the same format required by `@RequestMapping`. – Sotirios Delimanolis May 28 '13 at 15:11

4 Answers4

56

Given

@Controller
public class MyController {
    @RequestMapping(value = "/index")
    public String respond() {
        return "index";
    }
}

Spring will create an instance of MyController. This is because Spring parses your configuration, <mvc:annotation-driven>, sees @Controller (which is like @Component) and instantiates the annotated class. Because it sees @RequestMapping as well, it generates a HandlerMapping for it, see the docs here.

Any HTTP requests the DispatcherServlet receives will be dispatched to this controller instance through the HandlerMapping registered before, calling respond() through java reflection on that instance.

If you have instance fields like

@Controller
public class MyController {
    private int count = 0;
    @RequestMapping(value = "/index")
    public String respond() {
        count++;
        return "index";
    }
}

count would be a hazard, because it might be modified by many threads and changes to it might be lost.

You need to understand how Servlet containers work. The container instantiates one instance of your Spring MVC DispatcherServlet. The container also manages a pool of Threads which it uses to respond to connections, ie. HTTP requests. When such a request arrives, the container picks a Thread from the pool and, within that Thread, executes the service() method on the DispatcherServlet which dispatches to the correct @Controller instance that Spring registered for you (from your configuration).

So YES, Spring MVC classes must be thread safe. You can do this by playing with different scopes for your class instance fields or just having local variables instead. Failing that, you'll need to add appropriate synchronization around critical sections in your code.

Sotirios Delimanolis
  • 263,859
  • 56
  • 671
  • 702
  • "Spring will create an instance of MyController" (assuming you mean only one instance), could you provide any official documentation regarding this statement? As I commented in other answer, it seems some confusion in this part. – kosa May 28 '13 at 15:21
  • The official [docs](http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html), but not a specific spot. Let me update the answer. – Sotirios Delimanolis May 28 '13 at 15:23
  • 1
    @Nambari [this paragraph in docs](http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s04.html#beans-factory-scopes-singleton) says is eplicitly: `The singleton scope is the default scope in Spring` – soulcheck May 28 '13 at 15:24
  • 1
    "You need to understand how Servlet containers work" This is the crucial paragraph; Servlet containers are multi-threaded, so request handling code (such as Spring MVC) must be thread safe. – Raedwald May 28 '13 at 15:34
  • @Raedwald See the last paragraph, yes. And it depends on the context, see my example. – Sotirios Delimanolis May 28 '13 at 15:35
0

By default, controllers are singletons and thus must be thread-safe. However, you can configure the controllers to be request or session scoped, i.e.:

@Controller
@Scope("session")
public class MyController {

    ...
}

Controllers with session scope can be helpful for managing session state. A good description of different patterns can be found in Using Sessions in Spring-MVC (including "scoped-proxies") and in How to get Session Object In Spring MVC. Some of the presented patterns require request scope.

The request scope is useful as well if you have data that you cannot afford to calculate more than one per request.

Codo
  • 70,546
  • 16
  • 157
  • 193
  • Hello. I came here and found this useful. But can You tell me, if there are lot of users say some hundreds or thousand. Does that mean we will have that many number of controllers? please help! @codo – Tahir Hussain Mir Dec 24 '16 at 09:03
  • 1
    I guess so. Otherwise it wouldn't work. If you need session data, you'll inevitably end up with data structures per user in memory. – Codo Dec 25 '16 at 13:06
-1

Yes, of course.

It's best if those are stateless, which makes them thread safe by default. If there's no shared, mutable state there's no problem.

duffymo
  • 299,921
  • 44
  • 364
  • 552
  • 7
    "of course": I don't think that is so obvious to a beginner. Care to expand a little? – Raedwald May 28 '13 at 15:08
  • @Raedwalk Spring only creates one instance (by default) of your `@Component` classes, so all of their instance fields will be shared for each request. – Sotirios Delimanolis May 28 '13 at 15:08
  • Few days ago, I saw opposite response from one of the experienced SO contributor. Response was, "each request will have its own instance of these components" (Different from HTTPServlet architecture). I agree "It's best if those are stateless, which makes them thread safe by default", but it would be great if there is any official documentation on "one instance of component". – kosa May 28 '13 at 15:09
  • 1
    Spring makes beans singletons by default, but there are other scopes as well: prototype, per request, per session. Other experienced developers might have made a different choice. I prefer stateless singletons because I think they scale better. – duffymo May 28 '13 at 15:21
  • 1
    "If there's no shared, mutable state" almost all interesting web-applications have shared, mutable data. In most cases, the shared data is in a data-base, so the work of ensuring thread-safety is done in Hibernate/ the JPA. – Raedwald May 28 '13 at 15:25
  • @Raedwald You'll have shared Service or Repository classes like DAOs to do database operations, but anything done in their methods will either be ThreadLocal or will use local instances within methods, so you won't have that problem. – Sotirios Delimanolis May 28 '13 at 15:31
  • 1
    Most interesting web applications don't have shared state. They keep session specific information safe in session, where only a particular user can see it. I don't think you understand what thread safety means. – duffymo May 28 '13 at 15:34
-1

Basically the answer should be yes and no. Except to very serious reason. Not because Spring synchronizes work for you- it does not do it(by default a Controller is a Singleton bean). Of coarse a thread safety must be kept along a method call, but normally mechanism of Servlets wipes out necessity to synchronize something, because a request executed inside a thread. So,during a call of any @RequestMapping annotated method the whole call stack executed in one thread. In the root it is outgoing from the service-do(Get, Post..) methods of a Servlet and then handlers map acted, which Spring builds (see http://www.studytrails.com/frameworks/spring/spring-mvc-handler-mappings/ http://technicalstack.com/dispatcher-servlethandlermapping-controller/ for example). Spring calls handling method from map of handlers, after URL has resolved. No other tricks. So think, you work inside a doPost(...) for instance method of DispatchServlet. Is a Servlet thread safe? No of coarse. Can you do it thread safe-yes, use locks, synchronized, what else and make your Servlet to be a bottleneck! Exactly the same is about controller. A doGet/Post/what else method of Servlet has basically a functional model, all data are in HttpServletRequest object. The same manner should be used in Controller object- used data classes, and stack instead of fields. You can synchronize access to them, but by paying price of bottleneck. Of coarse you can use atomics, by is it so needed? If you need to keep any state during session, you can use @Scope("session") after @Controller or (for singleton controller) a handler method with signature (..., HttpSession) both of them has pro and cons. But note, that you created additional CPU and GC expenses. Anyway, you are responsible for Controller thread safety when you want to use fields and exit from concept of stateless. Normally a cache (redis for instance) is preferable for a client state keep. At least you can restore state when a failure occurred. Stateful controllers out of session scope basically have no reason.

Simon
  • 133
  • 1
  • 4