2

I am new to spring. On reading the documentation I found it's mentioned that

Bean default scope is a singleton.

If it has only a single instance in the container then "How it behaves in the multi-threaded environment ".

Typically in any web application, multiple requests will be done at the same time and if a POJO class is autowired and multiple requests are done at the same time then getter and setter will be crossing data of each other. Request 1 sets the data and same time request 2 override. Request 1 gets overridden data of request 2.

Like Foo is a POJO class whose get and set is not synchronized.

 @Service
    public class Foo {
        String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

   

     @Autowired
        private Foo foo;
    
        @RequestMapping(value = "foo" , method = RequestMethod.POST )
        public String saveFoo(@RequestBody String fooname){
            foo.setName(fooname);  // In case of multiple request 
                                  //get and set will be happing on same instance could be wrong
            return foo.getName();
        }

What is the ideal way to handle Autowire and POJO in a multi-threaded environment? Does the developer had to mention the prototype scope ?

Sumeet Kumar Yadav
  • 11,912
  • 6
  • 43
  • 80
  • Spring beans are not thread-safe.......It's your responsibility to provide thread-safety. – Amimul Ehsan Rahi Mar 02 '21 at 18:32
  • The fact that yu use spring doesn't mean **everything** has to be managed by Spring. For this create a `Foo` when you need it and it is perfectly thread safe. Your current code isn't as it is keeping state in a singleton. – M. Deinum Mar 02 '21 at 18:34

4 Answers4

3

In general, service objects should be stateless. Your problem is that you are storing data directly in your Foo, which is not where it belongs. Calls to services should include all of the necessary parameters in the method signature; persistent objects should be saved somewhere (like a database) and referred to by key (perhaps kept in an HTTP session or sent as a request parameter).

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • How we can autowire pojo classes? Imagine scenario like based on request body data pojo need to be formed. Are you saying we should never have autowired pojo class before saving to entity ? Can you please add some example code – Sumeet Kumar Yadav Mar 02 '21 at 19:08
  • 1
    @Sumeet _Do not_ autowire POJOs. Autowiring is for _services_, and you should maintain a clean distinction between _services_ and _data objects_. – chrylis -cautiouslyoptimistic- Mar 02 '21 at 19:17
1

Spring beans are not thread-safe.......It's your responsibility to provide thread-safety.

Refer to this for best practices:

Spring bean thread safety

1
  • 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.
Mohit Sharma
  • 340
  • 2
  • 11
0

If your @Service must store state, I would recommend looking into the Command Pattern.

The command could be created from a Factory, which hopefully would be thread safe and provided to the classes that need it via 'prototype' scope.

If you wanted to get really fancy you could look into CQRS (Command Query Responsibility Segregation). CQRS won't help you with your threading, but it does change the execution timing of commands.

hooknc
  • 4,854
  • 5
  • 31
  • 60