Prevent ConcurrentModificationException during cascading delete
This commit is contained in:
parent
f2b3a39abb
commit
67b53e5326
|
@ -24,12 +24,17 @@ import ca.uhn.fhir.jpa.util.DeleteConflict;
|
|||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class DeleteConflictList implements Iterable<DeleteConflict> {
|
||||
private final List<DeleteConflict> myList = new ArrayList<>();
|
||||
private final Set<String> myResourceIdsMarkedForDeletion;
|
||||
private int myRemoveModCount;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -69,11 +74,38 @@ public class DeleteConflictList implements Iterable<DeleteConflict> {
|
|||
|
||||
@Override
|
||||
public Iterator<DeleteConflict> iterator() {
|
||||
return myList.iterator();
|
||||
// Note that handlers may add items to this list, so we're using a special iterator
|
||||
// that is ok with this. Only removals from the list should trigger a concurrent modification
|
||||
// issue
|
||||
return new Iterator<DeleteConflict>() {
|
||||
|
||||
private final int myOriginalRemoveModCont = myRemoveModCount;
|
||||
private int myNextIndex = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
checkForCoModification();
|
||||
return myNextIndex < myList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteConflict next() {
|
||||
checkForCoModification();
|
||||
return myList.get(myNextIndex++);
|
||||
}
|
||||
|
||||
private void checkForCoModification() {
|
||||
Validate.isTrue(myOriginalRemoveModCont == myRemoveModCount);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean removeIf(Predicate<DeleteConflict> theFilter) {
|
||||
return myList.removeIf(theFilter);
|
||||
boolean retVal = myList.removeIf(theFilter);
|
||||
if (retVal) {
|
||||
myRemoveModCount++;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public void addAll(DeleteConflictList theNewConflicts) {
|
||||
|
|
|
@ -64,6 +64,10 @@ public class CascadingDeleteInterceptorR4Test extends BaseResourceProviderR4Test
|
|||
e.setSubject(new Reference(myPatientId));
|
||||
myEncounterId = ourClient.create().resource(e).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
CarePlan cp = new CarePlan();
|
||||
cp.setEncounter(new Reference(myEncounterId));
|
||||
ourClient.create().resource(cp).execute();
|
||||
|
||||
Observation o = new Observation();
|
||||
o.setStatus(Observation.ObservationStatus.FINAL);
|
||||
o.setSubject( new Reference(myPatientId));
|
||||
|
|
|
@ -50,6 +50,10 @@
|
|||
ValueSet Precalculation sometimes failed on Oracle DBs due to an invalid SQL function. This
|
||||
has been corrected.
|
||||
</action>
|
||||
<action type="fix">
|
||||
A ConcurrentModificationException was sometimes thrown when performing a cascading delete.
|
||||
This has been corrected.
|
||||
</action>
|
||||
</release>
|
||||
<release version="4.1.0" date="2019-11-13" description="Jitterbug">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue