Transaction management issues
Description
Environment
Activity
Naveed Hussain
Issue has been resolved
muhammad siddique
adding this email conversation just for documentation
--------------------------------------------------We were having serious transactional issue in OR , specially when updating existing records (person, role, email etc).
The Problem
It is saving invalid data at sor level but not saving on calculated level on invalid data entry.
The reason was that our core service was committing the transaction even though there are validation errors.
The Impact
Editing (updating) any field (email, name, role, zip etc) using any interface (rest, batch,ui) was giving errors but still saving data on the database.
The Solution
We discussed several solutions.
1-The ideal solution would be to throw exception in core service on validation errors. But it is not viable since all code around service layer need to catch it.
2-The other solution is to programmatically roll back the transaction on validation errors. Yesterday we identified 6 places in core service where 'programmatic roll back' call needs to be made.
We were even getting exception on that as well when invoking core service from other services e.g. email service or guest service.
I spent almost half of my day debugging this issue and found that spring is trying to commit the transaction from caller services even though same transaction was requested to be rollback in core service.
So the solution is to call rollback statement in core and caller services. We need to make changes
A)-6 places in core services
B) Any other service that is calling that core service. I think it is only one 'Guest Service'. If we mark email service as non transactional we don't need to roll back again there.
Naveed Hussain
We have a problem with transaction management in our service layer.
What is happening is that, at all our service layer methods, we are declaring transactions as
@Transactional(propagation=Propagation.REQUIRED, rollbackFor = Exception.class)
Which means the transaction will rollback ONLY IF there is an exception.
However, in our code, we 1- update the SorPerson's roles with email and then 2- call personService.updateSorPerson(sorPerson). The very first thing updateSorPerson(...) method does is that it checks email format, if there is a problem then INSTEAD OF RAISING AN EXCEPTION our code RETURNS THE RESPONSE. In that case, Spring always assumes that the transaction was successful and commits the email addresses already assigned to SorPerson's role.
The solution is to rollback the transaction when there is a validation error.
1- It can be done by raising an exception (and handling that in upper layers of code)
2- Rollback the transaction programatically
Followings are the snippets of the code
------------------------------------------------
Appendix 1: saveOrCreateEmailForSorPersonForAllRoles
@Override
public ServiceExecutionResult<SorPerson> saveOrCreateEmailForSorPersonForAllRoles(SorPerson sorPerson, String emailAddress,
Type emailType){
//get all the roles for an SorPerson
List<SorRole> openRoles = sorPerson.getRoles();
if (openRoles.isEmpty()) { return new GeneralServiceExecutionResult<SorPerson>((SorPerson) null); }
for (SorRole r : openRoles) { r.addOrUpdateEmail(emailAddress, emailType); }
return this.personService.updateSorPerson(sorPerson);
}
------------------------------------------------
Appendix 2: updateSorPerson
public ServiceExecutionResult<SorPerson> updateSorPerson(final SorPerson sorPerson) {
final Set validationErrors = this.validator.validate(sorPerson);
if (!validationErrors.isEmpty()) {
Iterator iter = validationErrors.iterator();
while (iter.hasNext()) { logger.info("validation errors: " + iter.next()); }
return new GeneralServiceExecutionResult<SorPerson>(validationErrors);
}
When testing the REST API , it was noticed that the malformed email address ,for example abc(abr)def@test.com, was not rejected at least at the SOR level.
The update occured at the SoR level , but not at the calculated level.
The correct behavior should be that the this email should be rejected at Sor and calculated levels both.
This problem is there not only for emails but also for zip code, name and roles.