diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml
index 48711901c07..2c10aae25a5 100644
--- a/hapi-deployable-pom/pom.xml
+++ b/hapi-deployable-pom/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml
index 1e38f02cfed..b56416253b2 100644
--- a/hapi-fhir-android/pom.xml
+++ b/hapi-fhir-android/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml
index cdc9fb9a19a..b4ce4b0e79c 100644
--- a/hapi-fhir-base/pom.xml
+++ b/hapi-fhir-base/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-batch/pom.xml b/hapi-fhir-batch/pom.xml
index 6f04343198b..c1d10dce87d 100644
--- a/hapi-fhir-batch/pom.xml
+++ b/hapi-fhir-batch/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml
index e2c08f160f5..9853fa18ffb 100644
--- a/hapi-fhir-bom/pom.xml
+++ b/hapi-fhir-bom/pom.xml
@@ -3,14 +3,14 @@
4.0.0
ca.uhn.hapi.fhir
hapi-fhir-bom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
pom
HAPI FHIR BOM
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-checkstyle/pom.xml b/hapi-fhir-checkstyle/pom.xml
index 1b58f737eb2..1bc75d5271c 100644
--- a/hapi-fhir-checkstyle/pom.xml
+++ b/hapi-fhir-checkstyle/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml
index d4693c0105c..7e84961bde6 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml
+++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
index 315763e4d0b..77106e656f2 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
+++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-fhir-cli
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml
index 1a2233d3eee..5807b01cc01 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml
+++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../../hapi-deployable-pom
diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml
index 19df1e60cb2..00acfbb2f29 100644
--- a/hapi-fhir-cli/pom.xml
+++ b/hapi-fhir-cli/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml
index 454ddbbafb5..198b7b59ba9 100644
--- a/hapi-fhir-client-okhttp/pom.xml
+++ b/hapi-fhir-client-okhttp/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml
index 1011dfaa38f..d4e66d1efe8 100644
--- a/hapi-fhir-client/pom.xml
+++ b/hapi-fhir-client/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml
index 594a512cc14..658014b7ee1 100644
--- a/hapi-fhir-converter/pom.xml
+++ b/hapi-fhir-converter/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml
index feb772022f5..0e2e4f52a3e 100644
--- a/hapi-fhir-dist/pom.xml
+++ b/hapi-fhir-dist/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml
index 70552e518ee..83809ea2bbf 100644
--- a/hapi-fhir-docs/pom.xml
+++ b/hapi-fhir-docs/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_0/3770-added-error-handling-for-batch2.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_0/3770-added-error-handling-for-batch2.yaml
new file mode 100644
index 00000000000..732dc9db24a
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_1_0/3770-added-error-handling-for-batch2.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 3770
+title: "Batch2 will have a standard error handling that will fail the job if it fails
+a chunk processing for more than 3 times.
+Further, added better validation to reindex job to disallow bad urls."
diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml
index 522084f9de1..00504fb69d7 100644
--- a/hapi-fhir-jacoco/pom.xml
+++ b/hapi-fhir-jacoco/pom.xml
@@ -11,7 +11,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml
index 915d263033f..4ad08f7c4a6 100644
--- a/hapi-fhir-jaxrsserver-base/pom.xml
+++ b/hapi-fhir-jaxrsserver-base/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpa/pom.xml b/hapi-fhir-jpa/pom.xml
index bf098fdf893..b001e7daca7 100644
--- a/hapi-fhir-jpa/pom.xml
+++ b/hapi-fhir-jpa/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
4.0.0
diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml
index 1ceaab27190..863369a8f8e 100644
--- a/hapi-fhir-jpaserver-base/pom.xml
+++ b/hapi-fhir-jpaserver-base/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java
index c23661afa10..4f5c4073385 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java
@@ -24,6 +24,7 @@ import ca.uhn.fhir.batch2.api.IJobPersistence;
import ca.uhn.fhir.batch2.api.JobOperationResultJson;
import ca.uhn.fhir.batch2.coordinator.BatchWorkChunk;
import ca.uhn.fhir.batch2.model.JobInstance;
+import ca.uhn.fhir.batch2.model.MarkWorkChunkAsErrorRequest;
import ca.uhn.fhir.batch2.model.StatusEnum;
import ca.uhn.fhir.batch2.model.WorkChunk;
import ca.uhn.fhir.jpa.dao.data.IBatch2JobInstanceRepository;
@@ -198,6 +199,14 @@ public class JpaJobPersistenceImpl implements IJobPersistence {
myWorkChunkRepository.updateChunkStatusAndIncrementErrorCountForEndError(theChunkId, new Date(), theErrorMessage, StatusEnum.ERRORED);
}
+ @Override
+ public Optional markWorkChunkAsErroredAndIncrementErrorCount(MarkWorkChunkAsErrorRequest theParameters) {
+ markWorkChunkAsErroredAndIncrementErrorCount(theParameters.getChunkId(), theParameters.getErrorMsg());
+ Optional op = myWorkChunkRepository.findById(theParameters.getChunkId());
+
+ return op.map(c -> toChunk(c, theParameters.isIncludeData()));
+ }
+
@Override
public void markWorkChunkAsFailed(String theChunkId, String theErrorMessage) {
myWorkChunkRepository.updateChunkStatusAndIncrementErrorCountForEndError(theChunkId, new Date(), theErrorMessage, StatusEnum.FAILED);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java
index 1097610f645..f73fdeebfe7 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java
@@ -27,6 +27,7 @@ class JpaJobPersistenceImplTest {
@InjectMocks
JpaJobPersistenceImpl mySvc;
+
@Test
void cancelSuccess() {
// setup
diff --git a/hapi-fhir-jpaserver-cql/pom.xml b/hapi-fhir-jpaserver-cql/pom.xml
index 1e1a3d026eb..b89e9aa7d9e 100644
--- a/hapi-fhir-jpaserver-cql/pom.xml
+++ b/hapi-fhir-jpaserver-cql/pom.xml
@@ -7,7 +7,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-mdm/pom.xml b/hapi-fhir-jpaserver-mdm/pom.xml
index 53b90ef5838..65bf75fd5a4 100644
--- a/hapi-fhir-jpaserver-mdm/pom.xml
+++ b/hapi-fhir-jpaserver-mdm/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml
index 3d78e8bed4f..d620d2f0ce6 100644
--- a/hapi-fhir-jpaserver-model/pom.xml
+++ b/hapi-fhir-jpaserver-model/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml
index e4559e77757..453e499ce36 100755
--- a/hapi-fhir-jpaserver-searchparam/pom.xml
+++ b/hapi-fhir-jpaserver-searchparam/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml
index 87706fa1422..3212b84c639 100644
--- a/hapi-fhir-jpaserver-subscription/pom.xml
+++ b/hapi-fhir-jpaserver-subscription/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-test-utilities/pom.xml b/hapi-fhir-jpaserver-test-utilities/pom.xml
index eaede692f68..988724210b7 100644
--- a/hapi-fhir-jpaserver-test-utilities/pom.xml
+++ b/hapi-fhir-jpaserver-test-utilities/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/Batch2JobHelper.java b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/Batch2JobHelper.java
index f8f8d79c183..434669adce2 100644
--- a/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/Batch2JobHelper.java
+++ b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/Batch2JobHelper.java
@@ -28,6 +28,9 @@ import org.awaitility.core.ConditionTimeoutException;
import org.hamcrest.Matchers;
import org.springframework.beans.factory.annotation.Autowired;
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
+
import java.util.Collection;
import java.util.List;
@@ -71,6 +74,17 @@ public class Batch2JobHelper {
}, equalTo(StatusEnum.CANCELLED));
}
+ public JobInstance awaitJobHitsStatusInTime(String theId, int theSeconds, StatusEnum... theStatuses) {
+ await().atMost(theSeconds, TimeUnit.SECONDS)
+ .pollDelay(Duration.ofSeconds(10))
+ .until(() -> {
+ myJobMaintenanceService.runMaintenancePass();
+ return myJobCoordinator.getInstance(theId).getStatus();
+ }, Matchers.in(theStatuses));
+
+ return myJobCoordinator.getInstance(theId);
+ }
+
public void awaitJobInProgress(String theId) {
await().until(() -> {
myJobMaintenanceService.runMaintenancePass();
diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/batch2/Batch2CoordinatorIT.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/batch2/Batch2CoordinatorIT.java
index 1067ff4f941..06de5234d2e 100644
--- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/batch2/Batch2CoordinatorIT.java
+++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/batch2/Batch2CoordinatorIT.java
@@ -7,6 +7,7 @@ import ca.uhn.fhir.batch2.api.IJobDataSink;
import ca.uhn.fhir.batch2.api.IJobMaintenanceService;
import ca.uhn.fhir.batch2.api.IJobPersistence;
import ca.uhn.fhir.batch2.api.IJobStepWorker;
+import ca.uhn.fhir.batch2.api.ILastJobStepWorker;
import ca.uhn.fhir.batch2.api.IReductionStepWorker;
import ca.uhn.fhir.batch2.api.JobExecutionFailedException;
import ca.uhn.fhir.batch2.api.RunOutcome;
@@ -17,6 +18,11 @@ import ca.uhn.fhir.batch2.model.ChunkOutcome;
import ca.uhn.fhir.batch2.model.JobDefinition;
import ca.uhn.fhir.batch2.model.JobInstance;
import ca.uhn.fhir.batch2.model.JobInstanceStartRequest;
+import ca.uhn.fhir.batch2.model.JobWorkNotificationJsonMessage;
+import ca.uhn.fhir.batch2.model.StatusEnum;
+import ca.uhn.fhir.jpa.subscription.channel.api.ChannelConsumerSettings;
+import ca.uhn.fhir.jpa.subscription.channel.api.IChannelFactory;
+import ca.uhn.fhir.jpa.subscription.channel.impl.LinkedBlockingChannel;
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
import ca.uhn.fhir.jpa.test.Batch2JobHelper;
import ca.uhn.fhir.model.api.IModelJson;
@@ -24,11 +30,16 @@ import ca.uhn.fhir.util.JsonUtil;
import ca.uhn.test.concurrency.LatchTimedOutError;
import ca.uhn.test.concurrency.PointcutLatch;
import com.fasterxml.jackson.annotation.JsonProperty;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.MessageHandler;
+import org.springframework.messaging.support.ExecutorChannelInterceptor;
import javax.annotation.Nonnull;
import java.util.ArrayList;
@@ -39,6 +50,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
+import static ca.uhn.fhir.batch2.config.BaseBatch2Config.CHANNEL_NAME;
+import static ca.uhn.fhir.batch2.coordinator.StepExecutionSvc.MAX_CHUNK_ERROR_COUNT;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -58,6 +71,8 @@ public class Batch2CoordinatorIT extends BaseJpaR4Test {
IJobMaintenanceService myJobMaintenanceService;
@Autowired
Batch2JobHelper myBatch2JobHelper;
+ @Autowired
+ private IChannelFactory myChannelFactory;
@Autowired
IJobPersistence myJobPersistence;
@@ -65,6 +80,7 @@ public class Batch2CoordinatorIT extends BaseJpaR4Test {
private final PointcutLatch myFirstStepLatch = new PointcutLatch("First Step");
private final PointcutLatch myLastStepLatch = new PointcutLatch("Last Step");
private IJobCompletionHandler myCompletionHandler;
+ private LinkedBlockingChannel myWorkChannel;
private static RunOutcome callLatch(PointcutLatch theLatch, StepExecutionDetails, ?> theStep) {
theLatch.call(theStep);
@@ -73,7 +89,13 @@ public class Batch2CoordinatorIT extends BaseJpaR4Test {
@BeforeEach
public void before() {
- myCompletionHandler = details -> {};
+ myCompletionHandler = details -> {};
+ myWorkChannel = (LinkedBlockingChannel) myChannelFactory.getOrCreateReceiver(CHANNEL_NAME, JobWorkNotificationJsonMessage.class, new ChannelConsumerSettings());
+ }
+
+ @AfterEach
+ public void after() {
+ myWorkChannel.clearInterceptorsForUnitTest();
}
@Test
@@ -123,7 +145,6 @@ public class Batch2CoordinatorIT extends BaseJpaR4Test {
myLastStepLatch.awaitExpected();
}
-
@Test
public void testFastTrack_Maintenance_do_not_both_call_CompletionHandler() throws InterruptedException {
IJobStepWorker firstStep = (step, sink) -> {
@@ -189,7 +210,6 @@ public class Batch2CoordinatorIT extends BaseJpaR4Test {
myLastStepLatch.awaitExpected();
}
-
@Test
public void testJobDefinitionWithReductionStepIT() throws InterruptedException {
// setup
@@ -371,6 +391,69 @@ public class Batch2CoordinatorIT extends BaseJpaR4Test {
myBatch2JobHelper.awaitJobCancelled(instanceId);
}
+ @Test
+ public void testStepRunFailure_continuouslyThrows_marksJobFailed() {
+ AtomicInteger interceptorCounter = new AtomicInteger();
+ myWorkChannel.addInterceptor(new ExecutorChannelInterceptor() {
+ @Override
+ public void afterMessageHandled(Message> message, MessageChannel channel, MessageHandler handler, Exception ex) {
+ if (ex != null) {
+ interceptorCounter.incrementAndGet();
+ ourLog.info("Work Channel Exception thrown: {}. Resending message", ex.getMessage());
+ channel.send(message);
+ }
+ }
+ });
+
+ // setup
+ AtomicInteger counter = new AtomicInteger();
+ // step 1
+ IJobStepWorker first = (step, sink) -> {
+ counter.getAndIncrement();
+ throw new RuntimeException("Exception");
+ };
+ // final step
+ ILastJobStepWorker last = (step, sink) -> {
+ fail("We should never hit this last step");
+ return RunOutcome.SUCCESS;
+ };
+ // job definition
+ String jobId = new Exception().getStackTrace()[0].getMethodName();
+ JobDefinition extends IModelJson> jd = JobDefinition.newBuilder()
+ .setJobDefinitionId(jobId)
+ .setJobDescription("test job")
+ .setJobDefinitionVersion(TEST_JOB_VERSION)
+ .setParametersType(TestJobParameters.class)
+ .gatedExecution()
+ .addFirstStep(
+ FIRST_STEP_ID,
+ "Test first step",
+ FirstStepOutput.class,
+ first
+ )
+ .addLastStep(
+ LAST_STEP_ID,
+ "Test last step",
+ last
+ )
+ .build();
+ myJobDefinitionRegistry.addJobDefinition(jd);
+ // test
+ JobInstanceStartRequest request = buildRequest(jobId);
+ myFirstStepLatch.setExpectedCount(1);
+ String instanceId = myJobCoordinator.startInstance(request);
+ JobInstance instance = myBatch2JobHelper.awaitJobHitsStatusInTime(instanceId,
+ 12, // we want to wait a long time (2 min here) cause backoff is incremental
+ StatusEnum.FAILED, StatusEnum.ERRORED // error states
+ );
+
+ assertEquals(MAX_CHUNK_ERROR_COUNT + 1, counter.get());
+ assertEquals(MAX_CHUNK_ERROR_COUNT, interceptorCounter.get());
+
+ assertTrue(instance.getStatus() == StatusEnum.FAILED
+ || instance.getStatus() == StatusEnum.ERRORED);
+ }
+
@Nonnull
private JobInstanceStartRequest buildRequest(String jobId) {
JobInstanceStartRequest request = new JobInstanceStartRequest();
diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/bulk/imprt2/BulkImportR4Test.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/bulk/imprt2/BulkImportR4Test.java
index 6276b7850ac..195332023c2 100644
--- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/bulk/imprt2/BulkImportR4Test.java
+++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/bulk/imprt2/BulkImportR4Test.java
@@ -185,7 +185,7 @@ public class BulkImportR4Test extends BaseJpaR4Test {
assertNotNull(instance.getCreateTime());
assertNotNull(instance.getStartTime());
assertNull(instance.getEndTime());
- assertThat(instance.getErrorMessage(), containsString("NullPointerException: This is an exception"));
+ assertThat(instance.getErrorMessage(), containsString("This is an exception"));
});
} finally {
diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/delete/job/ReindexJobTest.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/delete/job/ReindexJobTest.java
index 33e5b128174..6c3779f837c 100644
--- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/delete/job/ReindexJobTest.java
+++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/delete/job/ReindexJobTest.java
@@ -129,7 +129,7 @@ public class ReindexJobTest extends BaseJpaR4Test {
// Verify
assertEquals(StatusEnum.ERRORED, outcome.getStatus());
- assertEquals("java.lang.NullPointerException: foo message", outcome.getErrorMessage());
+ assertEquals("foo message", outcome.getErrorMessage());
}
@Test
diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml
index 8fc4f4fddef..2ca8a8186ce 100644
--- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml
+++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml
index 8af75a2b980..758a1bf6527 100644
--- a/hapi-fhir-server-mdm/pom.xml
+++ b/hapi-fhir-server-mdm/pom.xml
@@ -7,7 +7,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-server-openapi/pom.xml b/hapi-fhir-server-openapi/pom.xml
index a5b836d628f..f9e0de9e422 100644
--- a/hapi-fhir-server-openapi/pom.xml
+++ b/hapi-fhir-server-openapi/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml
index 73e8d67a48f..dcc135356da 100644
--- a/hapi-fhir-server/pom.xml
+++ b/hapi-fhir-server/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml
index 708a4cdc153..7c59060a165 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml
index 49f6646d6aa..f2811a6c718 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot-samples
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
hapi-fhir-spring-boot-sample-client-apache
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml
index a3cfe0ac80f..bb03521f05f 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot-samples
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
hapi-fhir-spring-boot-sample-client-okhttp
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml
index f898db94f74..c4c9340e3af 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot-samples
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
hapi-fhir-spring-boot-sample-server-jersey
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml
index 25d8f341423..a6e1fa8d89f 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir-spring-boot
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
hapi-fhir-spring-boot-samples
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml
index 3bbf1f44270..9d9767e8047 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml
index e6dea8e8605..c8cd5a98676 100644
--- a/hapi-fhir-spring-boot/pom.xml
+++ b/hapi-fhir-spring-boot/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-sql-migrate/pom.xml b/hapi-fhir-sql-migrate/pom.xml
index e04ea6a1aae..3597a607fb7 100644
--- a/hapi-fhir-sql-migrate/pom.xml
+++ b/hapi-fhir-sql-migrate/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-storage-batch2-jobs/pom.xml b/hapi-fhir-storage-batch2-jobs/pom.xml
index 99469bb5135..f0213c484cf 100644
--- a/hapi-fhir-storage-batch2-jobs/pom.xml
+++ b/hapi-fhir-storage-batch2-jobs/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
4.0.0
diff --git a/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexJobParametersValidator.java b/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexJobParametersValidator.java
index 3b475160327..49185755eed 100644
--- a/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexJobParametersValidator.java
+++ b/hapi-fhir-storage-batch2-jobs/src/main/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexJobParametersValidator.java
@@ -21,13 +21,19 @@ package ca.uhn.fhir.batch2.jobs.reindex;
*/
import ca.uhn.fhir.batch2.api.IJobParametersValidator;
+import ca.uhn.fhir.batch2.jobs.parameters.PartitionedUrl;
import ca.uhn.fhir.batch2.jobs.parameters.UrlListValidator;
+import ca.uhn.fhir.util.UrlUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.ArrayList;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class ReindexJobParametersValidator implements IJobParametersValidator {
+
private final UrlListValidator myUrlListValidator;
public ReindexJobParametersValidator(UrlListValidator theUrlListValidator) {
@@ -37,6 +43,21 @@ public class ReindexJobParametersValidator implements IJobParametersValidator validate(@NotNull ReindexJobParameters theParameters) {
- return myUrlListValidator.validatePartitionedUrls(theParameters.getPartitionedUrls());
+ List errors = myUrlListValidator.validatePartitionedUrls(theParameters.getPartitionedUrls());
+
+ if (errors == null || errors.isEmpty()) {
+ // only check if there's no other errors (new list to fix immutable issues)
+ errors = new ArrayList<>();
+ List urls = theParameters.getPartitionedUrls();
+ for (PartitionedUrl purl : urls) {
+ String url = purl.getUrl();
+
+ if (url.contains(" ") || url.contains("\n") || url.contains("\t")) {
+ errors.add("Invalid URL. URL cannot contain spaces : " + url);
+ }
+ }
+ }
+
+ return errors;
}
}
diff --git a/hapi-fhir-storage-batch2-jobs/src/test/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexJobParametersValidatorTest.java b/hapi-fhir-storage-batch2-jobs/src/test/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexJobParametersValidatorTest.java
new file mode 100644
index 00000000000..f8ee5873a2c
--- /dev/null
+++ b/hapi-fhir-storage-batch2-jobs/src/test/java/ca/uhn/fhir/batch2/jobs/reindex/ReindexJobParametersValidatorTest.java
@@ -0,0 +1,47 @@
+package ca.uhn.fhir.batch2.jobs.reindex;
+
+import ca.uhn.fhir.batch2.jobs.parameters.UrlListValidator;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.beans.factory.annotation.Value;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@ExtendWith(MockitoExtension.class)
+public class ReindexJobParametersValidatorTest {
+
+ @Mock
+ private UrlListValidator myListValidator;
+
+ @InjectMocks
+ private ReindexJobParametersValidator myValidator;
+
+ @ParameterizedTest
+ @ValueSource(strings = { "\n", " ", "\t" })
+ public void validate_urlWithSpace_fails(String theWhiteSpaceChar) {
+ List errors = runTestWithUrl("Patient," + theWhiteSpaceChar + "Practitioner");
+
+ // verify
+ assertFalse(errors.isEmpty());
+ assertTrue(errors.get(0).contains("Invalid URL. URL cannot contain spaces"));
+ }
+
+ private List runTestWithUrl(String theUrl) {
+ // setup
+ ReindexJobParameters parameters = new ReindexJobParameters();
+ parameters.addUrl(theUrl);
+
+ // test
+ List errors = myValidator.validate(parameters);
+
+ return errors;
+ }
+}
diff --git a/hapi-fhir-storage-batch2/pom.xml b/hapi-fhir-storage-batch2/pom.xml
index 662883fc325..1c76d1090a6 100644
--- a/hapi-fhir-storage-batch2/pom.xml
+++ b/hapi-fhir-storage-batch2/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/api/IJobPersistence.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/api/IJobPersistence.java
index d368ab54bb0..52d532b874e 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/api/IJobPersistence.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/api/IJobPersistence.java
@@ -22,6 +22,7 @@ package ca.uhn.fhir.batch2.api;
import ca.uhn.fhir.batch2.coordinator.BatchWorkChunk;
import ca.uhn.fhir.batch2.model.JobInstance;
+import ca.uhn.fhir.batch2.model.MarkWorkChunkAsErrorRequest;
import ca.uhn.fhir.batch2.model.StatusEnum;
import ca.uhn.fhir.batch2.model.WorkChunk;
@@ -100,8 +101,26 @@ public interface IJobPersistence {
*
* @param theChunkId The chunk ID
*/
+ @Deprecated
void markWorkChunkAsErroredAndIncrementErrorCount(String theChunkId, String theErrorMessage);
+ /**
+ * Marks a given chunk as having errored (ie, may be recoverable)
+ *
+ * Returns the work chunk.
+ *
+ * NB: For backwards compatibility reasons, it could be an empty optional, but
+ * this doesn't mean it has no workchunk (just implementers are not updated)
+ *
+ * @param theParameters - the parameters for marking the workchunk with error
+ * @return - workchunk optional, if available.
+ */
+ default Optional markWorkChunkAsErroredAndIncrementErrorCount(MarkWorkChunkAsErrorRequest theParameters) {
+ // old method - please override me
+ markWorkChunkAsErroredAndIncrementErrorCount(theParameters.getChunkId(), theParameters.getErrorMsg());
+ return Optional.empty(); // returning empty so as not to break implementers
+ }
+
/**
* Marks a given chunk as having failed (i.e. probably not recoverable)
*
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/StepExecutionSvc.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/StepExecutionSvc.java
index c2a9353abf4..873c3cdbd05 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/StepExecutionSvc.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/StepExecutionSvc.java
@@ -36,6 +36,7 @@ import ca.uhn.fhir.batch2.model.JobDefinition;
import ca.uhn.fhir.batch2.model.JobDefinitionStep;
import ca.uhn.fhir.batch2.model.JobInstance;
import ca.uhn.fhir.batch2.model.JobWorkCursor;
+import ca.uhn.fhir.batch2.model.MarkWorkChunkAsErrorRequest;
import ca.uhn.fhir.batch2.model.StatusEnum;
import ca.uhn.fhir.batch2.model.WorkChunk;
import ca.uhn.fhir.i18n.Msg;
@@ -48,10 +49,23 @@ import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Optional;
public class StepExecutionSvc {
private static final Logger ourLog = LoggerFactory.getLogger(StepExecutionSvc.class);
+ // TODO
+ /**
+ * This retry only works if your channel producer supports
+ * retries on message processing exceptions.
+ *
+ * What's more, we may one day want to have this configurable
+ * by the caller.
+ * But since this is not a feature of HAPI,
+ * this has not been done yet.
+ */
+ public static final int MAX_CHUNK_ERROR_COUNT = 3;
+
private final IJobPersistence myJobPersistence;
private final BatchJobSender myBatchJobSender;
@@ -303,7 +317,20 @@ public class StepExecutionSvc {
} catch (Exception e) {
ourLog.error("Failure executing job {} step {}", jobDefinitionId, targetStepId, e);
if (theStepExecutionDetails.hasAssociatedWorkChunk()) {
- myJobPersistence.markWorkChunkAsErroredAndIncrementErrorCount(chunkId, e.toString());
+ MarkWorkChunkAsErrorRequest parameters = new MarkWorkChunkAsErrorRequest();
+ parameters.setChunkId(chunkId);
+ parameters.setErrorMsg(e.getMessage());
+ Optional updatedOp = myJobPersistence.markWorkChunkAsErroredAndIncrementErrorCount(parameters);
+ if (updatedOp.isPresent()) {
+ WorkChunk chunk = updatedOp.get();
+
+ // TODO - marking for posterity
+ // see comments on MAX_CHUNK_ERROR_COUNT
+ if (chunk.getErrorCount() > MAX_CHUNK_ERROR_COUNT) {
+ myJobPersistence.markWorkChunkAsFailed(chunkId, "Too many errors: " + chunk.getErrorCount());
+ return false;
+ }
+ }
}
throw new JobStepFailedException(Msg.code(2041) + e.getMessage(), e);
} catch (Throwable t) {
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/SynchronizedJobPersistenceWrapper.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/SynchronizedJobPersistenceWrapper.java
index ff3ff56e0b5..3242f803b9e 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/SynchronizedJobPersistenceWrapper.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/coordinator/SynchronizedJobPersistenceWrapper.java
@@ -23,6 +23,7 @@ package ca.uhn.fhir.batch2.coordinator;
import ca.uhn.fhir.batch2.api.IJobPersistence;
import ca.uhn.fhir.batch2.api.JobOperationResultJson;
import ca.uhn.fhir.batch2.model.JobInstance;
+import ca.uhn.fhir.batch2.model.MarkWorkChunkAsErrorRequest;
import ca.uhn.fhir.batch2.model.StatusEnum;
import ca.uhn.fhir.batch2.model.WorkChunk;
@@ -92,6 +93,11 @@ public class SynchronizedJobPersistenceWrapper implements IJobPersistence {
myWrap.markWorkChunkAsErroredAndIncrementErrorCount(theChunkId, theErrorMessage);
}
+ @Override
+ public Optional markWorkChunkAsErroredAndIncrementErrorCount(MarkWorkChunkAsErrorRequest theParameters) {
+ return myWrap.markWorkChunkAsErroredAndIncrementErrorCount(theParameters);
+ }
+
@Override
public synchronized void markWorkChunkAsFailed(String theChunkId, String theErrorMessage) {
myWrap.markWorkChunkAsFailed(theChunkId, theErrorMessage);
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/MarkWorkChunkAsErrorRequest.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/MarkWorkChunkAsErrorRequest.java
new file mode 100644
index 00000000000..1cb3cbce20a
--- /dev/null
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/MarkWorkChunkAsErrorRequest.java
@@ -0,0 +1,33 @@
+package ca.uhn.fhir.batch2.model;
+
+public class MarkWorkChunkAsErrorRequest {
+ private String myChunkId;
+
+ private String myErrorMsg;
+
+ private boolean myIncludeData;
+
+ public String getChunkId() {
+ return myChunkId;
+ }
+
+ public void setChunkId(String theChunkId) {
+ myChunkId = theChunkId;
+ }
+
+ public String getErrorMsg() {
+ return myErrorMsg;
+ }
+
+ public void setErrorMsg(String theErrorMsg) {
+ myErrorMsg = theErrorMsg;
+ }
+
+ public boolean isIncludeData() {
+ return myIncludeData;
+ }
+
+ public void setIncludeData(boolean theIncludeData) {
+ myIncludeData = theIncludeData;
+ }
+}
diff --git a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/StatusEnum.java b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/StatusEnum.java
index 1657eff4aad..83775bd4dc0 100644
--- a/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/StatusEnum.java
+++ b/hapi-fhir-storage-batch2/src/main/java/ca/uhn/fhir/batch2/model/StatusEnum.java
@@ -116,6 +116,7 @@ public enum StatusEnum {
retVal = ourNotEndedStatuses;
return retVal;
}
+
@Nonnull
private static void initializeStaticEndedStatuses() {
EnumSet endedSet = EnumSet.noneOf(StatusEnum.class);
diff --git a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java
index 245a0ac307f..6314b615461 100644
--- a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java
+++ b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/JobCoordinatorImplTest.java
@@ -12,6 +12,7 @@ import ca.uhn.fhir.batch2.model.JobInstance;
import ca.uhn.fhir.batch2.model.JobInstanceStartRequest;
import ca.uhn.fhir.batch2.model.JobWorkNotification;
import ca.uhn.fhir.batch2.model.JobWorkNotificationJsonMessage;
+import ca.uhn.fhir.batch2.model.MarkWorkChunkAsErrorRequest;
import ca.uhn.fhir.batch2.model.StatusEnum;
import ca.uhn.fhir.batch2.model.WorkChunk;
import ca.uhn.fhir.jpa.subscription.channel.api.IChannelReceiver;
@@ -245,8 +246,11 @@ public class JobCoordinatorImplTest extends BaseBatch2Test {
assertEquals(PARAM_2_VALUE, params.getParam2());
assertEquals(PASSWORD_VALUE, params.getPassword());
- verify(myJobInstancePersister, times(1)).markWorkChunkAsErroredAndIncrementErrorCount(eq(CHUNK_ID), myErrorMessageCaptor.capture());
- assertEquals("java.lang.NullPointerException: This is an error message", myErrorMessageCaptor.getValue());
+ ArgumentCaptor parametersArgumentCaptor = ArgumentCaptor.forClass(MarkWorkChunkAsErrorRequest.class);
+ verify(myJobInstancePersister, times(1)).markWorkChunkAsErroredAndIncrementErrorCount(parametersArgumentCaptor.capture());
+ MarkWorkChunkAsErrorRequest capturedParams = parametersArgumentCaptor.getValue();
+ assertEquals(CHUNK_ID, capturedParams.getChunkId());
+ assertEquals("This is an error message", capturedParams.getErrorMsg());
}
@Test
diff --git a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/StepExecutionSvcTest.java b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/StepExecutionSvcTest.java
index 0326ddacf8d..9e2b455f7bd 100644
--- a/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/StepExecutionSvcTest.java
+++ b/hapi-fhir-storage-batch2/src/test/java/ca/uhn/fhir/batch2/coordinator/StepExecutionSvcTest.java
@@ -19,6 +19,7 @@ import ca.uhn.fhir.batch2.model.JobDefinitionReductionStep;
import ca.uhn.fhir.batch2.model.JobDefinitionStep;
import ca.uhn.fhir.batch2.model.JobInstance;
import ca.uhn.fhir.batch2.model.JobWorkCursor;
+import ca.uhn.fhir.batch2.model.MarkWorkChunkAsErrorRequest;
import ca.uhn.fhir.batch2.model.StatusEnum;
import ca.uhn.fhir.batch2.model.WorkChunk;
import ca.uhn.fhir.batch2.model.WorkChunkData;
@@ -34,9 +35,12 @@ import org.mockito.junit.jupiter.MockitoExtension;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
@@ -492,11 +496,70 @@ public class StepExecutionSvcTest {
fail("Expected Exception to be thrown");
} catch (JobStepFailedException jobStepFailedException) {
assertTrue(jobStepFailedException.getMessage().contains(msg));
- } catch (Exception anythingElse) {
- fail(anythingElse.getMessage());
}
}
+ @Test
+ public void doExecution_stepWorkerThrowsRandomExceptionForever_eventuallyMarksAsFailedAndReturnsFalse() {
+ // setup
+ int counter = 0;
+ AtomicInteger errorCounter = new AtomicInteger();
+ String errorMsg = "my Error Message";
+ JobInstance jobInstance = getTestJobInstance();
+ WorkChunk chunk = new WorkChunk();
+ chunk.setId("chunkId");
+ chunk.setData(new StepInputData());
+
+ JobWorkCursor workCursor = mock(JobWorkCursor.class);
+
+ JobDefinitionStep step = mockOutWorkCursor(StepType.INTERMEDIATE, workCursor, true, false);
+
+ // when
+ when(myNonReductionStep.run(any(), any()))
+ .thenThrow(new RuntimeException(errorMsg));
+ when(myJobPersistence.markWorkChunkAsErroredAndIncrementErrorCount(any(MarkWorkChunkAsErrorRequest.class)))
+ .thenAnswer((p) -> {
+ WorkChunk ec = new WorkChunk();
+ ec.setId(chunk.getId());
+ int count = errorCounter.getAndIncrement();
+ ec.setErrorCount(count);
+ return Optional.of(ec);
+ });
+
+ // test
+ Boolean processedOutcomeSuccessfully = null;
+ do {
+ try {
+ JobStepExecutorOutput, ?, ?> output = myExecutorSvc.doExecution(
+ workCursor,
+ jobInstance,
+ chunk
+ );
+ /*
+ * Getting a value here means we are no longer
+ * throwing exceptions. Which is the desired outcome.
+ * We just now need to ensure that this outcome is
+ * "false"
+ */
+ processedOutcomeSuccessfully = output.isSuccessful();
+ } catch (JobStepFailedException ex) {
+ assertTrue(ex.getMessage().contains(errorMsg));
+ counter++;
+ }
+ /*
+ * +2 because...
+ * we check for > MAX_CHUNK_ERROR_COUNT (+1)
+ * we want it to run one extra time here (+1)
+ */
+ } while (processedOutcomeSuccessfully == null && counter < StepExecutionSvc.MAX_CHUNK_ERROR_COUNT + 2);
+
+ // verify
+ assertNotNull(processedOutcomeSuccessfully);
+ // +1 because of the > MAX_CHUNK_ERROR_COUNT check
+ assertEquals(StepExecutionSvc.MAX_CHUNK_ERROR_COUNT + 1, counter);
+ assertFalse(processedOutcomeSuccessfully);
+ }
+
private void runExceptionThrowingTest(Exception theExceptionToThrow) {
// setup
JobInstance jobInstance = getTestJobInstance();
diff --git a/hapi-fhir-storage-mdm/pom.xml b/hapi-fhir-storage-mdm/pom.xml
index ce925743bf4..ea823379a2b 100644
--- a/hapi-fhir-storage-mdm/pom.xml
+++ b/hapi-fhir-storage-mdm/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
4.0.0
diff --git a/hapi-fhir-storage-test-utilities/pom.xml b/hapi-fhir-storage-test-utilities/pom.xml
index 6d07c1a54cb..b522ba74de9 100644
--- a/hapi-fhir-storage-test-utilities/pom.xml
+++ b/hapi-fhir-storage-test-utilities/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
4.0.0
diff --git a/hapi-fhir-storage/pom.xml b/hapi-fhir-storage/pom.xml
index ee50e83ecf4..4c45f819d3b 100644
--- a/hapi-fhir-storage/pom.xml
+++ b/hapi-fhir-storage/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/patch/XmlPatchUtils.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/patch/XmlPatchUtils.java
index 4477b0ed2d4..f836b314c49 100644
--- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/patch/XmlPatchUtils.java
+++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/patch/XmlPatchUtils.java
@@ -1,7 +1,7 @@
package ca.uhn.fhir.jpa.patch;
-import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import com.github.dnault.xmlpatch.Patcher;
diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/subscription/channel/impl/LinkedBlockingChannel.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/subscription/channel/impl/LinkedBlockingChannel.java
index 71e4560b073..a22401f484a 100644
--- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/subscription/channel/impl/LinkedBlockingChannel.java
+++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/subscription/channel/impl/LinkedBlockingChannel.java
@@ -24,6 +24,7 @@ import ca.uhn.fhir.jpa.subscription.channel.api.IChannelProducer;
import ca.uhn.fhir.jpa.subscription.channel.api.IChannelReceiver;
import org.springframework.messaging.support.ExecutorSubscribableChannel;
+import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -44,9 +45,7 @@ public class LinkedBlockingChannel extends ExecutorSubscribableChannel implement
}
public void clearInterceptorsForUnitTest() {
- while (getInterceptors().size() > 0) {
- removeInterceptor(0);
- }
+ setInterceptors(new ArrayList<>());
}
@Override
diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/subscription/channel/impl/LinkedBlockingChannelFactory.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/subscription/channel/impl/LinkedBlockingChannelFactory.java
index 6742c9b4a2f..fc363c273f7 100644
--- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/subscription/channel/impl/LinkedBlockingChannelFactory.java
+++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/subscription/channel/impl/LinkedBlockingChannelFactory.java
@@ -34,6 +34,7 @@ import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.Nonnull;
import javax.annotation.PreDestroy;
import java.util.Collections;
import java.util.HashMap;
@@ -76,41 +77,44 @@ public class LinkedBlockingChannelFactory implements IChannelFactory {
// TODO - does this need retry settings?
final String channelName = myChannelNamer.getChannelName(theChannelName, theChannelSettings);
- return myChannels.computeIfAbsent(channelName, t -> {
+ return myChannels.computeIfAbsent(channelName, t -> buildLinkedBlockingChannel(theConcurrentConsumers, channelName));
+ }
- String threadNamingPattern = channelName + "-%d";
+ @Nonnull
+ private LinkedBlockingChannel buildLinkedBlockingChannel(int theConcurrentConsumers, String channelName) {
+ String threadNamingPattern = channelName + "-%d";
- ThreadFactory threadFactory = new BasicThreadFactory.Builder()
- .namingPattern(threadNamingPattern)
- .uncaughtExceptionHandler(uncaughtExceptionHandler(channelName))
- .daemon(false)
- .priority(Thread.NORM_PRIORITY)
- .build();
+ ThreadFactory threadFactory = new BasicThreadFactory.Builder()
+ .namingPattern(threadNamingPattern)
+ .uncaughtExceptionHandler(uncaughtExceptionHandler(channelName))
+ .daemon(false)
+ .priority(Thread.NORM_PRIORITY)
+ .build();
- LinkedBlockingQueue queue = new LinkedBlockingQueue<>(SubscriptionConstants.DELIVERY_EXECUTOR_QUEUE_SIZE);
- RejectedExecutionHandler rejectedExecutionHandler = (theRunnable, theExecutor) -> {
- ourLog.info("Note: Executor queue is full ({} elements), waiting for a slot to become available!", queue.size());
- StopWatch sw = new StopWatch();
- try {
- queue.put(theRunnable);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new RejectedExecutionException(Msg.code(568) + "Task " + theRunnable.toString() +
- " rejected from " + e);
- }
- ourLog.info("Slot become available after {}ms", sw.getMillis());
- };
- ThreadPoolExecutor executor = new ThreadPoolExecutor(
- theConcurrentConsumers,
- theConcurrentConsumers,
- 0L,
- TimeUnit.MILLISECONDS,
- queue,
- threadFactory,
- rejectedExecutionHandler);
- return new LinkedBlockingChannel(channelName, executor, queue);
+ LinkedBlockingQueue queue = new LinkedBlockingQueue<>(SubscriptionConstants.DELIVERY_EXECUTOR_QUEUE_SIZE);
+ RejectedExecutionHandler rejectedExecutionHandler = (theRunnable, theExecutor) -> {
+ ourLog.info("Note: Executor queue is full ({} elements), waiting for a slot to become available!", queue.size());
+ StopWatch sw = new StopWatch();
+ try {
+ queue.put(theRunnable);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new RejectedExecutionException(Msg.code(568) + "Task " + theRunnable.toString() +
+ " rejected from " + e);
+ }
+ ourLog.info("Slot become available after {}ms", sw.getMillis());
+ };
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(
+ theConcurrentConsumers,
+ theConcurrentConsumers,
+ 0L,
+ TimeUnit.MILLISECONDS,
+ queue,
+ threadFactory,
+ rejectedExecutionHandler);
- });
+ LinkedBlockingChannel retval = new LinkedBlockingChannel(channelName, executor, queue);
+ return retval;
}
private Thread.UncaughtExceptionHandler uncaughtExceptionHandler(String theChannelName) {
diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml
index 8302ec04709..84843bcb545 100644
--- a/hapi-fhir-structures-dstu2.1/pom.xml
+++ b/hapi-fhir-structures-dstu2.1/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml
index b0760e001dd..dcbedfab110 100644
--- a/hapi-fhir-structures-dstu2/pom.xml
+++ b/hapi-fhir-structures-dstu2/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml
index 94808234717..ca10663a30c 100644
--- a/hapi-fhir-structures-dstu3/pom.xml
+++ b/hapi-fhir-structures-dstu3/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml
index 2f77659a569..fd5ef3c4094 100644
--- a/hapi-fhir-structures-hl7org-dstu2/pom.xml
+++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml
index 62e11e88d93..0ff8aaab966 100644
--- a/hapi-fhir-structures-r4/pom.xml
+++ b/hapi-fhir-structures-r4/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml
index 3370977fb55..568537ed37a 100644
--- a/hapi-fhir-structures-r5/pom.xml
+++ b/hapi-fhir-structures-r5/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml
index 70b7b38db91..46e312f19c8 100644
--- a/hapi-fhir-test-utilities/pom.xml
+++ b/hapi-fhir-test-utilities/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml
index 061234832a7..ccf96613ecd 100644
--- a/hapi-fhir-testpage-overlay/pom.xml
+++ b/hapi-fhir-testpage-overlay/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../pom.xml
diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml
index 6b2c4412db6..2ec61f888ad 100644
--- a/hapi-fhir-validation-resources-dstu2.1/pom.xml
+++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml
index f36f507363d..8775b09c527 100644
--- a/hapi-fhir-validation-resources-dstu2/pom.xml
+++ b/hapi-fhir-validation-resources-dstu2/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml
index fff7c5f172e..edcab369e62 100644
--- a/hapi-fhir-validation-resources-dstu3/pom.xml
+++ b/hapi-fhir-validation-resources-dstu3/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml
index 63d2f5faaf6..5e8883fc636 100644
--- a/hapi-fhir-validation-resources-r4/pom.xml
+++ b/hapi-fhir-validation-resources-r4/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation-resources-r5/pom.xml b/hapi-fhir-validation-resources-r5/pom.xml
index 6318c468787..1c08994a734 100644
--- a/hapi-fhir-validation-resources-r5/pom.xml
+++ b/hapi-fhir-validation-resources-r5/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml
index 87a1911de5c..07f41fc1f58 100644
--- a/hapi-fhir-validation/pom.xml
+++ b/hapi-fhir-validation/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-deployable-pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../hapi-deployable-pom/pom.xml
diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml
index 394ecd93bc8..588d43672c5 100644
--- a/hapi-tinder-plugin/pom.xml
+++ b/hapi-tinder-plugin/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../pom.xml
@@ -58,37 +58,37 @@
ca.uhn.hapi.fhir
hapi-fhir-structures-dstu3
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-structures-hl7org-dstu2
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-structures-r4
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-structures-r5
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-validation-resources-dstu2
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-validation-resources-dstu3
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
ca.uhn.hapi.fhir
hapi-fhir-validation-resources-r4
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
org.apache.velocity
diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml
index a9db3a2641f..7fbb73f01d1 100644
--- a/hapi-tinder-test/pom.xml
+++ b/hapi-tinder-test/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../pom.xml
diff --git a/pom.xml b/pom.xml
index e89d1077c41..78931b57bb0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-fhir
pom
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
HAPI-FHIR
An open-source implementation of the FHIR specification in Java.
https://hapifhir.io
@@ -2015,7 +2015,7 @@
ca.uhn.hapi.fhir
hapi-fhir-checkstyle
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml
index 9338a3e152e..5af408dc72f 100644
--- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml
+++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../../pom.xml
diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml
index fa247f6a790..c1c34084df1 100644
--- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml
+++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../../pom.xml
diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml
index 2a5555cd21d..533ddffaedb 100644
--- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml
+++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 6.1.0-PRE13-SNAPSHOT
+ 6.1.0-PRE14-SNAPSHOT
../../pom.xml