How should I create a controller which is thread safe?
As per the best practice controllers are singleton.
Consider the below code in which im storing user data through a autowired service Object ,which makes my code stateful. How would i make the below code thread safe.
@RestController
class ApiController {
@Autowired
IDbService< User > iDBService;
@RequestMapping(value = "/api/adduser", method = RequestMethod.POST)
public ResponseEntity<User> createUser(@RequestBody User user){
User savedUser=iDBService.create(user);
return new ResponseEntity<User>(savedUser, HttpStatus.CREATED);
}
Here is my Service implementation. I have shared variable in my service
public class IDbServiceImpl<T> implements IDBService<T>{
@Autowired
GenericRepository<T, Serializable> genericRepository;
@Override
public T create(T object) {
return genericRepository.save(object);
}
}
Your controller is a singleton by default and your service is singleton by default too.
Therefore in order to make them thread safe you have to make sure that the operations that take place inside the service must be thread safe, in case of changing the state of an object inside the service ie. a list.
In case of using a rdbms then you have a transaction related problem.
If you use spring and Jpa, the transaction manager will take care for your updates provided that you use @Transactional. In case of plain jdbc method then you can either use pure jdbc and do the transaction handling on your own or use spring-jdbc that comes with a transaction manager.
If you want the database rows not to be changed in case of a write in progress then you have to take into consideration row-locking related mechanisms. – gkatzioura Feb 7 at 15:23
In case of JPA using @Transactional will do the work. However depending on your application you might have to consider locking. Check this article on locking with jpa.
Controllers are
singletons
, therefore they should be implemented in a thread safe manner.Design your application in a way that controllers are stateless. Add transactional support in your
@Repository
layer.Example:
You could use Spring declarative transaction management mechanism. The
@Transactional
annotation itself defines the scope of a single database transaction.Your controller looks thread safe. As there is no instance variable storing the state. User object will be different for each request and will be resolved by the MVC framework.