Reputation: 3646
I am strugelling to understand why are my updates not commited when i try to use a @Scheduled
method.
This is a simplification of my scenario:
@Service
public class UserService {
@Transactional
public void updateUser(User user){
user.setName("Doe");
}
}
This service is called from two locations:
@RestController
@RequestMapping(value = "/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private UserRepository userRepository;
@ResponseStatus(HttpStatus.OK)
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public void getAvailableIssuers(@PathVariable("id") String id){
User user = userRepository.findOne(id);
userService.updateUser(user);
}
}
and a service that use a @Scheduled
method:
@Component
class InternalService {
@Autowired
private UserService userService;
@Autowired
private UserRepository userRepository;
@Scheduled(fixedRate=1000)
public void updateUser(){
User user = userRepository.findOne(1L);
userService.updateUser(user);
}
}
My problem is that when I try to update the user through the InternalService
the user never gets updated - but it is getting updated perfectly fine through the RestController. When I add the @Transactional
annotation for the scheduled method (even with readOnly = true) it works.
I read the documentation from spring regarding transactions but i still don`t understand why is it not working. I checked with the debuger and userService is in the form of a Spring Proxy.
Can someone help me with an explanation for this?
Upvotes: 2
Views: 679
Reputation: 77177
The problem is that your operation isn't constrained to that service method: In both cases, you're retrieving the object from the repository in the calling method. Your transaction has to cover the entire collection of database operations.
As to why your controller actually is working, I can't say for sure with just this information, but I'd guess that you are using OpenEntityManagerInView
and getting a transactional boundary for free.
Upvotes: 1