diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionsR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionsR4Test.java index fe28b223e84..b32f8696886 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionsR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionsR4Test.java @@ -7,13 +7,14 @@ import ca.uhn.fhir.jpa.subscription.channel.impl.LinkedBlockingChannel; import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionMatcherInterceptor; import ca.uhn.fhir.rest.annotation.Create; import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Transaction; import ca.uhn.fhir.rest.annotation.Update; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.server.IResourceProvider; import ca.uhn.fhir.rest.server.RestfulServer; -import ca.uhn.fhir.util.BundleUtil; import ca.uhn.fhir.test.utilities.JettyUtil; +import ca.uhn.fhir.util.BundleUtil; import com.google.common.collect.Lists; import net.ttddyy.dsproxy.QueryCount; import net.ttddyy.dsproxy.listener.SingleQueryCountHolder; @@ -22,9 +23,19 @@ import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; -import org.hl7.fhir.r4.model.*; -import org.junit.*; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.CodeableConcept; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Observation; +import org.hl7.fhir.r4.model.Subscription; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestParam; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; @@ -36,28 +47,23 @@ import java.util.List; @Ignore public abstract class BaseSubscriptionsR4Test extends BaseResourceProviderR4Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseSubscriptionsR4Test.class); - - private static Server ourListenerServer; - protected static int ourListenerPort; + protected static int ourListenerPort; protected static List ourContentTypes = Collections.synchronizedList(new ArrayList<>()); protected static List ourHeaders = Collections.synchronizedList(new ArrayList<>()); + protected static List ourTransactions = Collections.synchronizedList(Lists.newArrayList()); + protected static List ourCreatedObservations = Collections.synchronizedList(Lists.newArrayList()); + protected static List ourUpdatedObservations = Collections.synchronizedList(Lists.newArrayList()); + private static Server ourListenerServer; private static SingleQueryCountHolder ourCountHolder; - - @Autowired - private SingleQueryCountHolder myCountHolder; + private static String ourListenerServerBase; @Autowired protected SubscriptionTestUtil mySubscriptionTestUtil; @Autowired protected SubscriptionMatcherInterceptor mySubscriptionMatcherInterceptor; - protected CountingInterceptor myCountingInterceptor; - - protected static List ourCreatedObservations = Collections.synchronizedList(Lists.newArrayList()); - protected static List ourUpdatedObservations = Collections.synchronizedList(Lists.newArrayList()); - private static String ourListenerServerBase; - protected List mySubscriptionIds = Collections.synchronizedList(new ArrayList<>()); - + @Autowired + private SingleQueryCountHolder myCountHolder; @After public void afterUnregisterRestHookListener() { @@ -87,6 +93,7 @@ public abstract class BaseSubscriptionsR4Test extends BaseResourceProviderR4Test public void beforeReset() throws Exception { ourCreatedObservations.clear(); ourUpdatedObservations.clear(); + ourTransactions.clear(); ourContentTypes.clear(); ourHeaders.clear(); @@ -162,8 +169,7 @@ public abstract class BaseSubscriptionsR4Test extends BaseResourceProviderR4Test } - - public static class ObservationListener implements IResourceProvider { + public static class ObservationResourceProvider implements IResourceProvider { @Create public MethodOutcome create(@ResourceParam Observation theObservation, HttpServletRequest theRequest) { @@ -202,6 +208,16 @@ public abstract class BaseSubscriptionsR4Test extends BaseResourceProviderR4Test } + public static class PlainProvider { + + @Transaction + public Bundle transaction(@RequestParam Bundle theInput) { + ourTransactions.add(theInput); + return theInput; + } + + } + @AfterClass public static void reportTotalSelects() { ourLog.info("Total database select queries: {}", getQueryCount().getSelect()); @@ -214,9 +230,9 @@ public abstract class BaseSubscriptionsR4Test extends BaseResourceProviderR4Test @BeforeClass public static void startListenerServer() throws Exception { RestfulServer ourListenerRestServer = new RestfulServer(FhirContext.forR4()); - - ObservationListener obsListener = new ObservationListener(); - ourListenerRestServer.setResourceProviders(obsListener); + + ObservationResourceProvider observationResourceProvider = new ObservationResourceProvider(); + ourListenerRestServer.setResourceProviders(observationResourceProvider); ourListenerServer = new Server(0); @@ -229,8 +245,8 @@ public abstract class BaseSubscriptionsR4Test extends BaseResourceProviderR4Test ourListenerServer.setHandler(proxyHandler); JettyUtil.startServer(ourListenerServer); - ourListenerPort = JettyUtil.getPortForStartedServer(ourListenerServer); - ourListenerServerBase = "http://localhost:" + ourListenerPort + "/fhir/context"; + ourListenerPort = JettyUtil.getPortForStartedServer(ourListenerServer); + ourListenerServerBase = "http://localhost:" + ourListenerPort + "/fhir/context"; } @AfterClass diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestR4Test.java index 2f5e5fc32c2..3d64b37a81a 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestR4Test.java @@ -1013,4 +1013,30 @@ public class RestHookTestR4Test extends BaseSubscriptionsR4Test { } + @Test + public void testDeliverSearchSet() throws Exception { + { + Subscription subscription = newSubscription("Observation?", "application/json"); + subscription.addExtension(JpaConstants.EXT_SUBSCRIPTION_DELIVER_BUNDLE_SEARCH_RESULT, new StringType("Observation?_id=${resource_id}&_include=*")); + MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute(); + mySubscriptionIds.add(methodOutcome.getId()); + waitForActivatedSubscriptionCount(1); + } + + { + Patient patient = new Patient(); + patient.setActive(true); + IIdType patientId = ourClient.create().resource(patient).execute().getId(); + + Observation observation = new Observation(); + observation.addExtension().setUrl("Observation#accessType").setValue(new Coding().setCode("Catheter")); + observation.getSubject().setReferenceElement(patientId); + MethodOutcome methodOutcome = ourClient.create().resource(observation).execute(); + assertEquals(true, methodOutcome.getCreated()); + waitForQueueToDrain(); + waitForSize(1, ourTransactions); + } + + } + } diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java index 671e0fbfc1b..404b4a7e334 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java @@ -214,6 +214,10 @@ public class JpaConstants { * Extension ID for external binary references */ public static final String EXT_EXTERNALIZED_BINARY_ID = "http://hapifhir.io/fhir/StructureDefinition/externalized-binary-id"; + /** + * For subscription, deliver a bundle containinf a search result instead of just a single resource + */ + public static final String EXT_SUBSCRIPTION_DELIVER_BUNDLE_SEARCH_RESULT = "http://hapifhir.io/fhir/StructureDefinition/subscription-deliver-bundle-search-result"; /** * Placed in system-generated extensions */ diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/match/registry/SubscriptionCanonicalizer.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/match/registry/SubscriptionCanonicalizer.java index ea6b9b3ff52..0f60e299fa3 100644 --- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/match/registry/SubscriptionCanonicalizer.java +++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/match/registry/SubscriptionCanonicalizer.java @@ -261,6 +261,7 @@ public class SubscriptionCanonicalizer { retVal.setChannelExtensions(extractExtension(subscription)); retVal.setIdElement(subscription.getIdElement()); retVal.setPayloadString(subscription.getContentType()); + retVal.setDeliverBundleSearchResult(getExtensionString(subscription, JpaConstants.EXT_SUBSCRIPTION_DELIVER_BUNDLE_SEARCH_RESULT)); if (retVal.getChannelType() == CanonicalSubscriptionChannelType.EMAIL) { String from; diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/CanonicalSubscription.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/CanonicalSubscription.java index a8ba6d41f77..fcee7de1178 100644 --- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/CanonicalSubscription.java +++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/CanonicalSubscription.java @@ -64,6 +64,8 @@ public class CanonicalSubscription implements Serializable, Cloneable, IModelJso private RestHookDetails myRestHookDetails; @JsonProperty("extensions") private Map> myChannelExtensions; + @JsonProperty("deliverBundleSearchResult") + private String myDeliverBundleSearchResult; /** * Constructor @@ -276,7 +278,11 @@ public class CanonicalSubscription implements Serializable, Cloneable, IModelJso } } - public static class EmailDetails implements IModelJson { + public void setDeliverBundleSearchResult(String theDeliverBundleSearchResult) { + myDeliverBundleSearchResult = theDeliverBundleSearchResult; + } + + public static class EmailDetails implements IModelJson { @JsonProperty("from") private String myFrom;