Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DATACMNS-1758] Fix ConcurrencyModificationException in DefaultEntityCallbacks #453

Conversation

mhyeon-lee
Copy link
Contributor

resolves: DATACMNS-1758

@mhyeon-lee mhyeon-lee force-pushed the datacmns-1758-fix-concurrentmodificationexception branch from a874f4c to bc037bc Compare June 29, 2020 15:15
@@ -394,7 +394,7 @@ private BeanFactory getRequiredBeanFactory() {
}
}

return cachedEntityCallbacks;
return new ArrayList<>(cachedEntityCallbacks);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed it again.

I think it's safer to handle it where it returns the result.

}

return new ArrayList<>(cachedEntityCallbacks);
Copy link
Contributor Author

@mhyeon-lee mhyeon-lee Jun 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new ArrayList also has a problem.
If cachedEntityCallbacks.clear() is executed on another thread before this line is executed, an emptyList is returned.

I think it is easier to change the new cache list. (Give up the final)

Thread 1    |   Thread2
----------------------
clear()     |
            | new ArrayList(cachedEntityCallbacks);
addAll()    |

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, it's probably better to roll back the entire optimization to a state where it has been before. That way, we omit all concurrency issues in the first place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mp911de
This is not an optimization, but a fix to solve the concurrency issue.
getEntityCallbacks method returns cachedEntityCallbacks and DefaultEntityCallbacks use it with iterator

f9839c8#diff-f9f021397523461fe28f39d98bb39f39L83

However, cachedEntityCallbacks can be modified here. (clear, addAll)
This throws ConcurrentModificationException.

Exception:java.util.ConcurrentModificationException: null
  at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
  at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)
  at org.springframework.data.mapping.callback.DefaultEntityCallbacks.callback(DefaultEntityCallbacks.java:83)
  at org.springframework.data.jdbc.core.JdbcAggregateTemplate.triggerBeforeSave(JdbcAggregateTemplate.java:414)
  at org.springframework.data.jdbc.core.JdbcAggregateTemplate.store(JdbcAggregateTemplate.java:335)
  at org.springframework.data.jdbc.core.JdbcAggregateTemplate.update(JdbcAggregateTemplate.java:183)

Addresses concurrency issues by replacing the entire cachedEntityCallbacks without changing them when there are changes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm referring to 4616474.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mp911de
I understood your words. Thank you.

Should I close this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it makes sense that we fix our own issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants