diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/test/java/ca/uhn/fhir/cli/HapiFlywayMigrateDatabaseCommandTest.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/test/java/ca/uhn/fhir/cli/HapiFlywayMigrateDatabaseCommandTest.java index 7da2c97911b..0ed53b49fdd 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/src/test/java/ca/uhn/fhir/cli/HapiFlywayMigrateDatabaseCommandTest.java +++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/test/java/ca/uhn/fhir/cli/HapiFlywayMigrateDatabaseCommandTest.java @@ -81,7 +81,7 @@ public class HapiFlywayMigrateDatabaseCommandTest { @Test public void testMigrateFrom340_NoFlyway() throws IOException, SQLException { - File location = getLocation("migrator_h2_test_340_current"); + File location = getLocation("migrator_h2_test_340_current_noflyway"); String url = "jdbc:h2:" + location.getAbsolutePath() + ";create=true"; DriverTypeEnum.ConnectionProperties connectionProperties = DriverTypeEnum.H2_EMBEDDED.newConnectionProperties(url, "", ""); diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml index 05b8bc61c91..433d5389d57 100644 --- a/hapi-fhir-docs/pom.xml +++ b/hapi-fhir-docs/pom.xml @@ -82,11 +82,6 @@ jdom2 2.0.6 - - org.slf4j - slf4j-simple - 1.7.28 - javax.servlet diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/delete/DeleteConflictList.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/delete/DeleteConflictList.java index 3ea747d7b17..24a44b7fccd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/delete/DeleteConflictList.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/delete/DeleteConflictList.java @@ -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 { private final List myList = new ArrayList<>(); private final Set myResourceIdsMarkedForDeletion; + private int myRemoveModCount; /** * Constructor @@ -69,11 +74,38 @@ public class DeleteConflictList implements Iterable { @Override public Iterator 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() { + + 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 theFilter) { - return myList.removeIf(theFilter); + boolean retVal = myList.removeIf(theFilter); + if (retVal) { + myRemoveModCount++; + } + return retVal; } public void addAll(DeleteConflictList theNewConflicts) { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/CascadingDeleteInterceptorR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/CascadingDeleteInterceptorR4Test.java index 55c6bbfac2c..0e447601bb3 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/CascadingDeleteInterceptorR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/CascadingDeleteInterceptorR4Test.java @@ -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)); diff --git a/hapi-fhir-jpaserver-migrate/pom.xml b/hapi-fhir-jpaserver-migrate/pom.xml index 8c12ac366c7..345bf13d5ee 100644 --- a/hapi-fhir-jpaserver-migrate/pom.xml +++ b/hapi-fhir-jpaserver-migrate/pom.xml @@ -101,6 +101,22 @@ + + org.jacoco + jacoco-maven-plugin + + true + + + + default-prepare-agent + + prepare-agent + + + + + org.apache.maven.plugins diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/BaseMigrator.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/BaseMigrator.java index 4d7fb50aa40..75e083894d9 100644 --- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/BaseMigrator.java +++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/BaseMigrator.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.migrate; +/*- + * #%L + * HAPI FHIR JPA Server - Migration + * %% + * Copyright (C) 2014 - 2019 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask; import org.flywaydb.core.api.MigrationInfoService; diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/BruteForceMigrator.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/BruteForceMigrator.java index 6853aafd13c..d40871f226c 100644 --- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/BruteForceMigrator.java +++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/BruteForceMigrator.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.jpa.migrate; +/*- + * #%L + * HAPI FHIR JPA Server - Migration + * %% + * Copyright (C) 2014 - 2019 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import org.flywaydb.core.api.MigrationInfoService; diff --git a/src/changes/changes.xml b/src/changes/changes.xml index d9c96b0bf4e..e261d7632cb 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,6 +50,10 @@ ValueSet Precalculation sometimes failed on Oracle DBs due to an invalid SQL function. This has been corrected. + + A ConcurrentModificationException was sometimes thrown when performing a cascading delete. + This has been corrected. +