Consider this Entity:
@Entity
class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id
String username
String name
Boolean blocked
@Version
Integer version
}
... and this Controller:
@Controller
@Scope("session")
class ExampleController {
@Autowired
UserRepository userRepository
User currentUser
@GetMapping("/user/{id}", Model model)
def getUser(@PathVariable Integer id) {
currentUser = userRepository.findOne(id)
model.addAttribute("user", currentUser)
"user-view"
}
@GetMapping("/user/block", Model model)
def alterUser() {
currentUser.blocked = true
userRepository.save(currentUser)
model.addAttribute("user", currentUser)
"user-view"
}
}
Since the scope of the Controller is "session" the Class variable "currentUser" will contain a instance of User that was found by "/user/{id}". If I have a button on the view that simply calls the URL "/user/block" it will change the "currentUser" instance.
The problem here is that if I have 2 browser tabs opened on different Users, they will share Scope and will overlap information.
The solution I came across on the Web is to change the Scope to "request". So the controller would have to look like this:
@Controller
@Scope("request")
class ExampleController {
@Autowired
UserRepository userRepository
@GetMapping("/user/{id}", Model model)
def getUser(@PathVariable Integer id) {
def currentUser = userRepository.findOne(id)
model.addAttribute("user", currentUser)
"user-view"
}
@GetMapping("/user/{id}/block", Model model)
def alterUser(@PathVariable Integer id) {
def currentUser = userRepository.findOne(id)
currentUser.blocked = true
userRepository.save(currentUser)
model.addAttribute("user", currentUser)
"user-view"
}
}
As we can see, the currentUser needs to be re-selected from the database for each request. This is fine but, since it's being re-selected I can't control it's version anymore. If the User has been changed by another Session between these 2 requests it will be re-selected from the database with a new version and I will not get an ObjectOptimisticLockingFailureException...
How do you guys would deal with this? Any ideas on how can I change an object between requests and still respect versioning?