2480 partition aware subscription (#3218)
* some fixmes to start
* Added some FIXMEs
* added RequestPartitionId to reosurceDelivryMessage and ResourceModifiedMessage
* ResourceDeliveryMessage and ResourceModifiedMessage tests
* fixed issue with test missing partitionHelperSvc mocked bean
* Added tests and implemented SubscriptionMatchingSubscriber for partition aware subscription
* modified implementation of partitionId in CanonicalSubscription
* Moved PartitionablePartitionId, and refactored all calls to getUserData(Constants.RESOURCE_PARTITION_ID) and setUserData(Constants.RESOURCE_PARTITION_ID)
* Revert "Moved PartitionablePartitionId, and refactored all calls to getUserData(Constants.RESOURCE_PARTITION_ID) and setUserData(Constants.RESOURCE_PARTITION_ID)"
This reverts commit fe40fb9733
.
* Got added partitionId to subscriptions, added changes to make SubscriptionMatchingSubscriberTest work
* added SubscriptionTriggering test, also added partition support to subscriptionLoader
* Changed implementation for storing partition id of subscriptions from messages, refactored tests to new implementation
* added all subscription systemRequestDetails with all partition to subscription reader
* refactored a generic system request details with default all partition request
* Added test for dao subscriptions, fixes to get the test working
* added partition support for latest version delivery
* added doc changes and changelog for multitenancy subscription
* cleanup and added partitioned subscription manually trigger test
* fixed mocked subscriptionDao
* added package-info for subscription module
* some code review changes
* removed AllPartitionSystemRequestDetail, added new text for multitenant subscription
* renamed method for code review
* version bump to 5.7.0PRE7
Co-authored-by: Michael Buckley <michael.buckley@smilecdr.com>
Co-authored-by: Ken Stevens <khstevens@gmail.com>
Co-authored-by: Long Ma <long@smilecdr.com>
Co-authored-by: Steven Li <steven@smilecdr.com>
This commit is contained in:
parent
d6e543a478
commit
a56603daa2
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: add
|
||||
issue: 2480
|
||||
title: "Added partition support for subscriptions. Subscriptions will now only match resource from the same partition"
|
|
@ -95,13 +95,13 @@ The following resource types may not be placed in any partition except the defau
|
|||
* CodeSystem
|
||||
* CompartmentDefinition
|
||||
* ConceptMap
|
||||
* Library
|
||||
* NamingSystem
|
||||
* OperationDefinition
|
||||
* Questionnaire
|
||||
* SearchParameter
|
||||
* StructureDefinition
|
||||
* StructureMap
|
||||
* Subscription
|
||||
* ValueSet
|
||||
|
||||
## Examples
|
||||
|
@ -150,18 +150,16 @@ None of the limitations listed here are considered permanent. Over time the HAPI
|
|||
* CodeSystem
|
||||
* CompartmentDefinition
|
||||
* ConceptMap
|
||||
* Library
|
||||
* NamingSystem
|
||||
* OperationDefinition
|
||||
* Questionnaire
|
||||
* SearchParameter
|
||||
* StructureDefinition
|
||||
* StructureMap
|
||||
* Subscription
|
||||
* ValueSet
|
||||
|
||||
* **Server Capability Statement is not partition aware**: The server creates and exposes a single server capability statement, covering all partitions. This can be misleading when partitioning us used as a multitenancy strategy.
|
||||
|
||||
* **Subscriptions may not be partitioned**: All subscriptions must be placed in the default partition, and subscribers will receive deliveries for any matching resources from all partitions.
|
||||
* **Server Capability Statement is not partition aware**: The server creates and exposes a single server capability statement, covering all partitions. This can be misleading when partitioning us used as a multitenancy strategy.
|
||||
|
||||
* **Conformance resources may not be partitioned**: Conformance resources must be placed in the default partition, and will be shared for any validation activities across all partitions.
|
||||
|
||||
|
@ -174,3 +172,5 @@ None of the limitations listed here are considered permanent. Over time the HAPI
|
|||
* **Package Operations are not partition aware**: Package operations will only create, update and query resources in the default partition.
|
||||
|
||||
* **Advanced Elasticsearch indexing is not partition optimized**: The results are correctly partitioned, but the extended indexing is not optimized to account for partitions.
|
||||
|
||||
* **Subscriptions are partition aware**: Subscriptions can be placed on any partition and will deliver matching resources from the same partition.
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -75,7 +75,6 @@ public class RequestPartitionHelperSvc implements IRequestPartitionHelperSvc {
|
|||
myNonPartitionableResourceNames = new HashSet<>();
|
||||
|
||||
// Infrastructure
|
||||
myNonPartitionableResourceNames.add("Subscription");
|
||||
myNonPartitionableResourceNames.add("SearchParameter");
|
||||
|
||||
// Validation and Conformance
|
||||
|
@ -85,6 +84,8 @@ public class RequestPartitionHelperSvc implements IRequestPartitionHelperSvc {
|
|||
myNonPartitionableResourceNames.add("CompartmentDefinition");
|
||||
myNonPartitionableResourceNames.add("OperationDefinition");
|
||||
|
||||
myNonPartitionableResourceNames.add("Library");
|
||||
|
||||
// Terminology
|
||||
myNonPartitionableResourceNames.add("ConceptMap");
|
||||
myNonPartitionableResourceNames.add("CodeSystem");
|
||||
|
|
|
@ -200,7 +200,7 @@ public abstract class BasePartitioningR4Test extends BaseJpaR4SystemTest {
|
|||
}
|
||||
|
||||
@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_READ)
|
||||
public RequestPartitionId PartitionIdentifyRead(ServletRequestDetails theRequestDetails) {
|
||||
public RequestPartitionId partitionIdentifyRead(ServletRequestDetails theRequestDetails) {
|
||||
RequestPartitionId retVal = myReadRequestPartitionIds.remove(0);
|
||||
ourLog.info("Returning partition for read: {}", retVal);
|
||||
return retVal;
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
package ca.uhn.fhir.jpa.partition;
|
||||
|
||||
import ca.uhn.fhir.interceptor.api.Hook;
|
||||
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.api.model.ExpungeOptions;
|
||||
import ca.uhn.fhir.jpa.config.StoppableSubscriptionDeliveringRestHookSubscriber;
|
||||
import ca.uhn.fhir.jpa.dao.r4.BasePartitioningR4Test;
|
||||
import ca.uhn.fhir.jpa.entity.PartitionEntity;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.subscription.BaseSubscriptionsR4Test;
|
||||
import ca.uhn.fhir.jpa.subscription.resthook.RestHookTestR4Test;
|
||||
import ca.uhn.fhir.jpa.subscription.triggering.ISubscriptionTriggeringSvc;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import org.awaitility.core.ConditionTimeoutException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.Observation;
|
||||
import org.hl7.fhir.r4.model.Parameters;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Subscription;
|
||||
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 javax.servlet.ServletException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class PartitionedSubscriptionTriggeringR4Test extends BaseSubscriptionsR4Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(RestHookTestR4Test.class);
|
||||
|
||||
@Autowired
|
||||
StoppableSubscriptionDeliveringRestHookSubscriber myStoppableSubscriptionDeliveringRestHookSubscriber;
|
||||
|
||||
@Autowired
|
||||
private ISubscriptionTriggeringSvc mySubscriptionTriggeringSvc;
|
||||
|
||||
static final String PARTITION_1 = "PART-1";
|
||||
static final String PARTITION_2 = "PART-2";
|
||||
|
||||
protected MyReadWriteInterceptor myPartitionInterceptor;
|
||||
protected LocalDate myPartitionDate;
|
||||
protected LocalDate myPartitionDate2;
|
||||
protected int myPartitionId;
|
||||
protected int myPartitionId2;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEach() throws ServletException {
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myPartitionSettings.setIncludePartitionInSearchHashes(new PartitionSettings().isIncludePartitionInSearchHashes());
|
||||
|
||||
myDaoConfig.setUniqueIndexesEnabled(true);
|
||||
|
||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);
|
||||
|
||||
myPartitionDate = LocalDate.of(2020, Month.JANUARY, 14);
|
||||
myPartitionDate2 = LocalDate.of(2020, Month.JANUARY, 15);
|
||||
myPartitionId = 1;
|
||||
myPartitionId2 = 2;
|
||||
|
||||
myPartitionInterceptor = new MyReadWriteInterceptor();
|
||||
myPartitionInterceptor.setResultPartitionId(RequestPartitionId.fromPartitionNames(PARTITION_1));
|
||||
|
||||
mySrdInterceptorService.registerInterceptor(myPartitionInterceptor);
|
||||
|
||||
myPartitionConfigSvc.createPartition(new PartitionEntity().setId(1).setName(PARTITION_1));
|
||||
myPartitionConfigSvc.createPartition(new PartitionEntity().setId(2).setName(PARTITION_2));
|
||||
|
||||
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.ENABLED);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@Override
|
||||
public void afterUnregisterRestHookListener() {
|
||||
myStoppableSubscriptionDeliveringRestHookSubscriber.setCountDownLatch(null);
|
||||
myStoppableSubscriptionDeliveringRestHookSubscriber.unPause();
|
||||
myDaoConfig.setTriggerSubscriptionsForNonVersioningChanges(new DaoConfig().isTriggerSubscriptionsForNonVersioningChanges());
|
||||
|
||||
myDaoRegistry.getSystemDao().expunge(new ExpungeOptions().setExpungeEverything(true), null);
|
||||
|
||||
myPartitionSettings.setUnnamedPartitionMode(false);
|
||||
|
||||
mySrdInterceptorService.unregisterInterceptorsIf(t -> t instanceof BasePartitioningR4Test.MyReadWriteInterceptor);
|
||||
myInterceptor = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSubscriptionInPartition() throws Exception {
|
||||
String payload = "application/fhir+json";
|
||||
|
||||
String code = "1000000050";
|
||||
String criteria1 = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
Subscription subscription = newSubscription(criteria1, payload);
|
||||
|
||||
assertEquals(mySrdInterceptorService.getAllRegisteredInterceptors().size(), 1);
|
||||
|
||||
myDaoRegistry.getResourceDao("Subscription").create(subscription, mySrd);
|
||||
|
||||
waitForActivatedSubscriptionCount(1);
|
||||
|
||||
Observation observation = createBaseObservation(code, "SNOMED-CT");
|
||||
myDaoRegistry.getResourceDao("Observation").create(observation, mySrd);
|
||||
|
||||
// Should see 1 subscription notification
|
||||
waitForQueueToDrain();
|
||||
assertEquals(0, ourObservationProvider.getCountCreate());
|
||||
ourObservationProvider.waitForUpdateCount(1);
|
||||
|
||||
assertEquals(Constants.CT_FHIR_JSON_NEW, ourRestfulServer.getRequestContentTypes().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSubscriptionInPartitionAndResourceInDifferentPartition() throws Exception {
|
||||
String payload = "application/fhir+json";
|
||||
|
||||
String code = "1000000050";
|
||||
String criteria1 = "Patient?active=true";
|
||||
Subscription subscription = newSubscription(criteria1, payload);
|
||||
|
||||
assertEquals(mySrdInterceptorService.getAllRegisteredInterceptors().size(), 1);
|
||||
|
||||
myDaoRegistry.getResourceDao("Subscription").create(subscription, mySrd);
|
||||
|
||||
waitForActivatedSubscriptionCount(1);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setActive(true);
|
||||
myDaoRegistry.getResourceDao("Patient").create(patient, new SystemRequestDetails().setRequestPartitionId(RequestPartitionId.fromPartitionId(2)));
|
||||
|
||||
// Should see 0 subscription notification
|
||||
waitForQueueToDrain();
|
||||
assertEquals(0, ourPatientProvider.getCountCreate());
|
||||
|
||||
try {
|
||||
// Should have 0 matching subscription, if we get 1 update count then the test fails
|
||||
ourPatientProvider.waitForUpdateCount(1);
|
||||
fail();
|
||||
} catch (ConditionTimeoutException e) {
|
||||
assertEquals(0, ourRestfulServer.getRequestContentTypes().size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualTriggeredSubscriptionInPartition() throws Exception {
|
||||
String payload = "application/fhir+json";
|
||||
String code = "1000000050";
|
||||
String criteria1 = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
|
||||
// Create the resource first
|
||||
DaoMethodOutcome observationOutcome = myDaoRegistry.getResourceDao("Observation").create(createBaseObservation(code, "SNOMED-CT"), mySrd);
|
||||
|
||||
Observation observation = (Observation) observationOutcome.getResource();
|
||||
|
||||
// Create the subscription now
|
||||
DaoMethodOutcome subscriptionOutcome = myDaoRegistry.getResourceDao("Subscription").create(newSubscription(criteria1, payload), mySrd);
|
||||
|
||||
assertEquals(mySrdInterceptorService.getAllRegisteredInterceptors().size(), 1);
|
||||
|
||||
Subscription subscription = (Subscription) subscriptionOutcome.getResource();
|
||||
|
||||
waitForActivatedSubscriptionCount(1);
|
||||
|
||||
ArrayList<IPrimitiveType<String>> resourceIdList = new ArrayList<>();
|
||||
resourceIdList.add(observation.getIdElement());
|
||||
|
||||
|
||||
Parameters resultParameters = (Parameters) mySubscriptionTriggeringSvc.triggerSubscription(resourceIdList, null, subscription.getIdElement());
|
||||
|
||||
waitForQueueToDrain();
|
||||
assertEquals(0, ourObservationProvider.getCountCreate());
|
||||
|
||||
String responseValue = resultParameters.getParameter().get(0).getValue().primitiveValue();
|
||||
assertThat(responseValue, containsString("Subscription triggering job submitted as JOB ID"));
|
||||
}
|
||||
|
||||
@Interceptor
|
||||
public static class MyReadWriteInterceptor {
|
||||
private RequestPartitionId myReadPartitionId;
|
||||
|
||||
public void setResultPartitionId(RequestPartitionId theRequestPartitionId) {
|
||||
myReadPartitionId = theRequestPartitionId;
|
||||
}
|
||||
|
||||
@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_READ)
|
||||
public RequestPartitionId read() {
|
||||
RequestPartitionId retVal = myReadPartitionId;
|
||||
ourLog.info("Returning partition for read: {}", retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_CREATE)
|
||||
public RequestPartitionId create() {
|
||||
RequestPartitionId retVal = myReadPartitionId;
|
||||
ourLog.info("Returning partition for write: {}", retVal);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -142,20 +142,25 @@ public abstract class BaseSubscriptionsR4Test extends BaseResourceProviderR4Test
|
|||
}
|
||||
|
||||
|
||||
protected Observation sendObservation(String code, String system) {
|
||||
protected Observation sendObservation(String theCode, String theSystem) {
|
||||
Observation observation = createBaseObservation(theCode, theSystem);
|
||||
|
||||
IIdType id = myObservationDao.create(observation).getId();
|
||||
observation.setId(id);
|
||||
|
||||
return observation;
|
||||
}
|
||||
|
||||
protected Observation createBaseObservation(String theCode, String theSystem) {
|
||||
Observation observation = new Observation();
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
observation.setCode(codeableConcept);
|
||||
observation.getIdentifierFirstRep().setSystem("foo").setValue("1");
|
||||
Coding coding = codeableConcept.addCoding();
|
||||
coding.setCode(code);
|
||||
coding.setSystem(system);
|
||||
coding.setCode(theCode);
|
||||
coding.setSystem(theSystem);
|
||||
|
||||
observation.setStatus(Observation.ObservationStatus.FINAL);
|
||||
|
||||
IIdType id = myObservationDao.create(observation).getId();
|
||||
observation.setId(id);
|
||||
|
||||
return observation;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public class ProducingChannelParameters extends BaseChannelParameters {
|
|||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* <p>
|
||||
* Producing channels are sending channels. They send data to topics/queues.
|
||||
*
|
||||
* @param theChannelName
|
||||
|
|
|
@ -24,7 +24,7 @@ public class ReceivingChannelParameters extends BaseChannelParameters {
|
|||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* <p>
|
||||
* Receiving channels are channels that receive data from topics/queues
|
||||
*
|
||||
* @param theChannelName
|
||||
|
|
|
@ -23,8 +23,10 @@ package ca.uhn.fhir.jpa.subscription.match.deliver.resthook;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.subscription.match.deliver.BaseSubscriptionDeliverySubscriber;
|
||||
|
@ -162,10 +164,11 @@ public class SubscriptionDeliveringRestHookSubscriber extends BaseSubscriptionDe
|
|||
return operation;
|
||||
}
|
||||
|
||||
public IBaseResource getResource(IIdType payloadId) throws ResourceGoneException {
|
||||
public IBaseResource getResource(IIdType payloadId, RequestPartitionId thePartitionId) throws ResourceGoneException {
|
||||
RuntimeResourceDefinition resourceDef = myFhirContext.getResourceDefinition(payloadId.getResourceType());
|
||||
SystemRequestDetails systemRequestDetails = new SystemRequestDetails().setRequestPartitionId(thePartitionId);
|
||||
IFhirResourceDao<?> dao = myDaoRegistry.getResourceDao(resourceDef.getImplementingClass());
|
||||
return dao.read(payloadId.toVersionless());
|
||||
return dao.read(payloadId.toVersionless(), systemRequestDetails);
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,7 +180,7 @@ public class SubscriptionDeliveringRestHookSubscriber extends BaseSubscriptionDe
|
|||
|
||||
try {
|
||||
if (payloadId != null) {
|
||||
payloadResource = getResource(payloadId.toVersionless());
|
||||
payloadResource = getResource(payloadId.toVersionless(), theMsg.getRequestPartitionId());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -24,12 +24,15 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
|
||||
import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
|
||||
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -37,7 +40,7 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class DaoSubscriptionMatcher implements ISubscriptionMatcher {
|
||||
private Logger ourLog = LoggerFactory.getLogger(DaoSubscriptionMatcher.class);
|
||||
private final Logger ourLog = LoggerFactory.getLogger(DaoSubscriptionMatcher.class);
|
||||
|
||||
@Autowired
|
||||
DaoRegistry myDaoRegistry;
|
||||
|
@ -56,7 +59,7 @@ public class DaoSubscriptionMatcher implements ISubscriptionMatcher {
|
|||
// Run the subscriptions query and look for matches, add the id as part of the criteria to avoid getting matches of previous resources rather than the recent resource
|
||||
criteria += "&_id=" + id.toUnqualifiedVersionless().getValue();
|
||||
|
||||
IBundleProvider results = performSearch(criteria);
|
||||
IBundleProvider results = performSearch(criteria, theSubscription);
|
||||
|
||||
ourLog.debug("Subscription check found {} results for query: {}", results.size(), criteria);
|
||||
|
||||
|
@ -66,7 +69,7 @@ public class DaoSubscriptionMatcher implements ISubscriptionMatcher {
|
|||
/**
|
||||
* Search based on a query criteria
|
||||
*/
|
||||
private IBundleProvider performSearch(String theCriteria) {
|
||||
private IBundleProvider performSearch(String theCriteria, CanonicalSubscription theSubscription) {
|
||||
IFhirResourceDao<?> subscriptionDao = myDaoRegistry.getSubscriptionDao();
|
||||
RuntimeResourceDefinition responseResourceDef = subscriptionDao.validateCriteriaAndReturnResourceDefinition(theCriteria);
|
||||
SearchParameterMap responseCriteriaUrl = myMatchUrlService.translateMatchUrl(theCriteria, responseResourceDef);
|
||||
|
@ -74,7 +77,9 @@ public class DaoSubscriptionMatcher implements ISubscriptionMatcher {
|
|||
IFhirResourceDao<? extends IBaseResource> responseDao = myDaoRegistry.getResourceDao(responseResourceDef.getImplementingClass());
|
||||
responseCriteriaUrl.setLoadSynchronousUpTo(1);
|
||||
|
||||
return responseDao.search(responseCriteriaUrl);
|
||||
PartitionablePartitionId partitionId = new PartitionablePartitionId(theSubscription.getRequestPartitionId(), null);
|
||||
RequestDetails systemRequestDetails = new SystemRequestDetails().setRequestPartitionId(partitionId.toPartitionId());
|
||||
return responseDao.search(responseCriteriaUrl, systemRequestDetails);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.subscription.match.matcher.subscriber;
|
|||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.subscription.match.matcher.matching.SubscriptionStrategyEvaluator;
|
||||
import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionCanonicalizer;
|
||||
import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionConstants;
|
||||
|
@ -49,7 +50,7 @@ import javax.annotation.Nonnull;
|
|||
* Also validates criteria. If invalid, rejects the subscription without persisting the subscription.
|
||||
*/
|
||||
public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscriptionResources implements MessageHandler {
|
||||
private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingSubscriber.class);
|
||||
private final Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingSubscriber.class);
|
||||
@Autowired
|
||||
private SubscriptionRegistry mySubscriptionRegistry;
|
||||
@Autowired
|
||||
|
@ -115,19 +116,21 @@ public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscript
|
|||
@SuppressWarnings("unchecked")
|
||||
private boolean activateSubscription(final IBaseResource theSubscription) {
|
||||
IFhirResourceDao subscriptionDao = myDaoRegistry.getSubscriptionDao();
|
||||
IBaseResource subscription = subscriptionDao.read(theSubscription.getIdElement());
|
||||
SystemRequestDetails srd = SystemRequestDetails.forAllPartition();
|
||||
|
||||
IBaseResource subscription = subscriptionDao.read(theSubscription.getIdElement(), SystemRequestDetails.forAllPartition());
|
||||
subscription.setId(subscription.getIdElement().toVersionless());
|
||||
|
||||
ourLog.info("Activating subscription {} from status {} to {}", subscription.getIdElement().toUnqualified().getValue(), SubscriptionConstants.REQUESTED_STATUS, SubscriptionConstants.ACTIVE_STATUS);
|
||||
try {
|
||||
SubscriptionUtil.setStatus(myFhirContext, subscription, SubscriptionConstants.ACTIVE_STATUS);
|
||||
subscriptionDao.update(subscription);
|
||||
subscriptionDao.update(subscription, srd);
|
||||
return true;
|
||||
} catch (final UnprocessableEntityException e) {
|
||||
ourLog.info("Changing status of {} to ERROR", subscription.getIdElement());
|
||||
SubscriptionUtil.setStatus(myFhirContext, subscription, "error");
|
||||
SubscriptionUtil.setReason(myFhirContext, subscription, e.getMessage());
|
||||
subscriptionDao.update(subscription);
|
||||
subscriptionDao.update(subscription, srd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
*/
|
||||
|
||||
public class SubscriptionMatchingSubscriber implements MessageHandler {
|
||||
private Logger ourLog = LoggerFactory.getLogger(SubscriptionMatchingSubscriber.class);
|
||||
private final Logger ourLog = LoggerFactory.getLogger(SubscriptionMatchingSubscriber.class);
|
||||
public static final String SUBSCRIPTION_MATCHING_CHANNEL_NAME = "subscription-matching";
|
||||
|
||||
@Autowired
|
||||
|
@ -123,7 +123,12 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
|
|||
boolean resourceMatched = false;
|
||||
|
||||
for (ActiveSubscription nextActiveSubscription : subscriptions) {
|
||||
|
||||
// skip if the partitions don't match
|
||||
CanonicalSubscription subscription = nextActiveSubscription.getSubscription();
|
||||
if (subscription != null && subscription.getRequestPartitionId() != null && theMsg.getPartitionId() != null
|
||||
&& !theMsg.getPartitionId().hasPartitionId(subscription.getRequestPartitionId())) {
|
||||
continue;
|
||||
}
|
||||
String nextSubscriptionId = getId(nextActiveSubscription);
|
||||
|
||||
if (isNotBlank(theMsg.getSubscriptionId())) {
|
||||
|
@ -154,15 +159,15 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
|
|||
}
|
||||
|
||||
IBaseResource payload = theMsg.getNewPayload(myFhirContext);
|
||||
CanonicalSubscription subscription = nextActiveSubscription.getSubscription();
|
||||
|
||||
EncodingEnum encoding = null;
|
||||
if (subscription.getPayloadString() != null && !subscription.getPayloadString().isEmpty()) {
|
||||
if (subscription != null && subscription.getPayloadString() != null && !subscription.getPayloadString().isEmpty()) {
|
||||
encoding = EncodingEnum.forContentType(subscription.getPayloadString());
|
||||
}
|
||||
encoding = defaultIfNull(encoding, EncodingEnum.JSON);
|
||||
|
||||
ResourceDeliveryMessage deliveryMsg = new ResourceDeliveryMessage();
|
||||
deliveryMsg.setPartitionId(theMsg.getPartitionId());
|
||||
|
||||
deliveryMsg.setPayload(myFhirContext, payload, encoding);
|
||||
deliveryMsg.setSubscription(subscription);
|
||||
|
|
|
@ -21,10 +21,15 @@ package ca.uhn.fhir.jpa.subscription.match.matcher.subscriber;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionCanonicalizer;
|
||||
import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionRegistry;
|
||||
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
|
||||
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -42,13 +47,17 @@ import javax.annotation.Nonnull;
|
|||
* Also validates criteria. If invalid, rejects the subscription without persisting the subscription.
|
||||
*/
|
||||
public class SubscriptionRegisteringSubscriber extends BaseSubscriberForSubscriptionResources implements MessageHandler {
|
||||
private Logger ourLog = LoggerFactory.getLogger(SubscriptionRegisteringSubscriber.class);
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionRegisteringSubscriber.class);
|
||||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
@Autowired
|
||||
private SubscriptionRegistry mySubscriptionRegistry;
|
||||
@Autowired
|
||||
private SubscriptionCanonicalizer mySubscriptionCanonicalizer;
|
||||
@Autowired
|
||||
private PartitionSettings myPartitionSettings;
|
||||
@Autowired
|
||||
private DaoRegistry myDaoRegistry;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -77,9 +86,18 @@ public class SubscriptionRegisteringSubscriber extends BaseSubscriberForSubscrip
|
|||
case CREATE:
|
||||
case UPDATE:
|
||||
IBaseResource subscription = payload.getNewPayload(myFhirContext);
|
||||
IBaseResource subscriptionToRegister = subscription;
|
||||
String statusString = mySubscriptionCanonicalizer.getSubscriptionStatus(subscription);
|
||||
|
||||
// reading resource back from db in order to store partition id in the userdata of the resource for partitioned subscriptions
|
||||
if (myPartitionSettings.isPartitioningEnabled()) {
|
||||
IFhirResourceDao subscriptionDao = myDaoRegistry.getSubscriptionDao();
|
||||
RequestDetails systemRequestDetails = new SystemRequestDetails().setRequestPartitionId(payload.getPartitionId());
|
||||
subscriptionToRegister = subscriptionDao.read(subscription.getIdElement(), systemRequestDetails);
|
||||
}
|
||||
|
||||
if ("active".equals(statusString)) {
|
||||
mySubscriptionRegistry.registerSubscriptionUnlessAlreadyRegistered(payload.getNewPayload(myFhirContext));
|
||||
mySubscriptionRegistry.registerSubscriptionUnlessAlreadyRegistered(subscriptionToRegister);
|
||||
} else {
|
||||
mySubscriptionRegistry.unregisterSubscriptionIfRegistered(payload.getPayloadId(myFhirContext).getIdPart());
|
||||
}
|
||||
|
|
|
@ -27,13 +27,14 @@ import ca.uhn.fhir.jpa.cache.IResourceChangeListener;
|
|||
import ca.uhn.fhir.jpa.cache.IResourceChangeListenerCache;
|
||||
import ca.uhn.fhir.jpa.cache.IResourceChangeListenerRegistry;
|
||||
import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.jpa.searchparam.retry.Retrier;
|
||||
import ca.uhn.fhir.jpa.subscription.match.matcher.subscriber.SubscriptionActivatingSubscriber;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -75,6 +76,7 @@ public class SubscriptionLoader implements IResourceChangeListener {
|
|||
private IResourceChangeListenerRegistry myResourceChangeListenerRegistry;
|
||||
|
||||
private SearchParameterMap mySearchParameterMap;
|
||||
private SystemRequestDetails mySystemRequestDetails;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -86,6 +88,8 @@ public class SubscriptionLoader implements IResourceChangeListener {
|
|||
@PostConstruct
|
||||
public void registerListener() {
|
||||
mySearchParameterMap = getSearchParameterMap();
|
||||
mySystemRequestDetails = SystemRequestDetails.forAllPartition();
|
||||
|
||||
IResourceChangeListenerCache subscriptionCache = myResourceChangeListenerRegistry.registerResourceResourceChangeListener("Subscription", mySearchParameterMap, this, REFRESH_INTERVAL);
|
||||
subscriptionCache.forceRefresh();
|
||||
}
|
||||
|
@ -142,7 +146,7 @@ public class SubscriptionLoader implements IResourceChangeListener {
|
|||
synchronized (mySyncSubscriptionsLock) {
|
||||
ourLog.debug("Starting sync subscriptions");
|
||||
|
||||
IBundleProvider subscriptionBundleList = getSubscriptionDao().search(mySearchParameterMap);
|
||||
IBundleProvider subscriptionBundleList = getSubscriptionDao().search(mySearchParameterMap, mySystemRequestDetails);
|
||||
|
||||
Integer subscriptionCount = subscriptionBundleList.size();
|
||||
assert subscriptionCount != null;
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Module to support Subscriptions
|
||||
* <p>
|
||||
* Subscriptions are partition aware
|
||||
* <p>
|
||||
* The functionalities of this module follows the HL7 spec on Subscriptions:
|
||||
* http://hl7.org/fhir/subscription.html
|
||||
* <p>
|
||||
* Activated by {@link ca.uhn.fhir.jpa.model.config.PartitionSettings#setPartitioningEnabled(boolean)}
|
||||
*/
|
||||
package ca.uhn.fhir.jpa.subscription;
|
|
@ -6,7 +6,9 @@ import ca.uhn.fhir.interceptor.api.HookParams;
|
|||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.impl.LinkedBlockingChannel;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
|
||||
import ca.uhn.fhir.jpa.subscription.match.matcher.matching.IResourceModifiedConsumer;
|
||||
|
@ -60,6 +62,8 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
|
|||
private SubscriptionChannelFactory mySubscriptionChannelFactory;
|
||||
@Autowired
|
||||
private DaoConfig myDaoConfig;
|
||||
@Autowired
|
||||
private IRequestPartitionHelperSvc myRequestPartitionHelperSvc;
|
||||
|
||||
private volatile MessageChannel myMatchingChannel;
|
||||
|
||||
|
@ -114,7 +118,9 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
|
|||
*/
|
||||
@Override
|
||||
public void submitResourceModified(IBaseResource theNewResource, ResourceModifiedMessage.OperationTypeEnum theOperationType, RequestDetails theRequest) {
|
||||
ResourceModifiedMessage msg = new ResourceModifiedMessage(myFhirContext, theNewResource, theOperationType, theRequest);
|
||||
// Even though the resource is being written, the subscription will be interacting with it by effectively "reading" it so we set the RequestPartitionId as a read request
|
||||
RequestPartitionId requestPartitionId = myRequestPartitionHelperSvc.determineReadPartitionForRequestForRead(theRequest, theNewResource.getIdElement().getResourceType(), theNewResource.getIdElement());
|
||||
ResourceModifiedMessage msg = new ResourceModifiedMessage(myFhirContext, theNewResource, theOperationType, theRequest, requestPartitionId);
|
||||
|
||||
// Interceptor call: SUBSCRIPTION_RESOURCE_MODIFIED
|
||||
HookParams params = new HookParams()
|
||||
|
|
|
@ -30,6 +30,7 @@ import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc;
|
|||
import ca.uhn.fhir.jpa.model.sched.HapiJob;
|
||||
import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
|
||||
import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition;
|
||||
import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
|
||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.subscription.match.matcher.matching.IResourceModifiedConsumer;
|
||||
|
@ -114,7 +115,7 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
|
|||
if (!subscriptionId.hasResourceType()) {
|
||||
subscriptionId = subscriptionId.withResourceType(ResourceTypeEnum.SUBSCRIPTION.getCode());
|
||||
}
|
||||
subscriptionDao.read(subscriptionId);
|
||||
subscriptionDao.read(subscriptionId, SystemRequestDetails.forAllPartition());
|
||||
}
|
||||
|
||||
List<IPrimitiveType<String>> resourceIds = ObjectUtils.defaultIfNull(theResourceIds, Collections.emptyList());
|
||||
|
@ -298,7 +299,7 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
|
|||
private Future<Void> submitResource(String theSubscriptionId, String theResourceIdToTrigger) {
|
||||
org.hl7.fhir.r4.model.IdType resourceId = new org.hl7.fhir.r4.model.IdType(theResourceIdToTrigger);
|
||||
IFhirResourceDao dao = myDaoRegistry.getResourceDao(resourceId.getResourceType());
|
||||
IBaseResource resourceToTrigger = dao.read(resourceId);
|
||||
IBaseResource resourceToTrigger = dao.read(resourceId, SystemRequestDetails.forAllPartition());
|
||||
|
||||
return submitResource(theSubscriptionId, resourceToTrigger);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.subscription.match.deliver;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.subscription.match.deliver.resthook.SubscriptionDeliveringRestHookSubscriber;
|
||||
import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionRegistry;
|
||||
import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
|
||||
|
@ -13,19 +14,28 @@ import ca.uhn.fhir.rest.api.EncodingEnum;
|
|||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.eq;
|
||||
|
@ -35,9 +45,10 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class BaseSubscriptionDeliverySubscriberTest {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(BaseSubscriptionDeliverySubscriberTest.class);
|
||||
|
||||
private SubscriptionDeliveringRestHookSubscriber mySubscriber;
|
||||
private FhirContext myCtx = FhirContext.forR4();
|
||||
private final FhirContext myCtx = FhirContext.forR4();
|
||||
|
||||
@Mock
|
||||
private IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||
|
@ -79,13 +90,9 @@ public class BaseSubscriptionDeliverySubscriberTest {
|
|||
public void testRestHookDeliverySuccessful() {
|
||||
when(myInterceptorBroadcaster.callHooks(any(), any())).thenReturn(true);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setActive(true);
|
||||
Patient patient = generatePatient();
|
||||
|
||||
CanonicalSubscription subscription = new CanonicalSubscription();
|
||||
subscription.setIdElement(new IdType("Subscription/123"));
|
||||
subscription.setEndpointUrl("http://example.com/fhir");
|
||||
subscription.setPayloadString("application/fhir+json");
|
||||
CanonicalSubscription subscription = generateSubscription();
|
||||
|
||||
ResourceDeliveryMessage payload = new ResourceDeliveryMessage();
|
||||
payload.setSubscription(subscription);
|
||||
|
@ -101,13 +108,9 @@ public class BaseSubscriptionDeliverySubscriberTest {
|
|||
public void testRestHookDeliveryFails_ShouldRollBack() {
|
||||
when(myInterceptorBroadcaster.callHooks(any(), any())).thenReturn(true);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setActive(true);
|
||||
Patient patient = generatePatient();
|
||||
|
||||
CanonicalSubscription subscription = new CanonicalSubscription();
|
||||
subscription.setIdElement(new IdType("Subscription/123"));
|
||||
subscription.setEndpointUrl("http://example.com/fhir");
|
||||
subscription.setPayloadString("application/fhir+json");
|
||||
CanonicalSubscription subscription = generateSubscription();
|
||||
|
||||
ResourceDeliveryMessage payload = new ResourceDeliveryMessage();
|
||||
payload.setSubscription(subscription);
|
||||
|
@ -132,13 +135,9 @@ public class BaseSubscriptionDeliverySubscriberTest {
|
|||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.SUBSCRIPTION_BEFORE_REST_HOOK_DELIVERY), any())).thenReturn(true);
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.SUBSCRIPTION_AFTER_DELIVERY_FAILED), any())).thenReturn(false);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setActive(true);
|
||||
Patient patient = generatePatient();
|
||||
|
||||
CanonicalSubscription subscription = new CanonicalSubscription();
|
||||
subscription.setIdElement(new IdType("Subscription/123"));
|
||||
subscription.setEndpointUrl("http://example.com/fhir");
|
||||
subscription.setPayloadString("application/fhir+json");
|
||||
CanonicalSubscription subscription = generateSubscription();
|
||||
|
||||
ResourceDeliveryMessage payload = new ResourceDeliveryMessage();
|
||||
payload.setSubscription(subscription);
|
||||
|
@ -158,13 +157,9 @@ public class BaseSubscriptionDeliverySubscriberTest {
|
|||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.SUBSCRIPTION_BEFORE_DELIVERY), any())).thenReturn(true);
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.SUBSCRIPTION_BEFORE_REST_HOOK_DELIVERY), any())).thenReturn(false);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setActive(true);
|
||||
Patient patient = generatePatient();
|
||||
|
||||
CanonicalSubscription subscription = new CanonicalSubscription();
|
||||
subscription.setIdElement(new IdType("Subscription/123"));
|
||||
subscription.setEndpointUrl("http://example.com/fhir");
|
||||
subscription.setPayloadString("application/fhir+json");
|
||||
CanonicalSubscription subscription = generateSubscription();
|
||||
|
||||
ResourceDeliveryMessage payload = new ResourceDeliveryMessage();
|
||||
payload.setSubscription(subscription);
|
||||
|
@ -181,4 +176,77 @@ public class BaseSubscriptionDeliverySubscriberTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializeDeliveryMessageWithRequestPartition() throws JsonProcessingException {
|
||||
CanonicalSubscription subscription = generateSubscription();
|
||||
Patient patient = generatePatient();
|
||||
|
||||
ResourceDeliveryMessage message = new ResourceDeliveryMessage();
|
||||
message.setPartitionId(RequestPartitionId.fromPartitionId(123, LocalDate.of(2020, 1, 1)));
|
||||
message.setSubscription(subscription);
|
||||
message.setPayload(myCtx, patient, EncodingEnum.JSON);
|
||||
message.setOperationType(ResourceModifiedMessage.OperationTypeEnum.CREATE);
|
||||
|
||||
ResourceDeliveryJsonMessage jsonMessage = new ResourceDeliveryJsonMessage(message);
|
||||
String jsonString = jsonMessage.asJson();
|
||||
|
||||
ourLog.info(jsonString);
|
||||
|
||||
|
||||
|
||||
// Assert that the partitionID is being serialized in JSON
|
||||
assertThat(jsonString, containsString("\"partitionDate\":[2020,1,1]"));
|
||||
assertThat(jsonString, containsString("\"partitionIds\":[123]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializeDeliveryMessageWithNoPartition() throws JsonProcessingException {
|
||||
CanonicalSubscription subscription = generateSubscription();
|
||||
Patient patient = generatePatient();
|
||||
|
||||
ResourceDeliveryMessage message = new ResourceDeliveryMessage();
|
||||
message.setSubscription(subscription);
|
||||
message.setPayload(myCtx, patient, EncodingEnum.JSON);
|
||||
message.setOperationType(ResourceModifiedMessage.OperationTypeEnum.CREATE);
|
||||
|
||||
ResourceDeliveryJsonMessage jsonMessage = new ResourceDeliveryJsonMessage(message);
|
||||
String jsonString = jsonMessage.asJson();
|
||||
|
||||
ourLog.info(jsonString);
|
||||
|
||||
assertThat(jsonString, containsString("\"operationType\":\"CREATE"));
|
||||
assertThat(jsonString, containsString("\"canonicalSubscription\":"));
|
||||
|
||||
// Assert that the default partitionID is being generated and is being serialized in JSON
|
||||
assertThat(jsonString, containsString("\"allPartitions\":false"));
|
||||
assertThat(jsonString, containsString("\"partitionIds\":[null]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializeLegacyDeliveryMessage() throws JsonProcessingException {
|
||||
String legacyDeliveryMessageJson = "{\"headers\":{\"retryCount\":0,\"customHeaders\":{}},\"payload\":{\"operationType\":\"CREATE\",\"canonicalSubscription\":{\"id\":\"Subscription/123\",\"endpointUrl\":\"http://example.com/fhir\",\"payload\":\"application/fhir+json\"},\"payload\":\"{\\\"resourceType\\\":\\\"Patient\\\",\\\"active\\\":true}\"}}";
|
||||
|
||||
ResourceDeliveryJsonMessage jsonMessage = ResourceDeliveryJsonMessage.fromJson(legacyDeliveryMessageJson);
|
||||
|
||||
ourLog.info(jsonMessage.getPayload().getRequestPartitionId().asJson());
|
||||
|
||||
assertNotNull(jsonMessage.getPayload().getRequestPartitionId());
|
||||
assertEquals(jsonMessage.getPayload().getRequestPartitionId().toJson(), RequestPartitionId.defaultPartition().toJson());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Patient generatePatient() {
|
||||
Patient patient = new Patient();
|
||||
patient.setActive(true);
|
||||
return patient;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private CanonicalSubscription generateSubscription() {
|
||||
CanonicalSubscription subscription = new CanonicalSubscription();
|
||||
subscription.setIdElement(new IdType("Subscription/123"));
|
||||
subscription.setEndpointUrl("http://example.com/fhir");
|
||||
subscription.setPayloadString("application/fhir+json");
|
||||
return subscription;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package ca.uhn.fhir.jpa.subscription.module;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
|
||||
import org.hl7.fhir.r4.model.Organization;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
|
@ -22,6 +25,7 @@ public class ResourceModifiedTest {
|
|||
Organization decodedOrg = (Organization) msg.getNewPayload(myFhirContext);
|
||||
assertEquals(org.getId(), decodedOrg.getId());
|
||||
assertEquals(org.getName(), decodedOrg.getName());
|
||||
assertEquals(msg.getPartitionId().toJson(), RequestPartitionId.defaultPartition().toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -35,6 +39,7 @@ public class ResourceModifiedTest {
|
|||
Organization decodedOrg = (Organization) msg.getNewPayload(myFhirContext);
|
||||
assertEquals(org.getId(), decodedOrg.getId());
|
||||
assertEquals(org.getName(), decodedOrg.getName());
|
||||
assertEquals(msg.getPartitionId().toJson(), RequestPartitionId.defaultPartition().toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -46,6 +51,19 @@ public class ResourceModifiedTest {
|
|||
assertEquals("Organization/testOrgId", msg.getPayloadId(myFhirContext).getValue());
|
||||
assertEquals(ResourceModifiedMessage.OperationTypeEnum.DELETE, msg.getOperationType());
|
||||
assertNull(msg.getNewPayload(myFhirContext));
|
||||
assertEquals(msg.getPartitionId().toJson(), RequestPartitionId.defaultPartition().toJson());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWithPartition() {
|
||||
Organization org = new Organization();
|
||||
org.setName("testOrgName");
|
||||
org.setId("Organization/testOrgId");
|
||||
ResourceModifiedMessage msg = new ResourceModifiedMessage(myFhirContext, org, ResourceModifiedMessage.OperationTypeEnum.CREATE);
|
||||
msg.setPartitionId(RequestPartitionId.fromPartitionId(123, LocalDate.of(2020, 1, 1)));
|
||||
|
||||
assertEquals(msg.getPartitionId().getPartitionIds().size(), 1);
|
||||
assertEquals(msg.getPartitionId().getPartitionIds().get(0), 123);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,11 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.api.ChannelConsumerSettings;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.subscription.ISubscriptionDeliveryChannelNamer;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
|
||||
|
@ -40,6 +45,7 @@ import org.junit.jupiter.api.AfterAll;
|
|||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.mockito.Mockito;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -59,9 +65,11 @@ public abstract class BaseBlockingQueueSubscribableChannelDstu3Test extends Base
|
|||
|
||||
@Autowired
|
||||
FhirContext myFhirContext;
|
||||
@Autowired
|
||||
protected DaoRegistry myDaoRegistry;
|
||||
|
||||
// Caused by: java.lang.IllegalStateException: Unable to register mock bean org.springframework.messaging.MessageHandler expected a single matching bean to replace but found [subscriptionActivatingSubscriber, subscriptionDeliveringEmailSubscriber, subscriptionDeliveringRestHookSubscriber, subscriptionMatchingSubscriber, subscriptionRegisteringSubscriber]
|
||||
|
||||
|
||||
@Autowired
|
||||
@Qualifier("subscriptionActivatingSubscriber")
|
||||
MessageHandler mySubscriptionActivatingSubscriber;
|
||||
|
@ -82,6 +90,8 @@ public abstract class BaseBlockingQueueSubscribableChannelDstu3Test extends Base
|
|||
private SubscriptionLoader mySubscriptionLoader;
|
||||
@Autowired
|
||||
private ISubscriptionDeliveryChannelNamer mySubscriptionDeliveryChannelNamer;
|
||||
@Autowired
|
||||
protected PartitionSettings myPartitionSettings;
|
||||
|
||||
protected String myCode = "1000000050";
|
||||
|
||||
|
@ -96,6 +106,8 @@ public abstract class BaseBlockingQueueSubscribableChannelDstu3Test extends Base
|
|||
protected final PointcutLatch mySubscriptionMatchingPost = new PointcutLatch(Pointcut.SUBSCRIPTION_AFTER_PERSISTED_RESOURCE_CHECKED);
|
||||
protected final PointcutLatch mySubscriptionActivatedPost = new PointcutLatch(Pointcut.SUBSCRIPTION_AFTER_ACTIVE_SUBSCRIPTION_REGISTERED);
|
||||
protected final PointcutLatch mySubscriptionAfterDelivery = new PointcutLatch(Pointcut.SUBSCRIPTION_AFTER_DELIVERY);
|
||||
protected final PointcutLatch mySubscriptionResourceMatched = new PointcutLatch(Pointcut.SUBSCRIPTION_RESOURCE_MATCHED);
|
||||
protected final PointcutLatch mySubscriptionResourceNotMatched = new PointcutLatch(Pointcut.SUBSCRIPTION_RESOURCE_DID_NOT_MATCH_ANY_SUBSCRIPTIONS);
|
||||
|
||||
@BeforeEach
|
||||
public void beforeReset() {
|
||||
|
@ -113,10 +125,13 @@ public abstract class BaseBlockingQueueSubscribableChannelDstu3Test extends Base
|
|||
myInterceptorRegistry.registerAnonymousInterceptor(Pointcut.SUBSCRIPTION_AFTER_PERSISTED_RESOURCE_CHECKED, mySubscriptionMatchingPost);
|
||||
myInterceptorRegistry.registerAnonymousInterceptor(Pointcut.SUBSCRIPTION_AFTER_ACTIVE_SUBSCRIPTION_REGISTERED, mySubscriptionActivatedPost);
|
||||
myInterceptorRegistry.registerAnonymousInterceptor(Pointcut.SUBSCRIPTION_AFTER_DELIVERY, mySubscriptionAfterDelivery);
|
||||
myInterceptorRegistry.registerAnonymousInterceptor(Pointcut.SUBSCRIPTION_RESOURCE_MATCHED, mySubscriptionResourceMatched);
|
||||
myInterceptorRegistry.registerAnonymousInterceptor(Pointcut.SUBSCRIPTION_RESOURCE_DID_NOT_MATCH_ANY_SUBSCRIPTIONS, mySubscriptionResourceNotMatched);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void cleanup() {
|
||||
myPartitionSettings.setPartitioningEnabled(false);
|
||||
myInterceptorRegistry.unregisterAllInterceptors();
|
||||
mySubscriptionMatchingPost.clear();
|
||||
mySubscriptionActivatedPost.clear();
|
||||
|
@ -125,7 +140,11 @@ public abstract class BaseBlockingQueueSubscribableChannelDstu3Test extends Base
|
|||
}
|
||||
|
||||
public <T extends IBaseResource> T sendResource(T theResource) throws InterruptedException {
|
||||
ResourceModifiedMessage msg = new ResourceModifiedMessage(myFhirContext, theResource, ResourceModifiedMessage.OperationTypeEnum.CREATE);
|
||||
return sendResource(theResource, null);
|
||||
}
|
||||
|
||||
public <T extends IBaseResource> T sendResource(T theResource, RequestPartitionId theRequestPartitionId) throws InterruptedException {
|
||||
ResourceModifiedMessage msg = new ResourceModifiedMessage(myFhirContext, theResource, ResourceModifiedMessage.OperationTypeEnum.CREATE, null, theRequestPartitionId);
|
||||
ResourceModifiedJsonMessage message = new ResourceModifiedJsonMessage(msg);
|
||||
mySubscriptionMatchingPost.setExpectedCount(1);
|
||||
ourSubscribableChannel.send(message);
|
||||
|
@ -133,15 +152,18 @@ public abstract class BaseBlockingQueueSubscribableChannelDstu3Test extends Base
|
|||
return theResource;
|
||||
}
|
||||
|
||||
protected Subscription sendSubscription(String theCriteria, String thePayload, String theEndpoint) throws InterruptedException {
|
||||
Subscription subscription = makeActiveSubscription(theCriteria, thePayload, theEndpoint);
|
||||
protected Subscription sendSubscription(Subscription theSubscription, RequestPartitionId theRequestPartitionId, Boolean mockDao) throws InterruptedException {
|
||||
mySubscriptionActivatedPost.setExpectedCount(1);
|
||||
Subscription retval = sendResource(subscription);
|
||||
Subscription retVal = sendResource(theSubscription, theRequestPartitionId);
|
||||
mySubscriptionActivatedPost.awaitExpected();
|
||||
return retval;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected Observation sendObservation(String code, String system) throws InterruptedException {
|
||||
return sendObservation(code, system, null);
|
||||
}
|
||||
|
||||
protected Observation sendObservation(String code, String system, RequestPartitionId theRequestPartitionId) throws InterruptedException {
|
||||
Observation observation = new Observation();
|
||||
IdType id = new IdType("Observation", nextId());
|
||||
observation.setId(id);
|
||||
|
@ -154,7 +176,7 @@ public abstract class BaseBlockingQueueSubscribableChannelDstu3Test extends Base
|
|||
|
||||
observation.setStatus(Observation.ObservationStatus.FINAL);
|
||||
|
||||
return sendResource(observation);
|
||||
return sendResource(observation, theRequestPartitionId);
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
|
@ -224,6 +246,8 @@ public abstract class BaseBlockingQueueSubscribableChannelDstu3Test extends Base
|
|||
}
|
||||
|
||||
@Override
|
||||
public void clear() { updateLatch.clear();}
|
||||
public void clear() {
|
||||
updateLatch.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.hl7.fhir.dstu3.model.CodeableConcept;
|
|||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
import org.hl7.fhir.dstu3.model.Observation;
|
||||
import org.hl7.fhir.dstu3.model.Subscription;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -26,8 +27,10 @@ public class SubscriptionCheckingSubscriberTest extends BaseBlockingQueueSubscri
|
|||
String criteria1 = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
String criteria2 = "Observation?code=SNOMED-CT|" + code + "111&_format=xml";
|
||||
|
||||
sendSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(criteria2, payload, ourListenerServerBase);
|
||||
Subscription subscription1 = makeActiveSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription1, null, false);
|
||||
Subscription subscription2 = makeActiveSubscription(criteria2, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription2, null, false);
|
||||
|
||||
assertEquals(2, mySubscriptionRegistry.size());
|
||||
|
||||
|
@ -47,8 +50,10 @@ public class SubscriptionCheckingSubscriberTest extends BaseBlockingQueueSubscri
|
|||
String criteria1 = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
String criteria2 = "Observation?code=SNOMED-CT|" + code + "111&_format=xml";
|
||||
|
||||
sendSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(criteria2, payload, ourListenerServerBase);
|
||||
Subscription subscription1 = makeActiveSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription1, null, false);
|
||||
Subscription subscription2 = makeActiveSubscription(criteria2, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription2, null, false);
|
||||
|
||||
assertEquals(2, mySubscriptionRegistry.size());
|
||||
|
||||
|
@ -68,8 +73,10 @@ public class SubscriptionCheckingSubscriberTest extends BaseBlockingQueueSubscri
|
|||
String criteria1 = "Observation?code=SNOMED-CT|" + code;
|
||||
String criteria2 = "Observation?code=SNOMED-CT|" + code + "111";
|
||||
|
||||
sendSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(criteria2, payload, ourListenerServerBase);
|
||||
Subscription subscription1 = makeActiveSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription1, null, false);
|
||||
Subscription subscription2 = makeActiveSubscription(criteria2, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription2, null, false);
|
||||
|
||||
assertEquals(2, mySubscriptionRegistry.size());
|
||||
|
||||
|
@ -90,8 +97,10 @@ public class SubscriptionCheckingSubscriberTest extends BaseBlockingQueueSubscri
|
|||
String criteria1 = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
String criteria2 = "Observation?code=SNOMED-CT|" + code + "111&_format=xml";
|
||||
|
||||
sendSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(criteria2, payload, ourListenerServerBase);
|
||||
Subscription subscription1 = makeActiveSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription1, null, false);
|
||||
Subscription subscription2 = makeActiveSubscription(criteria2, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription2, null, false);
|
||||
|
||||
assertEquals(2, mySubscriptionRegistry.size());
|
||||
|
||||
|
|
|
@ -1,19 +1,37 @@
|
|||
package ca.uhn.fhir.jpa.subscription.module.subscriber;
|
||||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.subscription.module.standalone.BaseBlockingQueueSubscribableChannelDstu3Test;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.hl7.fhir.dstu3.model.Observation;
|
||||
import org.hl7.fhir.dstu3.model.Subscription;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
|
||||
/**
|
||||
* Tests copied from jpa.subscription.resthook.RestHookTestDstu3Test
|
||||
*/
|
||||
public class SubscriptionMatchingSubscriberTest extends BaseBlockingQueueSubscribableChannelDstu3Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionMatchingSubscriberTest.class);
|
||||
private final IFhirResourceDao<Subscription> myMockSubscriptionDao = Mockito.mock(IFhirResourceDao.class);
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEach() {
|
||||
Mockito.when(myMockSubscriptionDao.getResourceType()).thenReturn(Subscription.class);
|
||||
myDaoRegistry.register(myMockSubscriptionDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestHookSubscriptionApplicationFhirJson() throws Exception {
|
||||
|
@ -23,8 +41,10 @@ public class SubscriptionMatchingSubscriberTest extends BaseBlockingQueueSubscri
|
|||
String criteria1 = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
String criteria2 = "Observation?code=SNOMED-CT|" + code + "111&_format=xml";
|
||||
|
||||
sendSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(criteria2, payload, ourListenerServerBase);
|
||||
Subscription subscription1 = makeActiveSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription1, null, false);
|
||||
Subscription subscription2 = makeActiveSubscription(criteria2, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription2, null, false);
|
||||
|
||||
assertEquals(2, mySubscriptionRegistry.size());
|
||||
|
||||
|
@ -44,8 +64,10 @@ public class SubscriptionMatchingSubscriberTest extends BaseBlockingQueueSubscri
|
|||
String criteria1 = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
String criteria2 = "Observation?code=SNOMED-CT|" + code + "111&_format=xml";
|
||||
|
||||
sendSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(criteria2, payload, ourListenerServerBase);
|
||||
Subscription subscription1 = makeActiveSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription1, null, false);
|
||||
Subscription subscription2 = makeActiveSubscription(criteria2, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription2, null, false);
|
||||
|
||||
assertEquals(2, mySubscriptionRegistry.size());
|
||||
|
||||
|
@ -59,16 +81,16 @@ public class SubscriptionMatchingSubscriberTest extends BaseBlockingQueueSubscri
|
|||
|
||||
@Test
|
||||
public void testRestHookSubscription_NoResourceTypeInPayloadId() throws Exception {
|
||||
sendSubscription("Observation?", "application/fhir+xml", ourListenerServerBase);
|
||||
|
||||
assertEquals(1, mySubscriptionRegistry.size());
|
||||
ourObservationListener.setExpectedCount(1);
|
||||
|
||||
Observation observation = new Observation();
|
||||
observation.setId("OBS");
|
||||
observation.setStatus(Observation.ObservationStatus.CORRECTED);
|
||||
sendResource(observation);
|
||||
|
||||
Subscription subscription = makeActiveSubscription("Observation?", "application/fhir+xml", ourListenerServerBase);
|
||||
sendSubscription(subscription, null, false);
|
||||
|
||||
assertEquals(1, mySubscriptionRegistry.size());
|
||||
ourObservationListener.setExpectedCount(1);
|
||||
sendResource(observation);
|
||||
ourObservationListener.awaitExpected();
|
||||
|
||||
assertEquals(1, ourContentTypes.size());
|
||||
|
@ -83,8 +105,10 @@ public class SubscriptionMatchingSubscriberTest extends BaseBlockingQueueSubscri
|
|||
String criteria1 = "Observation?code=SNOMED-CT|" + code;
|
||||
String criteria2 = "Observation?code=SNOMED-CT|" + code + "111";
|
||||
|
||||
sendSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(criteria2, payload, ourListenerServerBase);
|
||||
Subscription subscription1 = makeActiveSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription1, null, false);
|
||||
Subscription subscription2 = makeActiveSubscription(criteria2, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription2, null, false);
|
||||
|
||||
assertEquals(2, mySubscriptionRegistry.size());
|
||||
|
||||
|
@ -107,9 +131,12 @@ public class SubscriptionMatchingSubscriberTest extends BaseBlockingQueueSubscri
|
|||
String criteria2 = "[*]";
|
||||
String criteria3 = "Observation?code=FOO"; // won't match
|
||||
|
||||
sendSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(criteria2, payload, ourListenerServerBase);
|
||||
sendSubscription(criteria3, payload, ourListenerServerBase);
|
||||
Subscription subscription1 = makeActiveSubscription(criteria1, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription1, null, false);
|
||||
Subscription subscription2 = makeActiveSubscription(criteria2, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription2, null, false);
|
||||
Subscription subscription3 = makeActiveSubscription(criteria3, payload, ourListenerServerBase);
|
||||
sendSubscription(subscription3, null, false);
|
||||
|
||||
assertEquals(3, mySubscriptionRegistry.size());
|
||||
|
||||
|
@ -121,5 +148,127 @@ public class SubscriptionMatchingSubscriberTest extends BaseBlockingQueueSubscri
|
|||
assertEquals(Constants.CT_FHIR_XML_NEW, ourContentTypes.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionAndResourceOnTheSamePartitionMatch() throws InterruptedException {
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
String payload = "application/fhir+json";
|
||||
|
||||
String code = "1000000050";
|
||||
String criteria = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
|
||||
RequestPartitionId requestPartitionId = RequestPartitionId.fromPartitionId(0);
|
||||
Subscription subscription = makeActiveSubscription(criteria, payload, ourListenerServerBase);
|
||||
mockSubscriptionRead(requestPartitionId, subscription);
|
||||
sendSubscription(subscription, requestPartitionId, true);
|
||||
|
||||
ourObservationListener.setExpectedCount(1);
|
||||
mySubscriptionResourceMatched.setExpectedCount(1);
|
||||
sendObservation(code, "SNOMED-CT", requestPartitionId);
|
||||
mySubscriptionResourceMatched.awaitExpected();
|
||||
ourObservationListener.awaitExpected();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionAndResourceOnTheSamePartitionMatchPart2() throws InterruptedException {
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
String payload = "application/fhir+json";
|
||||
|
||||
String code = "1000000050";
|
||||
String criteria = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
|
||||
RequestPartitionId requestPartitionId = RequestPartitionId.fromPartitionId(1);
|
||||
Subscription subscription = makeActiveSubscription(criteria, payload, ourListenerServerBase);
|
||||
mockSubscriptionRead(requestPartitionId, subscription);
|
||||
sendSubscription(subscription, requestPartitionId, true);
|
||||
|
||||
ourObservationListener.setExpectedCount(1);
|
||||
mySubscriptionResourceMatched.setExpectedCount(1);
|
||||
sendObservation(code, "SNOMED-CT", requestPartitionId);
|
||||
mySubscriptionResourceMatched.awaitExpected();
|
||||
ourObservationListener.awaitExpected();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionAndResourceOnDiffPartitionNotMatch() throws InterruptedException {
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
String payload = "application/fhir+json";
|
||||
|
||||
String code = "1000000050";
|
||||
String criteria = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
|
||||
RequestPartitionId requestPartitionId = RequestPartitionId.fromPartitionId(1);
|
||||
Subscription subscription = makeActiveSubscription(criteria, payload, ourListenerServerBase);
|
||||
mockSubscriptionRead(requestPartitionId, subscription);
|
||||
sendSubscription(subscription, requestPartitionId, true);
|
||||
|
||||
mySubscriptionResourceNotMatched.setExpectedCount(1);
|
||||
sendObservation(code, "SNOMED-CT", RequestPartitionId.fromPartitionId(0));
|
||||
mySubscriptionResourceNotMatched.awaitExpected();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionAndResourceOnDiffPartitionNotMatchPart2() throws InterruptedException {
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
String payload = "application/fhir+json";
|
||||
|
||||
String code = "1000000050";
|
||||
String criteria = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
|
||||
RequestPartitionId requestPartitionId = RequestPartitionId.fromPartitionId(0);
|
||||
Subscription subscription = makeActiveSubscription(criteria, payload, ourListenerServerBase);
|
||||
mockSubscriptionRead(requestPartitionId, subscription);
|
||||
sendSubscription(subscription, requestPartitionId, true);
|
||||
|
||||
mySubscriptionResourceNotMatched.setExpectedCount(1);
|
||||
sendObservation(code, "SNOMED-CT", RequestPartitionId.fromPartitionId(1));
|
||||
mySubscriptionResourceNotMatched.awaitExpected();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionOnOnePartitionMatchResourceOnMultiplePartitions() throws InterruptedException {
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
String payload = "application/fhir+json";
|
||||
|
||||
String code = "1000000050";
|
||||
String criteria = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
|
||||
RequestPartitionId requestPartitionId = RequestPartitionId.fromPartitionId(1);
|
||||
Subscription subscription = makeActiveSubscription(criteria, payload, ourListenerServerBase);
|
||||
mockSubscriptionRead(requestPartitionId, subscription);
|
||||
sendSubscription(subscription, requestPartitionId, true);
|
||||
|
||||
ourObservationListener.setExpectedCount(1);
|
||||
mySubscriptionResourceMatched.setExpectedCount(1);
|
||||
List<Integer> partitionId = Collections.synchronizedList(Lists.newArrayList(0, 1, 2));
|
||||
sendObservation(code, "SNOMED-CT", RequestPartitionId.fromPartitionIds(partitionId));
|
||||
mySubscriptionResourceMatched.awaitExpected();
|
||||
ourObservationListener.awaitExpected();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionOnOnePartitionDoNotMatchResourceOnMultiplePartitions() throws InterruptedException {
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
String payload = "application/fhir+json";
|
||||
|
||||
String code = "1000000050";
|
||||
String criteria = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
|
||||
|
||||
RequestPartitionId requestPartitionId = RequestPartitionId.fromPartitionId(1);
|
||||
Subscription subscription = makeActiveSubscription(criteria, payload, ourListenerServerBase);
|
||||
mockSubscriptionRead(requestPartitionId, subscription);
|
||||
sendSubscription(subscription, requestPartitionId, true);
|
||||
|
||||
mySubscriptionResourceNotMatched.setExpectedCount(1);
|
||||
List<Integer> partitionId = Collections.synchronizedList(Lists.newArrayList(0, 2));
|
||||
sendObservation(code, "SNOMED-CT", RequestPartitionId.fromPartitionIds(partitionId));
|
||||
mySubscriptionResourceNotMatched.awaitExpected();
|
||||
}
|
||||
|
||||
|
||||
private void mockSubscriptionRead(RequestPartitionId theRequestPartitionId, Subscription subscription) {
|
||||
Subscription modifiedSubscription = subscription.copy();
|
||||
// the original partition info was the request info, but we need the actual storage partition.
|
||||
modifiedSubscription.setUserData(Constants.RESOURCE_PARTITION_ID, theRequestPartitionId);
|
||||
Mockito.when(myMockSubscriptionDao.read(eq(subscription.getIdElement()), any())).thenReturn(modifiedSubscription);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import ca.uhn.fhir.jpa.cache.IResourceVersionSvc;
|
|||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
|
||||
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
|
||||
import ca.uhn.fhir.jpa.searchparam.config.SearchParamConfig;
|
||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
|
||||
|
@ -53,6 +54,8 @@ public class SubscriptionSubmitInterceptorLoaderTest {
|
|||
private SubscriptionMatcherInterceptor mySubscriptionMatcherInterceptor;
|
||||
@MockBean
|
||||
private IResourceVersionSvc myResourceVersionSvc;
|
||||
@MockBean
|
||||
private IRequestPartitionHelperSvc myRequestPartitionHelperSvc;
|
||||
|
||||
/**
|
||||
* It should be possible to run only the {@link SubscriptionSubmitterConfig} without the
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -57,6 +57,10 @@ public class SystemRequestDetails extends RequestDetails {
|
|||
super(new MyInterceptorBroadcaster());
|
||||
}
|
||||
|
||||
public static SystemRequestDetails forAllPartition(){
|
||||
return new SystemRequestDetails().setRequestPartitionId(RequestPartitionId.allPartitions());
|
||||
}
|
||||
|
||||
private ListMultimap<String, String> myHeaders;
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,15 +22,15 @@ package ca.uhn.fhir.jpa.subscription.match.registry;
|
|||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.subscription.match.matcher.matching.SubscriptionMatchingStrategy;
|
||||
import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
|
||||
import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscriptionChannelType;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Subscription;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.util.HapiExtensions;
|
||||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
|
@ -46,7 +46,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -124,6 +123,7 @@ public class SubscriptionCanonicalizer {
|
|||
if (status != null) {
|
||||
retVal.setStatus(org.hl7.fhir.r4.model.Subscription.SubscriptionStatus.fromCode(status.toCode()));
|
||||
}
|
||||
setPartitionIdOnReturnValue(theSubscription, retVal);
|
||||
retVal.setChannelType(getChannelType(theSubscription));
|
||||
retVal.setCriteriaString(subscription.getCriteria());
|
||||
retVal.setEndpointUrl(subscription.getChannel().getEndpoint());
|
||||
|
@ -232,6 +232,7 @@ public class SubscriptionCanonicalizer {
|
|||
retVal.setPayloadString(subscription.getChannel().getPayload());
|
||||
retVal.setPayloadSearchCriteria(getExtensionString(subscription, HapiExtensions.EXT_SUBSCRIPTION_PAYLOAD_SEARCH_CRITERIA));
|
||||
retVal.setTags(extractTags(subscription));
|
||||
setPartitionIdOnReturnValue(theSubscription, retVal);
|
||||
|
||||
if (retVal.getChannelType() == CanonicalSubscriptionChannelType.EMAIL) {
|
||||
String from;
|
||||
|
@ -278,6 +279,7 @@ public class SubscriptionCanonicalizer {
|
|||
if (status != null) {
|
||||
retVal.setStatus(org.hl7.fhir.r4.model.Subscription.SubscriptionStatus.fromCode(status.toCode()));
|
||||
}
|
||||
setPartitionIdOnReturnValue(theSubscription, retVal);
|
||||
retVal.setChannelType(getChannelType(subscription));
|
||||
retVal.setCriteriaString(getCriteria(theSubscription));
|
||||
retVal.setEndpointUrl(subscription.getEndpoint());
|
||||
|
@ -325,6 +327,13 @@ public class SubscriptionCanonicalizer {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private void setPartitionIdOnReturnValue(IBaseResource theSubscription, CanonicalSubscription retVal) {
|
||||
RequestPartitionId requestPartitionId = (RequestPartitionId) theSubscription.getUserData(Constants.RESOURCE_PARTITION_ID);
|
||||
if (requestPartitionId != null) {
|
||||
retVal.setPartitionId(requestPartitionId.getFirstPartitionIdOrNull());
|
||||
}
|
||||
}
|
||||
|
||||
private String getExtensionString(IBaseHasExtensions theBase, String theUrl) {
|
||||
return theBase
|
||||
.getExtension()
|
||||
|
|
|
@ -43,7 +43,6 @@ import java.util.Map;
|
|||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class CanonicalSubscription implements Serializable, Cloneable, IModelJson {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonProperty("id")
|
||||
|
@ -72,6 +71,8 @@ public class CanonicalSubscription implements Serializable, Cloneable, IModelJso
|
|||
private Map<String, String> myTags;
|
||||
@JsonProperty("payloadSearchCriteria")
|
||||
private String myPayloadSearchCriteria;
|
||||
@JsonProperty("partitionId")
|
||||
private Integer myPartitionId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -89,7 +90,7 @@ public class CanonicalSubscription implements Serializable, Cloneable, IModelJso
|
|||
}
|
||||
|
||||
/**
|
||||
* For now we're using the R4 TriggerDefinition, but this
|
||||
* For now, we're using the R4 TriggerDefinition, but this
|
||||
* may change in the future when things stabilize
|
||||
*/
|
||||
public void addTrigger(CanonicalEventDefinition theTrigger) {
|
||||
|
@ -159,9 +160,9 @@ public class CanonicalSubscription implements Serializable, Cloneable, IModelJso
|
|||
|
||||
public String getChannelExtension(String theUrl) {
|
||||
String retVal = null;
|
||||
List<String> strings = myChannelExtensions.get(theUrl);
|
||||
if (strings != null && strings.isEmpty() == false) {
|
||||
retVal = strings.get(0);
|
||||
List<String> channelExtensions = myChannelExtensions.get(theUrl);
|
||||
if (channelExtensions != null && !channelExtensions.isEmpty()) {
|
||||
retVal = channelExtensions.get(0);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
@ -227,8 +228,16 @@ public class CanonicalSubscription implements Serializable, Cloneable, IModelJso
|
|||
myStatus = theStatus;
|
||||
}
|
||||
|
||||
public Integer getRequestPartitionId() {
|
||||
return myPartitionId;
|
||||
}
|
||||
|
||||
public void setPartitionId(Integer thePartitionId) {
|
||||
myPartitionId = thePartitionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* For now we're using the R4 triggerdefinition, but this
|
||||
* For now, we're using the R4 triggerdefinition, but this
|
||||
* may change in the future when things stabilize
|
||||
*/
|
||||
public CanonicalEventDefinition getTrigger() {
|
||||
|
@ -325,7 +334,7 @@ public class CanonicalSubscription implements Serializable, Cloneable, IModelJso
|
|||
private String mySubjectTemplate;
|
||||
|
||||
/**
|
||||
* Construcor
|
||||
* Constructor
|
||||
*/
|
||||
public EmailDetails() {
|
||||
super();
|
||||
|
|
|
@ -22,9 +22,12 @@ package ca.uhn.fhir.jpa.subscription.model;
|
|||
|
||||
import ca.uhn.fhir.rest.server.messaging.json.BaseJsonMessage;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
public class ResourceDeliveryJsonMessage extends BaseJsonMessage<ResourceDeliveryMessage> {
|
||||
private static final ObjectMapper ourObjectMapper = new ObjectMapper().registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule());
|
||||
|
||||
@JsonProperty("payload")
|
||||
private ResourceDeliveryMessage myPayload;
|
||||
|
@ -58,4 +61,12 @@ public class ResourceDeliveryJsonMessage extends BaseJsonMessage<ResourceDeliver
|
|||
.append("myPayload", myPayload)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public static ResourceDeliveryJsonMessage fromJson(String theJson) throws JsonProcessingException {
|
||||
return ourObjectMapper.readValue(theJson, ResourceDeliveryJsonMessage.class);
|
||||
}
|
||||
|
||||
public String asJson() throws JsonProcessingException {
|
||||
return ourObjectMapper.writeValueAsString(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.subscription.model;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.messaging.BaseResourceMessage;
|
||||
|
@ -38,6 +39,8 @@ public class ResourceDeliveryMessage extends BaseResourceMessage implements IRes
|
|||
|
||||
@JsonProperty("canonicalSubscription")
|
||||
private CanonicalSubscription mySubscription;
|
||||
@JsonProperty("partitionId")
|
||||
private RequestPartitionId myPartitionId;
|
||||
@JsonProperty("payload")
|
||||
private String myPayloadString;
|
||||
@JsonProperty("payloadId")
|
||||
|
@ -50,6 +53,7 @@ public class ResourceDeliveryMessage extends BaseResourceMessage implements IRes
|
|||
*/
|
||||
public ResourceDeliveryMessage() {
|
||||
super();
|
||||
myPartitionId = RequestPartitionId.defaultPartition();
|
||||
}
|
||||
|
||||
public IBaseResource getPayload(FhirContext theCtx) {
|
||||
|
@ -110,6 +114,14 @@ public class ResourceDeliveryMessage extends BaseResourceMessage implements IRes
|
|||
}
|
||||
}
|
||||
|
||||
public RequestPartitionId getRequestPartitionId() {
|
||||
return myPartitionId;
|
||||
}
|
||||
|
||||
public void setPartitionId(RequestPartitionId thePartitionId) {
|
||||
myPartitionId = thePartitionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
|
@ -117,6 +129,7 @@ public class ResourceDeliveryMessage extends BaseResourceMessage implements IRes
|
|||
.append("myPayloadString", myPayloadString)
|
||||
.append("myPayload", myPayloadDecoded)
|
||||
.append("myPayloadId", myPayloadId)
|
||||
.append("myPartitionId", myPartitionId)
|
||||
.append("myOperationType", getOperationType())
|
||||
.toString();
|
||||
}
|
||||
|
|
|
@ -21,14 +21,13 @@ package ca.uhn.fhir.jpa.subscription.model;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.messaging.BaseResourceModifiedMessage;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Most of this class has been moved to ResourceModifiedMessage in the hapi-fhir-server project, for a reusable channel ResourceModifiedMessage
|
||||
* that doesn't require knowledge of subscriptions.
|
||||
|
@ -42,6 +41,8 @@ public class ResourceModifiedMessage extends BaseResourceModifiedMessage {
|
|||
@JsonProperty(value = "subscriptionId", required = false)
|
||||
private String mySubscriptionId;
|
||||
|
||||
@JsonProperty(value = "partitionId", required = false)
|
||||
private RequestPartitionId myPartitionId;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -53,10 +54,17 @@ public class ResourceModifiedMessage extends BaseResourceModifiedMessage {
|
|||
|
||||
public ResourceModifiedMessage(FhirContext theFhirContext, IBaseResource theResource, OperationTypeEnum theOperationType) {
|
||||
super(theFhirContext, theResource, theOperationType);
|
||||
myPartitionId = RequestPartitionId.defaultPartition();
|
||||
}
|
||||
|
||||
public ResourceModifiedMessage(FhirContext theFhirContext, IBaseResource theNewResource, OperationTypeEnum theOperationType, RequestDetails theRequest) {
|
||||
super(theFhirContext, theNewResource, theOperationType, theRequest);
|
||||
myPartitionId = RequestPartitionId.defaultPartition();
|
||||
}
|
||||
|
||||
public ResourceModifiedMessage(FhirContext theFhirContext, IBaseResource theNewResource, OperationTypeEnum theOperationType, RequestDetails theRequest, RequestPartitionId theRequestPartitionId) {
|
||||
super(theFhirContext, theNewResource, theOperationType, theRequest);
|
||||
myPartitionId = theRequestPartitionId;
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,6 +76,14 @@ public class ResourceModifiedMessage extends BaseResourceModifiedMessage {
|
|||
mySubscriptionId = theSubscriptionId;
|
||||
}
|
||||
|
||||
public RequestPartitionId getPartitionId() {
|
||||
return myPartitionId;
|
||||
}
|
||||
|
||||
public void setPartitionId(RequestPartitionId thePartitionId) {
|
||||
myPartitionId = thePartitionId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -75,6 +91,7 @@ public class ResourceModifiedMessage extends BaseResourceModifiedMessage {
|
|||
.append("operationType", myOperationType)
|
||||
.append("subscriptionId", mySubscriptionId)
|
||||
.append("payloadId", myPayloadId)
|
||||
.append("partitionId", myPartitionId)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -58,37 +58,37 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu3</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-r4</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-r5</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-r4</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -6,7 +6,7 @@
|
|||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<name>HAPI-FHIR</name>
|
||||
<description>An open-source implementation of the FHIR specification in Java.</description>
|
||||
<url>https://hapifhir.io</url>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.7.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.7.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
Loading…
Reference in New Issue