Must Spring Component Classes Be Thread-Safe

Must Spring component classes be thread-safe

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.

Are Spring objects thread safe?

These are two unrelated questions:

Are Spring Beans Thread Safe?

No.

Spring has different bean scopes (e.g. Prototype, Singleton, etc.) but all these scopes enforce is when the bean is created. For example a "prototype" scoped bean will be created each time this bean is "injected", whereas a "singleton" scoped bean will be created once and shared within the application context. There are other scopes but they just define a time span (e.g. a "scope") of when a new instance will be created.

The above has little, if anything to do with being thread safe, since if several threads have access to a bean (no matter the scope), it would only depend on the design of that bean to be or not to be "thread safe".

The reason I said "little, if anything" is because it might depend on the problem you are trying to solve. For example if you are concerned whether 2 or more HTTP requests may create a problem for the same bean, there is a "request" scope that will create a new instance of a bean for each HTTP request, hence you can "think" of a particular bean as being "safe" in the context of multiple HTTP requests. But it is still not truly thread safe by Spring since if several threads use this bean within the same HTTP request, it goes back to a bean design (your design of a bean backing class).

How to Make/Design a Thread Safe "Object"?

There are several ways, probably too long to list here but here are a few examples:

  • Design your beans immutable: for example have no setters and only use constructor arguments to create a bean. There are other ways, such as Builder pattern, etc..

  • Design your beans stateless: for example a bean that does something can be just a function (or several). This bean in most cases can and should be stateless, which means it does not have any state, it only does things with function arguments you provide each time (on each invocation)

  • Design your beans persistent: which is a special case of "immutable", but has some very nice properties. Usually is used in functional programming, where Spring (at least yet) not as useful as in imperative world, but I have used them with Scala/Spring projects.

  • Design your beans with locks [last resort]: I would recommend against this unless you are working on a lower level library. The reason is we (humans) are not good thinking in terms of locks. Just the way we are raised and nurtured. Everything happens in parallel without us needing to "put that rain on pause, let me get an umbrella". Computers however are all about locks when you are talking "multiple things at the same time", hence there are some of us (exceptional people) who are doing their fair share and implementing libraries based on these locks. Most of other humans can just use these libraries and worry not about concurrency.

Thread safety in Spring Boot with Instance variables

In resume: yes, apparently, this code is thread-safe. Since you're using Servlets, each request will be served in a different thread provided by the servlet container (if you're using the default configurations for Spring Boot, the servlet container is a Embedded Tomcat).

Why apparently? Because this code is only thread-safe if the instances of objects declared in the class scope are also thread-safe (i.e GreetingService must be thread-safe)

Take your own example:

The Thread#sleep executed in a first request has no effect on the subsequent ones (i.e other request will not be blocked) because the subsequent ones are served on different threads, as said above.

You will be fine as long as you don't assign new values to the global variables during a request life cycle.

Spring and Thread safety

Your REST service should be written so it's thread safe. That means no private data members that are mutable. If that's the case, you're safe.

If all your methods use method scope variables, then you're thread safe.

You should know that the app server will spawn a thread for each HTTP request that comes in. If you write the service as if it were single threaded you'll be fine.

You should always worry about multi-thread scenarios.

If your REST service has to interact with a database, then the connection should not be shared. You need a pooled data source that checks out a connection for each request, uses it in method scope, and returns it to the pool. JDBC connections are not thread safe, but you get away with it because you pool them.

Spring: Is using EntitiyManager in a @Component+@Transactional class thread safe?

Yes, it is thread-safe. Spring injects a proxy that delegates to the EM associated to the current transaction/thread. See the documentation, which says:

The injected JPA EntityManager behaves like an EntityManager fetched from an application server’s JNDI environment, as defined by the JPA specification. It delegates all calls to the current transactional EntityManager, if any. Otherwise, it falls back to a newly created EntityManager per operation, in effect making its usage thread-safe.

(emphasis mine).

Are autowired objects in spring-mvc threadsafe?

Q.1 : Are Spring Beans Thread Safe?
Answer: No.
Spring don't give you thread safety for their bean. Spring provide different type of bean scope like (Prototype,Singleton etc). If Prototype then a new bean create each time it invoke where a singleton bean created for one time and shared in application context.

If you are thinking for HTTP request, then 2 or more request can come.Hence new instance of a bean is created in each request scope. So you can think they are thread safe in context of HTTP request but it's not truly thread safe by spring itself.Because several thread can share the bean within the same HTTP request context.

Q.2 : Are Class variable Thread Safe?
Answer: No
Quoted from here

All private member variables are shared. They might be final, but that only means that the references can't be changed. Any mutable state must be synchronized.

Spring Singleton behavior in a multi-threaded environment

  • If a class hold any state. Then it is a candidate for @Autowired
    Prototype Bean. At each request a new bean should be created. Hence
    it will provide you the desired functionality. e.g. POJO, Entity, DTO's

  • If a class is for Utility/Behavior and doesn't hold any state than
    mark it as @Autowired default Singleton bean. e.g. Services, Gateways, Controllers.

  • If a class contains state, but you don't need any Spring
    functionality in that class. Use new keyword to create that object/
    or Some Factory.. @Autowired is for Spring managed beans. e.g. Entity, POJO's

  • If a class contains both state and behavior methods. Use SLP ( Single
    Responsibility Principle and move it to separate classes )

Furthermore:

  1. Spring use servlet threads internally , All Spring managed beans are thread safe ( i.e Classes created by Spring framework)
  2. Its your responsibility to carefully use Spring beans.
  3. Injection of beans is tricky, i.e A Singleton Bean Injected in Prototype Bean.


Related Topics



Leave a reply



Submit