Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Autowiring and thread-safety

I am new to Spring and recently created a test RESTful web service application. I am following the Spring @Autowiring way of injecting the beans. Below is my code and a question:

@Service
public class HelloWorld {       

    @Autowired
    private HelloWorldDaoImpl helloWorldDao;

    public void serviceRequest() {
        helloWorldDao.testDbConnection();
    }

}

@RestController
public class HelloWorldController {

    @Autowired
    private HelloWorld helloWorld;

    @RequestMapping(value = "/test", method = RequestMethod.POST)
    public String test() {
        helloWorld.serviceRequest();
        return "Success";
    }
}

Now my question is, when I have two requests coming in exactly at same time and they both are sharing the same Service class variable "helloWorld", then how do we ensure that value returned for Request 1 does not go to Request 2 and vice-versa?

Does Spring take care of such multi-threading issues automatically when we use @Autowired?

like image 505
Nick M Avatar asked Jul 17 '16 22:07

Nick M


1 Answers

Spring doesn't intrinsically look after the thread safety of your application, especially since this happens on a completely different layer. Autowiring (and Spring proxying) has nothing to do with it, it's just a mechanism for assembling dependent components into a working whole.

Your example is not a very representative one either, as both beans you presented are effectively immutable. There's no shared state that could be potentially reused by concurrent requests. To illustrate that really Spring doesn't care about thread safety for you, you could try the following code:

@Service
public class FooService {       
    // note: foo is a shared instance variable
    private int foo;

    public int getFoo() {
        return foo;
    }

    public void setFoo(int foo) {
        this.foo = foo;
    }
}

@RestController
public class FooController {

    @Autowired
    private FooService fooService;

    @RequestMapping(value = "/test")
    public String test() {
        int randomNumber = makeSomeRandomNumber();
        fooService.setFoo(randomNumber);
        int retrievedNumber = fooService.getFoo();
        if (randomNumber != retrievedNumber) {
            return "Error! Foo that was retrieved was not the same as the one that was set";
        }

        return "OK";
    }
}

If you stress-test this endpoint you're guaranteed to get the error message sooner or later - Spring will do nothing to prevent you from shooting yourself in the foot.

like image 83
kryger Avatar answered Oct 20 '22 12:10

kryger