From 1c88fd154dce7330baf1b3290143a5353795a1f2 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Mon, 14 Aug 2017 15:19:41 -0400 Subject: [PATCH] Upgrade subscriptions to use interceptors across the board --- .../java/ca/uhn/fhir/context/FhirContext.java | 20 +- .../uhn/fhir/jpa/config/BaseDstu2Config.java | 2 +- .../fhir/jpa/config/WebsocketDstu2Config.java | 2 +- .../WebsocketDstu2DispatcherConfig.java | 2 +- .../jpa/config/dstu3/BaseDstu3Config.java | 2 +- .../config/dstu3/WebsocketDstu3Config.java | 5 +- .../dstu3/WebsocketDstu3DispatcherConfig.java | 2 +- .../uhn/fhir/jpa/config/r4/BaseR4Config.java | 2 +- .../fhir/jpa/config/r4/WebsocketR4Config.java | 2 +- .../fhir/jpa/dao/BaseHapiFhirResourceDao.java | 272 ++++++++---------- .../fhir/jpa/dao/FhirResourceDaoDstu2.java | 18 -- .../jpa/dao/data/ISubscriptionTableDao.java | 10 +- .../jpa/dao/dstu3/FhirResourceDaoDstu3.java | 18 -- .../fhir/jpa/dao/r4/FhirResourceDaoR4.java | 18 -- .../entity/SubscriptionFlaggedResource.java | 45 ++- .../fhir/jpa/entity/SubscriptionTable.java | 9 +- .../BaseRestHookSubscriptionInterceptor.java | 89 ------ .../interceptor/IJpaServerInterceptor.java | 88 ------ .../JpaServerInterceptorAdapter.java | 43 --- ...WebSocketSubscriptionDstu2Interceptor.java | 93 ------ ...WebSocketSubscriptionDstu3Interceptor.java | 107 ------- .../WebSocketSubscriptionR4Interceptor.java | 107 ------- .../BaseSubscriptionInterceptor.java | 41 ++- .../BaseSubscriptionRestHookInterceptor.java | 19 ++ .../BaseSubscriptionWebsocketInterceptor.java | 37 +++ .../SubscriptionActivatingSubscriber.java | 15 +- .../SubscriptionCheckingSubscriber.java | 11 +- ...criptionDeliveringWebsocketSubscriber.java | 142 +++++++++ .../RestHookSubscriptionDstu2Interceptor.java | 6 +- .../SubscriptionWebsocketHandlerDstu2.java | 3 +- ...onWebsocketReturnResourceHandlerDstu2.java | 3 +- ...WebSocketSubscriptionDstu2Interceptor.java | 45 +++ .../RestHookSubscriptionDstu3Interceptor.java | 16 +- .../SubscriptionWebsocketHandlerDstu3.java | 3 +- ...onWebsocketReturnResourceHandlerDstu3.java | 3 +- ...WebSocketSubscriptionDstu3Interceptor.java | 57 ++++ .../r4/RestHookSubscriptionR4Interceptor.java | 6 +- .../WebSocketSubscriptionR4Interceptor.java | 44 +++ .../FhirResourceDaoDstu2InterceptorTest.java | 107 +++---- .../FhirResourceDaoDstu3InterceptorTest.java | 105 +++---- .../r4/FhirResourceDaoR4InterceptorTest.java | 105 +++---- .../BaseResourceProviderDstu2Test.java | 2 +- .../dstu3/BaseResourceProviderDstu3Test.java | 2 +- .../r4/BaseResourceProviderR4Test.java | 2 +- .../subscription/RestHookTestDstu2Test.java | 7 +- .../subscription/RestHookTestDstu3Test.java | 8 +- ...rceptorRegisteredToDaoConfigDstu2Test.java | 39 ++- ...rceptorRegisteredToDaoConfigDstu3Test.java | 24 +- .../subscription/r4/RestHookTestR4Test.java | 6 +- ...nterceptorRegisteredToDaoConfigR4Test.java | 33 ++- .../uhn/fhir/rest/server/RestfulServer.java | 2 +- .../rest/server/GraphQLR4ProviderTest.java | 81 ++++-- pom.xml | 6 +- src/changes/changes.xml | 7 +- 54 files changed, 879 insertions(+), 1064 deletions(-) delete mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/BaseRestHookSubscriptionInterceptor.java delete mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/IJpaServerInterceptor.java delete mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/JpaServerInterceptorAdapter.java delete mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/WebSocketSubscriptionDstu2Interceptor.java delete mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/WebSocketSubscriptionDstu3Interceptor.java delete mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/r4/WebSocketSubscriptionR4Interceptor.java create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionRestHookInterceptor.java create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionWebsocketInterceptor.java create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionDeliveringWebsocketSubscriber.java rename hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/{interceptor => subscription/dstu2}/RestHookSubscriptionDstu2Interceptor.java (90%) rename hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/{ => dstu2}/SubscriptionWebsocketHandlerDstu2.java (98%) rename hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/{ => dstu2}/SubscriptionWebsocketReturnResourceHandlerDstu2.java (99%) create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/WebSocketSubscriptionDstu2Interceptor.java rename hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/{interceptor => subscription/dstu3}/RestHookSubscriptionDstu3Interceptor.java (90%) rename hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/{ => dstu3}/SubscriptionWebsocketHandlerDstu3.java (98%) rename hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/{ => dstu3}/SubscriptionWebsocketReturnResourceHandlerDstu3.java (99%) create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/WebSocketSubscriptionDstu3Interceptor.java rename hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/{interceptor => subscription}/r4/RestHookSubscriptionR4Interceptor.java (91%) create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/r4/WebSocketSubscriptionR4Interceptor.java diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java index 21fc32577f4..106d9c6589e 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.context; +import java.io.IOException; import java.lang.reflect.Method; /* @@ -324,7 +325,7 @@ public class FhirContext { Map, BaseRuntimeElementDefinition> existing = new HashMap<>(); ModelScanner.scanVersionPropertyFile(null, nameToType, theVersion, existing); - Map>> newVersionToNameToResourceType = new HashMap>>(); + Map>> newVersionToNameToResourceType = new HashMap<>(); newVersionToNameToResourceType.putAll(myVersionToNameToResourceType); newVersionToNameToResourceType.put(theVersion, nameToType); myVersionToNameToResourceType = newVersionToNameToResourceType; @@ -913,16 +914,25 @@ public class FhirContext { Set resourceNames= new HashSet<>(); if (myNameToResourceDefinition.isEmpty()) { - + Properties props = new Properties(); + try { + props.load(myVersion.getFhirVersionPropertiesFile()); + } catch (IOException theE) { + throw new ConfigurationException("Failed to load version properties file"); + } + Enumeration propNames = props.propertyNames(); + while (propNames.hasMoreElements()){ + String next = (String) propNames.nextElement(); + if (next.startsWith("resource.")) { + resourceNames.add(next.substring("resource.".length()).trim()); + } + } } for (RuntimeResourceDefinition next : myNameToResourceDefinition.values()) { resourceNames.add(next.getName()); } -// Properties versionProperties = new Properties(); -// versionProperties.load(myVersion.getFhirVersionPropertiesFile()); -// return Collections.unmodifiableSet(resourceNames); } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu2Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu2Config.java index 30816a5327a..3a70c9eabe1 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu2Config.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu2Config.java @@ -28,7 +28,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.dao.*; -import ca.uhn.fhir.jpa.interceptor.RestHookSubscriptionDstu2Interceptor; +import ca.uhn.fhir.jpa.subscription.dstu2.RestHookSubscriptionDstu2Interceptor; import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu2; import ca.uhn.fhir.jpa.term.IHapiTerminologySvc; import ca.uhn.fhir.model.dstu2.composite.MetaDt; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDstu2Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDstu2Config.java index 3c037e62968..d57864e9fb9 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDstu2Config.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDstu2Config.java @@ -31,7 +31,7 @@ import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; import org.springframework.web.socket.handler.PerConnectionWebSocketHandler; -import ca.uhn.fhir.jpa.subscription.SubscriptionWebsocketHandlerDstu2; +import ca.uhn.fhir.jpa.subscription.dstu2.SubscriptionWebsocketHandlerDstu2; @Configuration @EnableWebSocket() diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDstu2DispatcherConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDstu2DispatcherConfig.java index 733793e0452..d20b3d7e63b 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDstu2DispatcherConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDstu2DispatcherConfig.java @@ -28,7 +28,7 @@ import org.springframework.context.annotation.Configuration; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription; -import ca.uhn.fhir.jpa.subscription.SubscriptionWebsocketHandlerDstu2; +import ca.uhn.fhir.jpa.subscription.dstu2.SubscriptionWebsocketHandlerDstu2; import ca.uhn.fhir.model.dstu2.resource.Subscription; @Configuration diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java index 7e17c4f3d20..0c4ab5aac79 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java @@ -40,7 +40,7 @@ import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc; import ca.uhn.fhir.jpa.dao.ISearchParamRegistry; import ca.uhn.fhir.jpa.dao.dstu3.SearchParamExtractorDstu3; import ca.uhn.fhir.jpa.dao.dstu3.SearchParamRegistryDstu3; -import ca.uhn.fhir.jpa.interceptor.RestHookSubscriptionDstu3Interceptor; +import ca.uhn.fhir.jpa.subscription.dstu3.RestHookSubscriptionDstu3Interceptor; import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3; import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu3; import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/WebsocketDstu3Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/WebsocketDstu3Config.java index 88656845d2d..e34817e7cfb 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/WebsocketDstu3Config.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/WebsocketDstu3Config.java @@ -23,7 +23,6 @@ package ca.uhn.fhir.jpa.config.dstu3; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.stereotype.Controller; @@ -33,8 +32,8 @@ import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; import org.springframework.web.socket.handler.PerConnectionWebSocketHandler; -import ca.uhn.fhir.jpa.interceptor.WebSocketSubscriptionDstu3Interceptor; -import ca.uhn.fhir.jpa.subscription.SubscriptionWebsocketHandlerDstu3; +import ca.uhn.fhir.jpa.subscription.dstu3.WebSocketSubscriptionDstu3Interceptor; +import ca.uhn.fhir.jpa.subscription.dstu3.SubscriptionWebsocketHandlerDstu3; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; @Configuration diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/WebsocketDstu3DispatcherConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/WebsocketDstu3DispatcherConfig.java index 038fad7bb1e..c92ecfc6fc8 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/WebsocketDstu3DispatcherConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/WebsocketDstu3DispatcherConfig.java @@ -29,7 +29,7 @@ import org.springframework.context.annotation.Configuration; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription; -import ca.uhn.fhir.jpa.subscription.SubscriptionWebsocketHandlerDstu3; +import ca.uhn.fhir.jpa.subscription.dstu3.SubscriptionWebsocketHandlerDstu3; @Configuration public class WebsocketDstu3DispatcherConfig { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java index 820de327f69..336ea7e83a2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java @@ -34,7 +34,7 @@ import ca.uhn.fhir.jpa.config.BaseConfig; import ca.uhn.fhir.jpa.dao.*; import ca.uhn.fhir.jpa.dao.r4.SearchParamExtractorR4; import ca.uhn.fhir.jpa.dao.r4.SearchParamRegistryR4; -import ca.uhn.fhir.jpa.interceptor.r4.RestHookSubscriptionR4Interceptor; +import ca.uhn.fhir.jpa.subscription.r4.RestHookSubscriptionR4Interceptor; import ca.uhn.fhir.jpa.provider.r4.TerminologyUploaderProviderR4; import ca.uhn.fhir.jpa.term.*; import ca.uhn.fhir.jpa.term.HapiTerminologySvcR4; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/WebsocketR4Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/WebsocketR4Config.java index fd5605e29ef..34446ed084f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/WebsocketR4Config.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/WebsocketR4Config.java @@ -30,7 +30,7 @@ import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.config.annotation.*; import org.springframework.web.socket.handler.PerConnectionWebSocketHandler; -import ca.uhn.fhir.jpa.interceptor.r4.WebSocketSubscriptionR4Interceptor; +import ca.uhn.fhir.jpa.subscription.r4.WebSocketSubscriptionR4Interceptor; import ca.uhn.fhir.jpa.subscription.r4.SubscriptionWebsocketHandlerR4; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java index 54ebd6dc0c1..4b315d2ed0c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java @@ -20,26 +20,15 @@ package ca.uhn.fhir.jpa.dao; * #L% */ -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -import java.util.*; - -import javax.annotation.PostConstruct; -import javax.persistence.NoResultException; -import javax.persistence.TypedQuery; - -import org.apache.commons.lang3.Validate; -import org.hl7.fhir.instance.model.api.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Required; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; - -import ca.uhn.fhir.context.*; -import ca.uhn.fhir.jpa.dao.data.*; +import ca.uhn.fhir.context.ConfigurationException; +import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.context.RuntimeResourceDefinition; +import ca.uhn.fhir.context.RuntimeSearchParam; +import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao; +import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao; +import ca.uhn.fhir.jpa.dao.data.IResourceTableDao; +import ca.uhn.fhir.jpa.dao.data.ISearchResultDao; import ca.uhn.fhir.jpa.entity.*; -import ca.uhn.fhir.jpa.interceptor.IJpaServerInterceptor; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.util.DeleteConflict; import ca.uhn.fhir.jpa.util.StopWatch; @@ -47,7 +36,10 @@ import ca.uhn.fhir.jpa.util.jsonpatch.JsonPatchUtils; import ca.uhn.fhir.jpa.util.xmlpatch.XmlPatchUtils; import ca.uhn.fhir.model.api.*; import ca.uhn.fhir.model.primitive.IdDt; -import ca.uhn.fhir.rest.api.*; +import ca.uhn.fhir.rest.api.PatchTypeEnum; +import ca.uhn.fhir.rest.api.QualifiedParamList; +import ca.uhn.fhir.rest.api.RestOperationTypeEnum; +import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.param.ParameterUtil; @@ -56,35 +48,49 @@ import ca.uhn.fhir.rest.server.exceptions.*; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor; -import ca.uhn.fhir.rest.server.method.MethodUtil; import ca.uhn.fhir.rest.server.method.SearchMethodBinding; -import ca.uhn.fhir.util.*; +import ca.uhn.fhir.util.FhirTerser; +import ca.uhn.fhir.util.ObjectUtil; +import ca.uhn.fhir.util.OperationOutcomeUtil; +import ca.uhn.fhir.util.ResourceReferenceInfo; +import org.apache.commons.lang3.Validate; +import org.hl7.fhir.instance.model.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Required; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.PostConstruct; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; +import java.util.*; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; @Transactional(propagation = Propagation.REQUIRED) public abstract class BaseHapiFhirResourceDao extends BaseHapiFhirDao implements IFhirResourceDao { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirResourceDao.class); - - @Autowired - private DaoConfig myDaoConfig; @Autowired protected PlatformTransactionManager myPlatformTransactionManager; @Autowired + protected IResourceTableDao myResourceTableDao; + @Autowired(required = false) + protected IFulltextSearchSvc mySearchDao; + @Autowired() + protected ISearchResultDao mySearchResultDao; + @Autowired + private DaoConfig myDaoConfig; + @Autowired private IResourceHistoryTableDao myResourceHistoryTableDao; @Autowired private IResourceLinkDao myResourceLinkDao; private String myResourceName; - @Autowired - protected IResourceTableDao myResourceTableDao; private Class myResourceType; - @Autowired(required = false) - protected IFulltextSearchSvc mySearchDao; - @Autowired() - protected ISearchResultDao mySearchResultDao; - private String mySecondaryPrimaryKeyParamName; - + @Override public void addTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel) { StopWatch w = new StopWatch(); @@ -94,10 +100,10 @@ public abstract class BaseHapiFhirResourceDao extends B } //@formatter:off - for (BaseTag next : new ArrayList(entity.getTags())) { - if (ObjectUtil.equals(next.getTag().getTagType(), theTagType) && - ObjectUtil.equals(next.getTag().getSystem(), theScheme) && - ObjectUtil.equals(next.getTag().getCode(), theTerm)) { + for (BaseTag next : new ArrayList<>(entity.getTags())) { + if (ObjectUtil.equals(next.getTag().getTagType(), theTagType) && + ObjectUtil.equals(next.getTag().getSystem(), theScheme) && + ObjectUtil.equals(next.getTag().getCode(), theTerm)) { return; } } @@ -113,10 +119,10 @@ public abstract class BaseHapiFhirResourceDao extends B myEntityManager.merge(entity); } } - - ourLog.info("Processed addTag {}/{} on {} in {}ms", new Object[] { theScheme, theTerm, theId, w.getMillisAndRestart() }); + + ourLog.info("Processed addTag {}/{} on {} in {}ms", new Object[]{theScheme, theTerm, theId, w.getMillisAndRestart()}); } - + @Override public DaoMethodOutcome create(final T theResource) { return create(theResource, null, true, null); @@ -182,9 +188,9 @@ public abstract class BaseHapiFhirResourceDao extends B T resourceToDelete = toResource(myResourceType, entity, false); validateOkToDelete(theDeleteConflicts, entity); - + preDelete(resourceToDelete, entity); - + // Notify interceptors if (theRequestDetails != null) { ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId); @@ -199,11 +205,6 @@ public abstract class BaseHapiFhirResourceDao extends B if (theRequestDetails != null) { ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId); theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete); - for (IServerInterceptor next : getConfig().getInterceptors()) { - if (next instanceof IJpaServerInterceptor) { - ((IJpaServerInterceptor) next).resourceDeleted(requestDetails, entity); - } - } } for (IServerInterceptor next : getConfig().getInterceptors()) { if (next instanceof IServerOperationInterceptor) { @@ -238,7 +239,7 @@ public abstract class BaseHapiFhirResourceDao extends B /** * This method gets called by {@link #deleteByUrl(String, List, RequestDetails)} as well as by - * transaction processors + * transaction processors */ @Override public DeleteMethodOutcome deleteByUrl(String theUrl, List deleteConflicts, RequestDetails theRequestDetails) { @@ -264,7 +265,7 @@ public abstract class BaseHapiFhirResourceDao extends B ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, idToDelete.getResourceType(), idToDelete); notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails); } - + // Perform delete Date updateTime = new Date(); updateEntity(null, entity, updateTime, updateTime); @@ -274,11 +275,6 @@ public abstract class BaseHapiFhirResourceDao extends B if (theRequestDetails != null) { theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete); ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, idToDelete.getResourceType(), idToDelete); - for (IServerInterceptor next : getConfig().getInterceptors()) { - if (next instanceof IJpaServerInterceptor) { - ((IJpaServerInterceptor) next).resourceDeleted(requestDetails, entity); - } - } } for (IServerInterceptor next : getConfig().getInterceptors()) { if (next instanceof IServerOperationInterceptor) { @@ -302,14 +298,14 @@ public abstract class BaseHapiFhirResourceDao extends B OperationOutcomeUtil.addIssue(getContext(), oo, severity, message, null, code); } - ourLog.info("Processed delete on {} (matched {} resource(s)) in {}ms", new Object[] { theUrl, deletedResources.size(), w.getMillis() }); + ourLog.info("Processed delete on {} (matched {} resource(s)) in {}ms", new Object[]{theUrl, deletedResources.size(), w.getMillis()}); DeleteMethodOutcome retVal = new DeleteMethodOutcome(); retVal.setDeletedEntities(deletedResources); retVal.setOperationOutcome(oo); return retVal; } - + @Override public DeleteMethodOutcome deleteByUrl(String theUrl, RequestDetails theRequestDetails) { List deleteConflicts = new ArrayList(); @@ -317,7 +313,7 @@ public abstract class BaseHapiFhirResourceDao extends B DeleteMethodOutcome outcome = deleteByUrl(theUrl, deleteConflicts, theRequestDetails); validateDeleteConflictsEmptyOrThrowException(deleteConflicts); - + return outcome; } @@ -351,7 +347,7 @@ public abstract class BaseHapiFhirResourceDao extends B if (isNotBlank(theResource.getIdElement().getIdPart())) { if (isValidPid(theResource.getIdElement())) { throw new UnprocessableEntityException( - "This server cannot create an entity with a user-specified numeric ID - Client should not specify an ID when creating a new resource, or should include at least one letter in the ID to force a client-defined ID"); + "This server cannot create an entity with a user-specified numeric ID - Client should not specify an ID when creating a new resource, or should include at least one letter in the ID to force a client-defined ID"); } createForcedIdIfNeeded(entity, theResource.getIdElement()); @@ -385,16 +381,11 @@ public abstract class BaseHapiFhirResourceDao extends B if (!thePerformIndexing) { incrementId(theResource, entity, theResource.getIdElement()); } - + // Notify JPA interceptors if (theRequestDetails != null) { ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theResource); theRequestDetails.getRequestOperationCallback().resourceCreated(theResource); - for (IServerInterceptor next : getConfig().getInterceptors()) { - if (next instanceof IJpaServerInterceptor) { - ((IJpaServerInterceptor) next).resourceCreated(requestDetails, entity); - } - } } for (IServerInterceptor next : getConfig().getInterceptors()) { if (next instanceof IServerOperationInterceptor) { @@ -418,12 +409,12 @@ public abstract class BaseHapiFhirResourceDao extends B List tags = toTagList(theMetaAdd); for (TagDefinition nextDef : tags) { - + boolean hasTag = false; - for (BaseTag next : new ArrayList(entity.getTags())) { - if (ObjectUtil.equals(next.getTag().getTagType(), nextDef.getTagType()) && - ObjectUtil.equals(next.getTag().getSystem(), nextDef.getSystem()) && - ObjectUtil.equals(next.getTag().getCode(), nextDef.getCode())) { + for (BaseTag next : new ArrayList<>(entity.getTags())) { + if (ObjectUtil.equals(next.getTag().getTagType(), nextDef.getTagType()) && + ObjectUtil.equals(next.getTag().getSystem(), nextDef.getSystem()) && + ObjectUtil.equals(next.getTag().getCode(), nextDef.getCode())) { hasTag = true; break; } @@ -431,7 +422,7 @@ public abstract class BaseHapiFhirResourceDao extends B if (!hasTag) { entity.setHasTags(true); - + TagDefinition def = getTagOrNull(nextDef.getTagType(), nextDef.getSystem(), nextDef.getCode(), nextDef.getDisplay()); if (def != null) { BaseTag newEntity = entity.addTag(def); @@ -443,7 +434,7 @@ public abstract class BaseHapiFhirResourceDao extends B } validateMetaCount(entity.getTags().size()); - + myEntityManager.merge(entity); } @@ -453,9 +444,9 @@ public abstract class BaseHapiFhirResourceDao extends B //@formatter:off for (TagDefinition nextDef : tags) { for (BaseTag next : new ArrayList(entity.getTags())) { - if (ObjectUtil.equals(next.getTag().getTagType(), nextDef.getTagType()) && - ObjectUtil.equals(next.getTag().getSystem(), nextDef.getSystem()) && - ObjectUtil.equals(next.getTag().getCode(), nextDef.getCode())) { + if (ObjectUtil.equals(next.getTag().getTagType(), nextDef.getTagType()) && + ObjectUtil.equals(next.getTag().getSystem(), nextDef.getSystem()) && + ObjectUtil.equals(next.getTag().getCode(), nextDef.getCode())) { myEntityManager.remove(next); entity.getTags().remove(next); } @@ -482,8 +473,6 @@ public abstract class BaseHapiFhirResourceDao extends B return tags; } - protected abstract List getIncludeValues(FhirTerser theTerser, Include theInclude, IBaseResource theResource, RuntimeResourceDefinition theResourceDef); - public String getResourceName() { return myResourceName; } @@ -493,6 +482,12 @@ public abstract class BaseHapiFhirResourceDao extends B return myResourceType; } + @SuppressWarnings("unchecked") + @Required + public void setResourceType(Class theTableType) { + myResourceType = (Class) theTableType; + } + @Override public TagList getTags(IIdType theResourceId, RequestDetails theRequestDetails) { // Notify interceptors @@ -535,17 +530,16 @@ public abstract class BaseHapiFhirResourceDao extends B } private void incrementId(T theResource, ResourceTable theSavedEntity, IIdType theResourceId) { - IIdType idType = theResourceId; String newVersion; long newVersionLong; - if (idType == null || idType.getVersionIdPart() == null) { + if (theResourceId == null || theResourceId.getVersionIdPart() == null) { newVersion = "1"; newVersionLong = 1; } else { - newVersionLong = idType.getVersionIdPartAsLong() + 1; + newVersionLong = theResourceId.getVersionIdPartAsLong() + 1; newVersion = Long.toString(newVersionLong); } - + IIdType newId = theResourceId.withVersion(newVersion); theResource.getIdElement().setValue(newId.getValue()); theSavedEntity.setVersion(newVersionLong); @@ -568,7 +562,7 @@ public abstract class BaseHapiFhirResourceDao extends B ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theResourceId); notifyInterceptors(RestOperationTypeEnum.META_ADD, requestDetails); } - + StopWatch w = new StopWatch(); BaseHasResource entity = readEntity(theResourceId); if (entity == null) { @@ -586,14 +580,13 @@ public abstract class BaseHapiFhirResourceDao extends B doMetaAdd(theMetaAdd, history); } - ourLog.info("Processed metaAddOperation on {} in {}ms", new Object[] { theResourceId, w.getMillisAndRestart() }); + ourLog.info("Processed metaAddOperation on {} in {}ms", new Object[]{theResourceId, w.getMillisAndRestart()}); @SuppressWarnings("unchecked") MT retVal = (MT) metaGetOperation(theMetaAdd.getClass(), theResourceId, theRequestDetails); return retVal; } - @Override public MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel, RequestDetails theRequestDetails) { // Notify interceptors @@ -601,7 +594,7 @@ public abstract class BaseHapiFhirResourceDao extends B ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theResourceId); notifyInterceptors(RestOperationTypeEnum.META_DELETE, requestDetails); } - + StopWatch w = new StopWatch(); BaseHasResource entity = readEntity(theResourceId); if (entity == null) { @@ -621,7 +614,7 @@ public abstract class BaseHapiFhirResourceDao extends B myEntityManager.flush(); - ourLog.info("Processed metaDeleteOperation on {} in {}ms", new Object[] { theResourceId.getValue(), w.getMillisAndRestart() }); + ourLog.info("Processed metaDeleteOperation on {} in {}ms", new Object[]{theResourceId.getValue(), w.getMillisAndRestart()}); @SuppressWarnings("unchecked") MT retVal = (MT) metaGetOperation(theMetaDel.getClass(), theResourceId, theRequestDetails); @@ -635,7 +628,7 @@ public abstract class BaseHapiFhirResourceDao extends B ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theId); notifyInterceptors(RestOperationTypeEnum.META, requestDetails); } - + Set tagDefs = new HashSet(); BaseHasResource entity = readEntity(theId); for (BaseTag next : entity.getTags()) { @@ -656,7 +649,7 @@ public abstract class BaseHapiFhirResourceDao extends B ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null); notifyInterceptors(RestOperationTypeEnum.META, requestDetails); } - + String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t WHERE t.myResourceType = :res_type)"; TypedQuery q = myEntityManager.createQuery(sql, TagDefinition.class); q.setParameter("res_type", myResourceName); @@ -675,9 +668,9 @@ public abstract class BaseHapiFhirResourceDao extends B throw new ResourceVersionConflictException("Version " + theId.getVersionIdPart() + " is not the most recent version of this resource, unable to apply patch"); } } - + validateResourceType(entityToUpdate); - + IBaseResource resourceToUpdate = toResource(entityToUpdate, false); IBaseResource destination; if (thePatchType == PatchTypeEnum.JSON_PATCH) { @@ -685,7 +678,7 @@ public abstract class BaseHapiFhirResourceDao extends B } else { destination = XmlPatchUtils.apply(getContext(), resourceToUpdate, thePatchBody); } - + @SuppressWarnings("unchecked") T destinationCasted = (T) destination; return update(destinationCasted, null, true, theRequestDetails); @@ -710,7 +703,7 @@ public abstract class BaseHapiFhirResourceDao extends B /** * Subclasses may override to provide behaviour. Invoked within a delete - * transaction with the resource that is about to be deleted. + * transaction with the resource that is about to be deleted. */ protected void preDelete(T theResourceToDelete, ResourceTable theEntityToDelete) { // nothing by default @@ -718,9 +711,8 @@ public abstract class BaseHapiFhirResourceDao extends B /** * May be overridden by subclasses to validate resources prior to storage - * - * @param theResource - * The resource that is about to be stored + * + * @param theResource The resource that is about to be stored */ protected void preProcessResourceForStorage(T theResource) { String type = getContext().getResourceDefinition(theResource).getName(); @@ -825,7 +817,7 @@ public abstract class BaseHapiFhirResourceDao extends B if (entity == null) { if (theId.hasVersionIdPart()) { TypedQuery q = myEntityManager - .createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class); + .createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class); q.setParameter("RID", pid); q.setParameter("RTYP", myResourceName); q.setParameter("RVER", theId.getVersionIdPartAsLong()); @@ -859,7 +851,7 @@ public abstract class BaseHapiFhirResourceDao extends B ourLog.debug("Indexing resource {} - PID {}", theResource.getIdElement().getValue(), theEntity.getId()); updateEntity(theResource, theEntity, null, true, false, theEntity.getUpdatedDate(), true, false); } - + @Override public void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm) { removeTag(theId, theTagType, theScheme, theTerm, null); @@ -872,7 +864,7 @@ public abstract class BaseHapiFhirResourceDao extends B ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theId); notifyInterceptors(RestOperationTypeEnum.DELETE_TAGS, requestDetails); } - + StopWatch w = new StopWatch(); BaseHasResource entity = readEntity(theId); if (entity == null) { @@ -881,9 +873,9 @@ public abstract class BaseHapiFhirResourceDao extends B //@formatter:off for (BaseTag next : new ArrayList(entity.getTags())) { - if (ObjectUtil.equals(next.getTag().getTagType(), theTagType) && - ObjectUtil.equals(next.getTag().getSystem(), theScheme) && - ObjectUtil.equals(next.getTag().getCode(), theTerm)) { + if (ObjectUtil.equals(next.getTag().getTagType(), theTagType) && + ObjectUtil.equals(next.getTag().getSystem(), theScheme) && + ObjectUtil.equals(next.getTag().getCode(), theTerm)) { myEntityManager.remove(next); entity.getTags().remove(next); } @@ -896,25 +888,25 @@ public abstract class BaseHapiFhirResourceDao extends B myEntityManager.merge(entity); - ourLog.info("Processed remove tag {}/{} on {} in {}ms", new Object[] { theScheme, theTerm, theId.getValue(), w.getMillisAndRestart() }); + ourLog.info("Processed remove tag {}/{} on {} in {}ms", new Object[]{theScheme, theTerm, theId.getValue(), w.getMillisAndRestart()}); } - @Transactional(propagation=Propagation.SUPPORTS) + @Transactional(propagation = Propagation.SUPPORTS) @Override public IBundleProvider search(final SearchParameterMap theParams) { return search(theParams, null); } - @Transactional(propagation=Propagation.SUPPORTS) + @Transactional(propagation = Propagation.SUPPORTS) @Override public IBundleProvider search(final SearchParameterMap theParams, RequestDetails theRequestDetails) { // Notify interceptors if (theRequestDetails != null) { ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), getResourceName(), null); notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails); - + if (theRequestDetails.isSubRequest()) { - Integer max = myDaoConfig.getMaximumSearchResultCountInTransaction(); + Integer max = myDaoConfig.getMaximumSearchResultCountInTransaction(); if (max != null) { Validate.inclusiveBetween(1, Integer.MAX_VALUE, max.intValue(), "Maximum search result count in transaction ust be a positive integer"); theParams.setLoadSynchronousUpTo(myDaoConfig.getMaximumSearchResultCountInTransaction()); @@ -925,7 +917,7 @@ public abstract class BaseHapiFhirResourceDao extends B theParams.setLoadSynchronous(true); } } - + return mySearchCoordinatorSvc.registerSearch(this, theParams, getResourceName()); } @@ -936,22 +928,16 @@ public abstract class BaseHapiFhirResourceDao extends B builder.setType(getResourceType(), getResourceName()); // FIXME: fail if too many results - + HashSet retVal = new HashSet(); - + String uuid = UUID.randomUUID().toString(); Iterator iter = builder.createQuery(theParams, uuid); while (iter.hasNext()) { retVal.add(iter.next()); } - - return retVal; - } - @SuppressWarnings("unchecked") - @Required - public void setResourceType(Class theTableType) { - myResourceType = (Class) theTableType; + return retVal; } /** @@ -970,15 +956,15 @@ public abstract class BaseHapiFhirResourceDao extends B } for (TagDefinition next : tagDefinitions) { switch (next.getTagType()) { - case PROFILE: - retVal.addProfile(next.getCode()); - break; - case SECURITY_LABEL: - retVal.addSecurity().setSystem(next.getSystem()).setCode(next.getCode()).setDisplay(next.getDisplay()); - break; - case TAG: - retVal.addTag().setSystem(next.getSystem()).setCode(next.getCode()).setDisplay(next.getDisplay()); - break; + case PROFILE: + retVal.addProfile(next.getCode()); + break; + case SECURITY_LABEL: + retVal.addSecurity().setSystem(next.getSystem()).setCode(next.getCode()).setDisplay(next.getDisplay()); + break; + case TAG: + retVal.addTag().setSystem(next.getSystem()).setCode(next.getCode()).setDisplay(next.getDisplay()); + break; } } return retVal; @@ -1028,15 +1014,15 @@ public abstract class BaseHapiFhirResourceDao extends B return retVal; } - @Transactional(propagation=Propagation.SUPPORTS) + @Transactional(propagation = Propagation.SUPPORTS) @Override public void translateRawParameters(Map> theSource, SearchParameterMap theTarget) { if (theSource == null || theSource.isEmpty()) { return; } - + Map searchParams = mySerarchParamRegistry.getActiveSearchParams(getResourceName()); - + Set paramNames = theSource.keySet(); for (String nextParamName : paramNames) { QualifierDetails qualifiedParamName = SearchMethodBinding.extractQualifiersFromParameterName(nextParamName); @@ -1058,7 +1044,7 @@ public abstract class BaseHapiFhirResourceDao extends B theTarget.add(qualifiedParamName.getParamName(), parsedParam); } } - + } } @@ -1109,7 +1095,7 @@ public abstract class BaseHapiFhirResourceDao extends B } catch (ResourceNotFoundException e) { if (resourceId.isIdPartValidLong()) { throw new InvalidRequestException( - getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getIdElement().getIdPart())); + getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getIdElement().getIdPart())); } return doCreate(theResource, null, thePerformIndexing, new Date(), theRequestDetails); } @@ -1121,7 +1107,7 @@ public abstract class BaseHapiFhirResourceDao extends B if (resourceId.hasResourceType() && !resourceId.getResourceType().equals(getResourceName())) { throw new UnprocessableEntityException( - "Invalid resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] of type[" + entity.getResourceType() + "] - Does not match expected [" + getResourceName() + "]"); + "Invalid resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] of type[" + entity.getResourceType() + "] - Does not match expected [" + getResourceName() + "]"); } // Notify interceptors @@ -1132,7 +1118,7 @@ public abstract class BaseHapiFhirResourceDao extends B } IBaseResource oldResource = toResource(entity, false); - + // Perform update ResourceTable savedEntity = updateEntity(theResource, entity, null, thePerformIndexing, thePerformIndexing, new Date(), theForceUpdateVersion, thePerformIndexing); @@ -1152,11 +1138,6 @@ public abstract class BaseHapiFhirResourceDao extends B if (theRequestDetails != null) { theRequestDetails.getRequestOperationCallback().resourceUpdated(theResource); theRequestDetails.getRequestOperationCallback().resourceUpdated(oldResource, theResource); - for (IServerInterceptor next : getConfig().getInterceptors()) { - if (next instanceof IJpaServerInterceptor) { - ((IJpaServerInterceptor) next).resourceUpdated(requestDetails, entity); - } - } } for (IServerInterceptor next : getConfig().getInterceptors()) { if (next instanceof IServerOperationInterceptor) { @@ -1164,21 +1145,21 @@ public abstract class BaseHapiFhirResourceDao extends B ((IServerOperationInterceptor) next).resourceUpdated(theRequestDetails, oldResource, theResource); } } - + DaoMethodOutcome outcome = toMethodOutcome(savedEntity, theResource).setCreated(false); if (!thePerformIndexing) { outcome.setId(theResource.getIdElement()); } - + String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart()); outcome.setOperationOutcome(createInfoOperationOutcome(msg)); ourLog.info(msg); return outcome; } - - + + @Override public DaoMethodOutcome update(T theResource, String theMatchUrl, boolean thePerformIndexing, RequestDetails theRequestDetails) { return update(theResource, theMatchUrl, thePerformIndexing, false, theRequestDetails); @@ -1191,18 +1172,19 @@ public abstract class BaseHapiFhirResourceDao extends B /** * Get the resource definition from the criteria which specifies the resource type + * * @param criteria * @return */ @Override public RuntimeResourceDefinition validateCriteriaAndReturnResourceDefinition(String criteria) { String resourceName; - if(criteria == null || criteria.trim().isEmpty()){ + if (criteria == null || criteria.trim().isEmpty()) { throw new IllegalArgumentException("Criteria cannot be empty"); } - if(criteria.contains("?")){ + if (criteria.contains("?")) { resourceName = criteria.substring(0, criteria.indexOf("?")); - }else{ + } else { resourceName = criteria; } @@ -1220,7 +1202,7 @@ public abstract class BaseHapiFhirResourceDao extends B } } } - + protected void validateOkToDelete(List theDeleteConflicts, ResourceTable theEntity) { TypedQuery query = myEntityManager.createQuery("SELECT l FROM ResourceLink l WHERE l.myTargetResourcePid = :target_pid", ResourceLink.class); query.setParameter("target_pid", theEntity.getId()); @@ -1235,7 +1217,7 @@ public abstract class BaseHapiFhirResourceDao extends B myResourceLinkDao.delete(resultList); return; } - + ResourceLink link = resultList.get(0); IdDt targetId = theEntity.getIdDt(); IdDt sourceId = link.getSourceResource().getIdDt(); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java index e19cc9f2c81..3b98de3250e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java @@ -56,24 +56,6 @@ public class FhirResourceDaoDstu2 extends BaseHapiFhirResou @Qualifier("myInstanceValidatorDstu2") private IValidatorModule myInstanceValidator; - @Override - protected List getIncludeValues(FhirTerser theTerser, Include theInclude, IBaseResource theResource, RuntimeResourceDefinition theResourceDef) { - List values; - if ("*".equals(theInclude.getValue())) { - values = new ArrayList(); - values.addAll(theTerser.getAllPopulatedChildElementsOfType(theResource, BaseResourceReferenceDt.class)); - } else if (theInclude.getValue().startsWith(theResourceDef.getName() + ":")) { - values = new ArrayList(); - String paramName = theInclude.getValue().substring(theInclude.getValue().indexOf(':') + 1); - RuntimeSearchParam sp = getSearchParamByName(theResourceDef, paramName); - for (String nextPath : sp.getPathsSplit()) { - values.addAll(theTerser.getValues(theResource, nextPath)); - } - } else { - values = Collections.emptyList(); - } - return values; - } @Override protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ISubscriptionTableDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ISubscriptionTableDao.java index d9f1a496a43..a93ae6e4c09 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ISubscriptionTableDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ISubscriptionTableDao.java @@ -33,19 +33,19 @@ import ca.uhn.fhir.jpa.entity.SubscriptionTable; public interface ISubscriptionTableDao extends JpaRepository { @Query("SELECT t FROM SubscriptionTable t WHERE t.myResId = :pid") - public SubscriptionTable findOneByResourcePid(@Param("pid") Long theId); + SubscriptionTable findOneByResourcePid(@Param("pid") Long theId); @Modifying @Query("DELETE FROM SubscriptionTable t WHERE t.myId = :id ") - public void deleteAllForSubscription(@Param("id") Long theSubscriptionId); + void deleteAllForSubscription(@Param("id") Long theSubscriptionId); @Modifying @Query("UPDATE SubscriptionTable t SET t.myLastClientPoll = :last_client_poll") - public int updateLastClientPoll(@Param("last_client_poll") Date theLastClientPoll); + int updateLastClientPoll(@Param("last_client_poll") Date theLastClientPoll); @Query("SELECT t FROM SubscriptionTable t WHERE t.myLastClientPoll < :cutoff OR (t.myLastClientPoll IS NULL AND t.myCreated < :cutoff)") - public Collection findInactiveBeforeCutoff(@Param("cutoff") Date theCutoff); + Collection findInactiveBeforeCutoff(@Param("cutoff") Date theCutoff); @Query("SELECT t.myId FROM SubscriptionTable t WHERE t.myStatus = :status AND t.myNextCheck <= :next_check") - public Collection findSubscriptionsWhichNeedToBeChecked(@Param("status") String theStatus, @Param("next_check") Date theNextCheck); + Collection findSubscriptionsWhichNeedToBeChecked(@Param("status") String theStatus, @Param("next_check") Date theNextCheck); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3.java index 6e436d97b0a..5169df83d0d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3.java @@ -70,24 +70,6 @@ public class FhirResourceDaoDstu3 extends BaseHapiFhirRe return oo; } - @Override - protected List getIncludeValues(FhirTerser theTerser, Include theInclude, IBaseResource theResource, RuntimeResourceDefinition theResourceDef) { - List values; - if ("*".equals(theInclude.getValue())) { - values = new ArrayList(); - values.addAll(theTerser.getAllPopulatedChildElementsOfType(theResource, BaseResourceReferenceDt.class)); - } else if (theInclude.getValue().startsWith(theResourceDef.getName() + ":")) { - values = new ArrayList(); - String paramName = theInclude.getValue().substring(theInclude.getValue().indexOf(':') + 1); - RuntimeSearchParam sp = getSearchParamByName(theResourceDef, paramName); - for (String nextPath : sp.getPathsSplit()) { - values.addAll(theTerser.getValues(theResource, nextPath)); - } - } else { - values = Collections.emptyList(); - } - return values; - } @Override public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequestDetails) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4.java index 5a841361dd8..e3c8b580409 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4.java @@ -70,24 +70,6 @@ public class FhirResourceDaoR4 extends BaseHapiFhirResou return oo; } - @Override - protected List getIncludeValues(FhirTerser theTerser, Include theInclude, IBaseResource theResource, RuntimeResourceDefinition theResourceDef) { - List values; - if ("*".equals(theInclude.getValue())) { - values = new ArrayList(); - values.addAll(theTerser.getAllPopulatedChildElementsOfType(theResource, BaseResourceReferenceDt.class)); - } else if (theInclude.getValue().startsWith(theResourceDef.getName() + ":")) { - values = new ArrayList(); - String paramName = theInclude.getValue().substring(theInclude.getValue().indexOf(':') + 1); - RuntimeSearchParam sp = getSearchParamByName(theResourceDef, paramName); - for (String nextPath : sp.getPathsSplit()) { - values.addAll(theTerser.getValues(theResource, nextPath)); - } - } else { - values = Collections.emptyList(); - } - return values; - } @Override public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequestDetails) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SubscriptionFlaggedResource.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SubscriptionFlaggedResource.java index 2a3e969dd25..2e4618f21ae 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SubscriptionFlaggedResource.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SubscriptionFlaggedResource.java @@ -20,64 +20,53 @@ package ca.uhn.fhir.jpa.entity; * #L% */ -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.ForeignKey; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; +import javax.persistence.*; @Entity @Table(name = "HFJ_SUBSCRIPTION_FLAG_RES") public class SubscriptionFlaggedResource { @Id - @GeneratedValue(strategy = GenerationType.AUTO, generator="SEQ_SUBSCRIPTION_FLAG_ID") + @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_SUBSCRIPTION_FLAG_ID") @SequenceGenerator(name = "SEQ_SUBSCRIPTION_FLAG_ID", sequenceName = "SEQ_SUBSCRIPTION_FLAG_ID") @Column(name = "PID", insertable = false, updatable = false) private Long myId; @ManyToOne() - @JoinColumn(name="RES_ID", nullable=false, foreignKey=@ForeignKey(name="FK_SUBSFLAGRES_RES")) + @JoinColumn(name = "RES_ID", nullable = false, foreignKey = @ForeignKey(name = "FK_SUBSFLAGRES_RES")) private ResourceTable myResource; - - //@formatter:off + @ManyToOne() - @JoinColumn(name="SUBSCRIPTION_ID", - foreignKey=@ForeignKey(name="FK_SUBSFLAG_SUBS") + @JoinColumn(name = "SUBSCRIPTION_ID", + foreignKey = @ForeignKey(name = "FK_SUBSFLAG_SUBS") ) private SubscriptionTable mySubscription; - //@formatter:om - - @Column(name="RES_VERSION", nullable=false) + + @Column(name = "RES_VERSION", nullable = false) private Long myVersion; public ResourceTable getResource() { return myResource; } - public SubscriptionTable getSubscription() { - return mySubscription; - } - - public Long getVersion() { - return myVersion; - } - public void setResource(ResourceTable theResource) { myResource = theResource; } + public SubscriptionTable getSubscription() { + return mySubscription; + } + public void setSubscription(SubscriptionTable theSubscription) { mySubscription = theSubscription; } + public Long getVersion() { + return myVersion; + } + public void setVersion(Long theVersion) { myVersion = theVersion; } - + } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SubscriptionTable.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SubscriptionTable.java index e95860e9b78..3bcb6f165fe 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SubscriptionTable.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/SubscriptionTable.java @@ -87,13 +87,18 @@ public class SubscriptionTable { @Column(name = "SUBSCRIPTION_STATUS", nullable = false, length = 20) private String myStatus; - //@formatter:off @OneToOne() @JoinColumn(name = "RES_ID", insertable = true, updatable = false, referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_SUBSCRIPTION_RESOURCE_ID") ) private ResourceTable mySubscriptionResource; - //@formatter:on + + /** + * Constructor + */ + public SubscriptionTable(){ + super(); + } public long getCheckInterval() { return myCheckInterval; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/BaseRestHookSubscriptionInterceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/BaseRestHookSubscriptionInterceptor.java deleted file mode 100644 index 0244c7aec08..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/BaseRestHookSubscriptionInterceptor.java +++ /dev/null @@ -1,89 +0,0 @@ -package ca.uhn.fhir.jpa.interceptor; - -/*- - * #%L - * HAPI FHIR JPA Server - * %% - * Copyright (C) 2014 - 2017 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.instance.model.api.IIdType; - -import ca.uhn.fhir.context.RuntimeResourceDefinition; -import ca.uhn.fhir.jpa.dao.*; -import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails; -import ca.uhn.fhir.rest.api.server.IBundleProvider; -import ca.uhn.fhir.rest.api.server.RequestDetails; -import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; -import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter; - -public abstract class BaseRestHookSubscriptionInterceptor extends ServerOperationInterceptorAdapter { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseRestHookSubscriptionInterceptor.class); - - protected static final Integer MAX_SUBSCRIPTION_RESULTS = 10000; - - protected abstract IFhirResourceDao getSubscriptionDao(); - - protected void checkSubscriptionCriterias(String theCriteria) { - try { - IBundleProvider results = executeSubscriptionCriteria(theCriteria, null); - } catch (Exception e) { - ourLog.warn("Invalid criteria when creating subscription", e); - throw new InvalidRequestException("Invalid criteria: " + e.getMessage()); - } - } - - private IBundleProvider executeSubscriptionCriteria(String theCriteria, IIdType idType) { - String criteria = theCriteria; - - /* - * 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 - */ - if (idType != null) { - criteria += "&_id=" + idType.getResourceType() + "/" + idType.getIdPart(); - } - - IBundleProvider results = getBundleProvider(criteria, true); - return results; - } - - /** - * Search based on a query criteria - * - * @param theCheckOnly Is this just a test that the search works - */ - protected IBundleProvider getBundleProvider(String theCriteria, boolean theCheckOnly) { - RuntimeResourceDefinition responseResourceDef = getSubscriptionDao().validateCriteriaAndReturnResourceDefinition(theCriteria); - SearchParameterMap responseCriteriaUrl = BaseHapiFhirDao.translateMatchUrl(getSubscriptionDao(), getSubscriptionDao().getContext(), theCriteria, responseResourceDef); - - RequestDetails req = new ServletSubRequestDetails(); - req.setSubRequest(true); - - IFhirResourceDao responseDao = getSubscriptionDao().getDao(responseResourceDef.getImplementingClass()); - - if (theCheckOnly) { - responseCriteriaUrl.setLoadSynchronousUpTo(1); - } else { - responseCriteriaUrl.setLoadSynchronousUpTo(MAX_SUBSCRIPTION_RESULTS); - } - - IBundleProvider responseResults = responseDao.search(responseCriteriaUrl, req); - return responseResults; - } - -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/IJpaServerInterceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/IJpaServerInterceptor.java deleted file mode 100644 index 3856a05735f..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/IJpaServerInterceptor.java +++ /dev/null @@ -1,88 +0,0 @@ -package ca.uhn.fhir.jpa.interceptor; - -import ca.uhn.fhir.jpa.entity.ResourceTable; -import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; -import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; -import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor; - -/* - * #%L - * HAPI FHIR JPA Server - * %% - * Copyright (C) 2014 - 2017 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -/** - * Server interceptor for JPA DAOs which adds methods that will be called at certain points - * in the operation lifecycle for JPA operations. - * - * @deprecated Use {@link IServerOperationInterceptor instead}. Deprecated since HAPI FHIR 2.3 - */ -@Deprecated -public interface IJpaServerInterceptor extends IServerInterceptor { - - /** - * This method is invoked by the JPA DAOs when a resource has been newly created in the database. - * It will be invoked within the current transaction scope. - *

- * This method is called within the server database transaction, after the - * entity has been persisted and flushed to the database. It may not be a good - * candidate for security decisions depending on how your database is set up. - * Any exceptions thrown by this method will result in the transaction being - * rolled back. Thrown exceptions should be of a type which - * subclasses {@link BaseServerResponseException}. - *

- * - * @param theDetails The request details - * @param theResourceTable The actual created entity - */ - void resourceCreated(ActionRequestDetails theDetails, ResourceTable theResourceTable); - - /** - * This method is invoked by the JPA DAOs when a resource has been updated in the database. - * It will be invoked within the current transaction scope. - *

- * This method is called within the server database transaction, after the - * entity has been persisted and flushed to the database. It may not be a good - * candidate for security decisions depending on how your database is set up. - * Any exceptions thrown by this method will result in the transaction being - * rolled back. Thrown exceptions should be of a type which - * subclasses {@link BaseServerResponseException}. - *

- * - * @param theDetails The request details - * @param theResourceTable The actual updated entity - */ - void resourceUpdated(ActionRequestDetails theDetails, ResourceTable theResourceTable); - - /** - * This method is invoked by the JPA DAOs when a resource has been updated in the database. - * It will be invoked within the current transaction scope. - *

- * This method is called within the server database transaction, after the - * entity has been persisted and flushed to the database. It may not be a good - * candidate for security decisions depending on how your database is set up. - * Any exceptions thrown by this method will result in the transaction being - * rolled back. Thrown exceptions should be of a type which - * subclasses {@link BaseServerResponseException}. - *

- * - * @param theDetails The request details - * @param theResourceTable The actual updated entity - */ - void resourceDeleted(ActionRequestDetails theDetails, ResourceTable theResourceTable); - -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/JpaServerInterceptorAdapter.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/JpaServerInterceptorAdapter.java deleted file mode 100644 index 63cf2a21610..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/JpaServerInterceptorAdapter.java +++ /dev/null @@ -1,43 +0,0 @@ -package ca.uhn.fhir.jpa.interceptor; - -/* - * #%L - * HAPI FHIR JPA Server - * %% - * Copyright (C) 2014 - 2017 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import ca.uhn.fhir.jpa.entity.ResourceTable; -import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter; - -public class JpaServerInterceptorAdapter extends InterceptorAdapter implements IJpaServerInterceptor { - - @Override - public void resourceCreated(ActionRequestDetails theDetails, ResourceTable theResourceTable) { - // nothing - } - - @Override - public void resourceUpdated(ActionRequestDetails theDetails, ResourceTable theResourceTable) { - // nothing - } - - @Override - public void resourceDeleted(ActionRequestDetails theDetails, ResourceTable theResourceTable) { - // nothing - } - -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/WebSocketSubscriptionDstu2Interceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/WebSocketSubscriptionDstu2Interceptor.java deleted file mode 100644 index efa3a703e7e..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/WebSocketSubscriptionDstu2Interceptor.java +++ /dev/null @@ -1,93 +0,0 @@ - -package ca.uhn.fhir.jpa.interceptor; - -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; - -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; - -/*- - * #%L - * HAPI FHIR JPA Server - * %% - * Copyright (C) 2014 - 2017 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import ca.uhn.fhir.jpa.dao.IFhirResourceDao; -import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription; -import ca.uhn.fhir.jpa.entity.ResourceTable; -import ca.uhn.fhir.model.dstu2.resource.Subscription; -import ca.uhn.fhir.rest.api.RequestTypeEnum; -import ca.uhn.fhir.rest.api.server.RequestDetails; -import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter; - -public class WebSocketSubscriptionDstu2Interceptor extends InterceptorAdapter implements IJpaServerInterceptor { - - private static final Logger logger = LoggerFactory.getLogger(WebSocketSubscriptionDstu2Interceptor.class); - - @Autowired - @Qualifier("mySubscriptionDaoDstu2") - private IFhirResourceDao reference; - - private IFhirResourceDaoSubscription casted; - - @PostConstruct - public void postConstruct(){ - casted = (IFhirResourceDaoSubscription) reference; - } - - @Override - public void resourceCreated(ActionRequestDetails theDetails, ResourceTable theResourceTable) { - } - - @Override - public void resourceUpdated(ActionRequestDetails theDetails, ResourceTable theResourceTable) { - } - - @Override - public void resourceDeleted(ActionRequestDetails theDetails, ResourceTable theResourceTable) { - } - - /** - * Checks for websocket subscriptions - * @param theRequestDetails - * A bean containing details about the request that is about to be processed, including details such as the - * resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been - * pulled out of the {@link HttpServletRequest servlet request}. - * @param theResponseObject - * The actual object which is being streamed to the client as a response - * @return - */ - @Override - public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) { - if (theRequestDetails.getResourceName() == null || - theRequestDetails.getResourceName().isEmpty() || - theRequestDetails.getResourceName().equals("Subscription")) { - return super.outgoingResponse(theRequestDetails, theResponseObject); - } - - if (theRequestDetails.getRequestType().equals(RequestTypeEnum.POST) || theRequestDetails.getRequestType().equals(RequestTypeEnum.PUT)) { - logger.info("Found POST or PUT for a non-subscription resource"); - casted.pollForNewUndeliveredResources(theRequestDetails.getResourceName()); - } - - return super.outgoingResponse(theRequestDetails, theResponseObject); - } -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/WebSocketSubscriptionDstu3Interceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/WebSocketSubscriptionDstu3Interceptor.java deleted file mode 100644 index 9162fd3b9ca..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/WebSocketSubscriptionDstu3Interceptor.java +++ /dev/null @@ -1,107 +0,0 @@ - -package ca.uhn.fhir.jpa.interceptor; - -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.hl7.fhir.dstu3.model.Subscription; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; - -/*- - * #%L - * HAPI FHIR JPA Server - * %% - * Copyright (C) 2014 - 2017 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import ca.uhn.fhir.jpa.dao.IFhirResourceDao; -import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription; -import ca.uhn.fhir.rest.api.RequestTypeEnum; -import ca.uhn.fhir.rest.api.RestOperationTypeEnum; -import ca.uhn.fhir.rest.api.server.RequestDetails; -import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; -import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter; - -public class WebSocketSubscriptionDstu3Interceptor extends ServerOperationInterceptorAdapter { - - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(WebSocketSubscriptionDstu3Interceptor.class); - - private IFhirResourceDaoSubscription mySubscriptionDaoCasted; - - @Autowired - @Qualifier("mySubscriptionDaoDstu3") - private IFhirResourceDao mySubscriptionDao; - - @Override - public boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException { - if (theRequestDetails.getRestOperationType().equals(RestOperationTypeEnum.DELETE)) { - mySubscriptionDaoCasted.pollForNewUndeliveredResources(theRequestDetails.getResourceName()); - } - - return super.incomingRequestPostProcessed(theRequestDetails, theRequest, theResponse); - } - - /** - * Checks for websocket subscriptions - * - * @param theRequestDetails - * A bean containing details about the request that is about to be processed, including details such as the - * resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been - * pulled out of the {@link HttpServletRequest servlet request}. - * @param theResponseObject - * The actual object which is being streamed to the client as a response - * @return - */ - @Override - public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) { - if (theRequestDetails.getResourceName() == null || - theRequestDetails.getResourceName().isEmpty() || - theRequestDetails.getResourceName().equals("Subscription")) { - return super.outgoingResponse(theRequestDetails, theResponseObject); - } - - if (theRequestDetails.getRequestType().equals(RequestTypeEnum.POST) || theRequestDetails.getRequestType().equals(RequestTypeEnum.PUT)) { - ourLog.info("Found POST or PUT for a non-subscription resource"); - mySubscriptionDaoCasted.pollForNewUndeliveredResources(theRequestDetails.getResourceName()); - } - - return super.outgoingResponse(theRequestDetails, theResponseObject); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @PostConstruct - public void postConstruct() { - mySubscriptionDaoCasted = (IFhirResourceDaoSubscription) mySubscriptionDao; - } - - @Override - public void resourceCreated(RequestDetails theRequest, IBaseResource theResource) { - // nothing - } - - @Override - public void resourceDeleted(RequestDetails theRequest, IBaseResource theResource) { - // nothing - } - - @Override - public void resourceUpdated(RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource) { - // nothing - } -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/r4/WebSocketSubscriptionR4Interceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/r4/WebSocketSubscriptionR4Interceptor.java deleted file mode 100644 index d29bb817347..00000000000 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/r4/WebSocketSubscriptionR4Interceptor.java +++ /dev/null @@ -1,107 +0,0 @@ - -package ca.uhn.fhir.jpa.interceptor.r4; - -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.hl7.fhir.r4.model.Subscription; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; - -/*- - * #%L - * HAPI FHIR JPA Server - * %% - * Copyright (C) 2014 - 2017 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import ca.uhn.fhir.jpa.dao.IFhirResourceDao; -import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription; -import ca.uhn.fhir.rest.api.RequestTypeEnum; -import ca.uhn.fhir.rest.api.RestOperationTypeEnum; -import ca.uhn.fhir.rest.api.server.RequestDetails; -import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; -import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter; - -public class WebSocketSubscriptionR4Interceptor extends ServerOperationInterceptorAdapter { - - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(WebSocketSubscriptionR4Interceptor.class); - - private IFhirResourceDaoSubscription mySubscriptionDaoCasted; - - @Autowired - @Qualifier("mySubscriptionDaoR4") - private IFhirResourceDao mySubscriptionDao; - - @Override - public boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException { - if (theRequestDetails.getRestOperationType().equals(RestOperationTypeEnum.DELETE)) { - mySubscriptionDaoCasted.pollForNewUndeliveredResources(theRequestDetails.getResourceName()); - } - - return super.incomingRequestPostProcessed(theRequestDetails, theRequest, theResponse); - } - - /** - * Checks for websocket subscriptions - * - * @param theRequestDetails - * A bean containing details about the request that is about to be processed, including details such as the - * resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been - * pulled out of the {@link HttpServletRequest servlet request}. - * @param theResponseObject - * The actual object which is being streamed to the client as a response - * @return - */ - @Override - public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) { - if (theRequestDetails.getResourceName() == null || - theRequestDetails.getResourceName().isEmpty() || - theRequestDetails.getResourceName().equals("Subscription")) { - return super.outgoingResponse(theRequestDetails, theResponseObject); - } - - if (theRequestDetails.getRequestType().equals(RequestTypeEnum.POST) || theRequestDetails.getRequestType().equals(RequestTypeEnum.PUT)) { - ourLog.info("Found POST or PUT for a non-subscription resource"); - mySubscriptionDaoCasted.pollForNewUndeliveredResources(theRequestDetails.getResourceName()); - } - - return super.outgoingResponse(theRequestDetails, theResponseObject); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @PostConstruct - public void postConstruct() { - mySubscriptionDaoCasted = (IFhirResourceDaoSubscription) mySubscriptionDao; - } - - @Override - public void resourceCreated(RequestDetails theRequest, IBaseResource theResource) { - // nothing - } - - @Override - public void resourceDeleted(RequestDetails theRequest, IBaseResource theResource) { - // nothing - } - - @Override - public void resourceUpdated(RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource) { - // nothing - } -} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionInterceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionInterceptor.java index 4871408275c..70ebb4f0c8d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionInterceptor.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionInterceptor.java @@ -18,6 +18,8 @@ import org.springframework.messaging.SubscribableChannel; import org.springframework.messaging.support.ExecutorSubscribableChannel; import org.springframework.messaging.support.GenericMessage; import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.transaction.support.TransactionSynchronizationAdapter; +import org.springframework.transaction.support.TransactionSynchronizationManager; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @@ -40,9 +42,12 @@ public abstract class BaseSubscriptionInterceptor extends ServerOperationInterce private MessageHandler mySubscriptionCheckingSubscriber; private ConcurrentHashMap myIdToSubscription = new ConcurrentHashMap<>(); private Logger ourLog = LoggerFactory.getLogger(BaseSubscriptionInterceptor.class); - private SubscriptionDeliveringRestHookSubscriber mySubscriptionDeliverySubscriber; private BlockingQueue myExecutorQueue; + public ConcurrentHashMap getIdToSubscription() { + return myIdToSubscription; + } + public abstract Subscription.SubscriptionChannelType getChannelType(); public SubscribableChannel getProcessingChannel() { @@ -90,7 +95,7 @@ public abstract class BaseSubscriptionInterceptor extends ServerOperationInterce } } - public BlockingQueue getExecutorQueue() { + public BlockingQueue getExecutorQueueForUnitTests() { return myExecutorQueue; } @@ -122,31 +127,33 @@ public abstract class BaseSubscriptionInterceptor extends ServerOperationInterce if (mySubscriptionActivatingSubscriber == null) { mySubscriptionActivatingSubscriber = new SubscriptionActivatingSubscriber(getSubscriptionDao(), myIdToSubscription, getChannelType(), myProcessingChannel); } - myProcessingChannel.subscribe(mySubscriptionActivatingSubscriber); + getProcessingChannel().subscribe(mySubscriptionActivatingSubscriber); } if (mySubscriptionCheckingSubscriber == null) { mySubscriptionCheckingSubscriber = new SubscriptionCheckingSubscriber(getSubscriptionDao(), myIdToSubscription, getChannelType(), myProcessingChannel); } - myProcessingChannel.subscribe(mySubscriptionCheckingSubscriber); + getProcessingChannel().subscribe(mySubscriptionCheckingSubscriber); - if (mySubscriptionDeliverySubscriber == null) { - mySubscriptionDeliverySubscriber = new SubscriptionDeliveringRestHookSubscriber(getSubscriptionDao(), myIdToSubscription, getChannelType(), myProcessingChannel); - } - myProcessingChannel.subscribe(mySubscriptionDeliverySubscriber); + registerDeliverySubscriber(); } + protected abstract void registerDeliverySubscriber(); + @SuppressWarnings("unused") @PreDestroy public void preDestroy() { if (myAutoActivateSubscriptions) { - myProcessingChannel.unsubscribe(mySubscriptionActivatingSubscriber); + getProcessingChannel().unsubscribe(mySubscriptionActivatingSubscriber); } - myProcessingChannel.unsubscribe(mySubscriptionCheckingSubscriber); - myProcessingChannel.unsubscribe(mySubscriptionDeliverySubscriber); + getProcessingChannel().unsubscribe(mySubscriptionCheckingSubscriber); + + unregisterDeliverySubscriber(); } + protected abstract void unregisterDeliverySubscriber(); + @Override public void resourceCreated(RequestDetails theRequest, IBaseResource theResource) { ResourceModifiedMessage msg = new ResourceModifiedMessage(); @@ -173,7 +180,15 @@ public abstract class BaseSubscriptionInterceptor extends ServerOperationInterce submitResourceModified(msg); } - private void submitResourceModified(ResourceModifiedMessage theMsg) { - myProcessingChannel.send(new GenericMessage<>(theMsg)); + private void submitResourceModified(final ResourceModifiedMessage theMsg) { + /* + * We only actually submit this item work working after the + */ + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { + @Override + public void afterCommit() { + getProcessingChannel().send(new GenericMessage<>(theMsg)); + } + }); } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionRestHookInterceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionRestHookInterceptor.java new file mode 100644 index 00000000000..d54fbdeaddb --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionRestHookInterceptor.java @@ -0,0 +1,19 @@ +package ca.uhn.fhir.jpa.subscription; + +public abstract class BaseSubscriptionRestHookInterceptor extends BaseSubscriptionInterceptor { + private SubscriptionDeliveringRestHookSubscriber mySubscriptionDeliverySubscriber; + + @Override + protected void registerDeliverySubscriber() { + if (mySubscriptionDeliverySubscriber == null) { + mySubscriptionDeliverySubscriber = new SubscriptionDeliveringRestHookSubscriber(getSubscriptionDao(), getIdToSubscription(), getChannelType(), getProcessingChannel()); + } + getProcessingChannel().subscribe(mySubscriptionDeliverySubscriber); + } + + + @Override + protected void unregisterDeliverySubscriber() { + getProcessingChannel().unsubscribe(mySubscriptionDeliverySubscriber); + } +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionWebsocketInterceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionWebsocketInterceptor.java new file mode 100644 index 00000000000..45d56057c42 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionWebsocketInterceptor.java @@ -0,0 +1,37 @@ +package ca.uhn.fhir.jpa.subscription; + +import ca.uhn.fhir.jpa.dao.data.IResourceTableDao; +import ca.uhn.fhir.jpa.dao.data.ISubscriptionFlaggedResourceDataDao; +import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.PlatformTransactionManager; + +public abstract class BaseSubscriptionWebsocketInterceptor extends BaseSubscriptionInterceptor { + private SubscriptionDeliveringWebsocketSubscriber mySubscriptionDeliverySubscriber; + + @Autowired + private ISubscriptionFlaggedResourceDataDao mySubscriptionFlaggedResourceDataDao; + + @Autowired + private ISubscriptionTableDao mySubscriptionTableDao; + + @Autowired + private PlatformTransactionManager myTxManager; + + @Autowired + private IResourceTableDao myResourceTableDao; + + @Override + protected void registerDeliverySubscriber() { + if (mySubscriptionDeliverySubscriber == null) { + mySubscriptionDeliverySubscriber = new SubscriptionDeliveringWebsocketSubscriber(getSubscriptionDao(), getIdToSubscription(), getChannelType(), getProcessingChannel(), myTxManager, mySubscriptionFlaggedResourceDataDao, mySubscriptionTableDao, myResourceTableDao); + } + getProcessingChannel().subscribe(mySubscriptionDeliverySubscriber); + } + + + @Override + protected void unregisterDeliverySubscriber() { + getProcessingChannel().unsubscribe(mySubscriptionDeliverySubscriber); + } +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingSubscriber.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingSubscriber.java index 786035490b8..04c8c67fb9d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingSubscriber.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingSubscriber.java @@ -9,7 +9,6 @@ import org.hl7.fhir.r4.model.Subscription; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessagingException; import org.springframework.messaging.SubscribableChannel; @@ -41,12 +40,16 @@ public class SubscriptionActivatingSubscriber extends BaseSubscriptionSubscriber IPrimitiveType status = ctx.newTerser().getSingleValueOrNull(subscription, SUBSCRIPTION_STATUS, IPrimitiveType.class); String statusString = status.getValueAsString(); - String oldStatus = Subscription.SubscriptionStatus.REQUESTED.toCode(); - if (oldStatus.equals(statusString)) { - String newStatus = Subscription.SubscriptionStatus.ACTIVE.toCode(); - status.setValueAsString(newStatus); - ourLog.info("Activating subscription {} from status {} to {}", subscription.getIdElement().toUnqualifiedVersionless().getValue(), oldStatus, newStatus); + String requestedStatus = Subscription.SubscriptionStatus.REQUESTED.toCode(); + String activeStatus = Subscription.SubscriptionStatus.ACTIVE.toCode(); + if (requestedStatus.equals(statusString)) { + status.setValueAsString(activeStatus); + ourLog.info("Activating subscription {} from status {} to {}", subscription.getIdElement().toUnqualified().getValue(), requestedStatus, activeStatus); getSubscriptionDao().update(subscription); + getIdToSubscription().put(subscription.getIdElement().getIdPart(), subscription); + } else if (activeStatus.equals(statusString)) { + ourLog.info("Newly created active subscription {}", subscription.getIdElement().toUnqualified().getValue()); + getIdToSubscription().put(subscription.getIdElement().getIdPart(), subscription); } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionCheckingSubscriber.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionCheckingSubscriber.java index 805e4c7eebc..ea778674269 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionCheckingSubscriber.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionCheckingSubscriber.java @@ -77,12 +77,6 @@ public class SubscriptionCheckingSubscriber extends BaseSubscriptionSubscriber { criteria += "&_id=" + resourceType + "/" + resourceId; criteria = massageCriteria(criteria); - try { - Thread.sleep(500); - } catch (InterruptedException theE) { - theE.printStackTrace(); - } - IBundleProvider results = performSearch(criteria); if (results.size() == 0) { continue; @@ -90,11 +84,10 @@ public class SubscriptionCheckingSubscriber extends BaseSubscriptionSubscriber { // should just be one resource as it was filtered by the id for (IBaseResource nextBase : results.getResources(0, results.size())) { - IBaseResource next = (IBaseResource) nextBase; - ourLog.info("Found match: queueing rest-hook notification for resource: {}", next.getIdElement()); + ourLog.info("Found match: queueing rest-hook notification for resource: {}", nextBase.getIdElement()); ResourceDeliveryMessage deliveryMsg = new ResourceDeliveryMessage(); - deliveryMsg.setPayoad(next); + deliveryMsg.setPayoad(nextBase); deliveryMsg.setSubscription(nextSubscription); deliveryMsg.setOperationType(msg.getOperationType()); deliveryMsg.setPayloadId(msg.getId()); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionDeliveringWebsocketSubscriber.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionDeliveringWebsocketSubscriber.java new file mode 100644 index 00000000000..88b57c10d7d --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionDeliveringWebsocketSubscriber.java @@ -0,0 +1,142 @@ +package ca.uhn.fhir.jpa.subscription; + +import ca.uhn.fhir.jpa.dao.IDao; +import ca.uhn.fhir.jpa.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.dao.data.IResourceTableDao; +import ca.uhn.fhir.jpa.dao.data.ISubscriptionFlaggedResourceDataDao; +import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao; +import ca.uhn.fhir.jpa.entity.ResourceTable; +import ca.uhn.fhir.jpa.entity.SubscriptionFlaggedResource; +import ca.uhn.fhir.jpa.entity.SubscriptionTable; +import ca.uhn.fhir.model.api.IResource; +import ca.uhn.fhir.rest.api.EncodingEnum; +import ca.uhn.fhir.rest.api.RestOperationTypeEnum; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; +import ca.uhn.fhir.rest.gclient.IClientExecutable; +import org.apache.commons.lang3.ObjectUtils; +import org.hl7.fhir.instance.model.api.IAnyResource; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.hl7.fhir.r4.model.Subscription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessagingException; +import org.springframework.messaging.SubscribableChannel; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; +import org.springframework.transaction.support.TransactionTemplate; + +import java.util.concurrent.ConcurrentHashMap; + +public class SubscriptionDeliveringWebsocketSubscriber extends BaseSubscriptionSubscriber { + private final PlatformTransactionManager myTxManager; + private final ISubscriptionFlaggedResourceDataDao mySubscriptionFlaggedResourceDao; + private final ISubscriptionTableDao mySubscriptionTableDao; + private final IResourceTableDao myResourceTableDao; + private Logger ourLog = LoggerFactory.getLogger(SubscriptionDeliveringWebsocketSubscriber.class); + + public SubscriptionDeliveringWebsocketSubscriber(IFhirResourceDao theSubscriptionDao, ConcurrentHashMap theIdToSubscription, Subscription.SubscriptionChannelType theChannelType, SubscribableChannel theProcessingChannel, PlatformTransactionManager theTxManager, ISubscriptionFlaggedResourceDataDao theSubscriptionFlaggedResourceDataDao, ISubscriptionTableDao theSubscriptionTableDao, IResourceTableDao theResourceTableDao) { + super(theSubscriptionDao, theIdToSubscription, theChannelType, theProcessingChannel); + + myTxManager = theTxManager; + mySubscriptionFlaggedResourceDao = theSubscriptionFlaggedResourceDataDao; + mySubscriptionTableDao = theSubscriptionTableDao; + myResourceTableDao = theResourceTableDao; + } + + + @Override + public void handleMessage(final Message theMessage) throws MessagingException { + if (!(theMessage.getPayload() instanceof ResourceDeliveryMessage)) { + return; + } + + final ResourceDeliveryMessage msg = (ResourceDeliveryMessage) theMessage.getPayload(); + + if (!subscriptionTypeApplies(getContext(), msg.getSubscription())) { + return; + } + + TransactionTemplate txTemplate = new TransactionTemplate(myTxManager); + txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED); + txTemplate.execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus status) { + IBaseResource payload = msg.getPayoad(); + Long payloadPid = extractResourcePid(payload); + ResourceTable payloadTable = myResourceTableDao.findOne(payloadPid); + + IBaseResource subscription = msg.getSubscription(); + Long subscriptionPid = extractResourcePid(subscription); + SubscriptionTable subscriptionTable = mySubscriptionTableDao.findOneByResourcePid(subscriptionPid); + + ourLog.info("Adding new resource {} for subscription: {}", payload.getIdElement().toUnqualified().getValue(), subscription.getIdElement().toUnqualifiedVersionless().getValue()); + + SubscriptionFlaggedResource candidate = new SubscriptionFlaggedResource(); + candidate.setResource(payloadTable); + candidate.setSubscription(subscriptionTable); + candidate.setVersion(payload.getIdElement().getVersionIdPartAsLong()); + + mySubscriptionFlaggedResourceDao.save(candidate); + } + }); + + RestOperationTypeEnum operationType = msg.getOperationType(); + IBaseResource subscription = msg.getSubscription(); + + // Grab the endpoint from the subscription + IPrimitiveType endpoint = getContext().newTerser().getSingleValueOrNull(subscription, BaseSubscriptionInterceptor.SUBSCRIPTION_ENDPOINT, IPrimitiveType.class); + String endpointUrl = endpoint.getValueAsString(); + + // Grab the payload type (encoding mimetype ) from the subscription + IPrimitiveType payload = getContext().newTerser().getSingleValueOrNull(subscription, BaseSubscriptionInterceptor.SUBSCRIPTION_PAYLOAD, IPrimitiveType.class); + String payloadString = payload.getValueAsString(); + if (payloadString.contains(";")) { + payloadString = payloadString.substring(0, payloadString.indexOf(';')); + } + payloadString = payloadString.trim(); + EncodingEnum payloadType = EncodingEnum.forContentType(payloadString); + payloadType = ObjectUtils.defaultIfNull(payloadType, EncodingEnum.XML); + + getContext().getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); + IGenericClient client = getContext().newRestfulGenericClient(endpointUrl); + + IBaseResource payloadResource = msg.getPayoad(); + + IClientExecutable operation; + switch (operationType) { + case CREATE: + operation = client.create().resource(payloadResource); + break; + case UPDATE: + operation = client.update().resource(payloadResource); + break; + case DELETE: + operation = client.delete().resourceById(msg.getPayloadId()); + break; + default: + ourLog.warn("Ignoring delivery message of type: {}", msg.getOperationType()); + return; + } + + operation.encoded(payloadType); + + ourLog.info("Delivering {} rest-hook payload {} for {}", operationType, payloadResource.getIdElement().toUnqualified().getValue(), subscription.getIdElement().toUnqualifiedVersionless().getValue()); + + operation.execute(); + + } + + private Long extractResourcePid(IBaseResource thePayoad) { + Long pid; + if (thePayoad instanceof IResource) { + pid = IDao.RESOURCE_PID.get((IResource) thePayoad); + } else { + pid = IDao.RESOURCE_PID.get((IAnyResource) thePayoad); + } + return pid; + } +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/RestHookSubscriptionDstu2Interceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/RestHookSubscriptionDstu2Interceptor.java similarity index 90% rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/RestHookSubscriptionDstu2Interceptor.java rename to hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/RestHookSubscriptionDstu2Interceptor.java index 1e889a97a76..8c9721eacbb 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/RestHookSubscriptionDstu2Interceptor.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/RestHookSubscriptionDstu2Interceptor.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.interceptor; +package ca.uhn.fhir.jpa.subscription.dstu2; /*- * #%L @@ -21,12 +21,12 @@ package ca.uhn.fhir.jpa.interceptor; */ import ca.uhn.fhir.jpa.dao.IFhirResourceDao; -import ca.uhn.fhir.jpa.subscription.BaseSubscriptionInterceptor; +import ca.uhn.fhir.jpa.subscription.BaseSubscriptionRestHookInterceptor; import ca.uhn.fhir.model.dstu2.resource.Subscription; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -public class RestHookSubscriptionDstu2Interceptor extends BaseSubscriptionInterceptor { +public class RestHookSubscriptionDstu2Interceptor extends BaseSubscriptionRestHookInterceptor { @Autowired @Qualifier("mySubscriptionDaoDstu2") private IFhirResourceDao mySubscriptionDao; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/SubscriptionWebsocketHandlerDstu2.java similarity index 98% rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java rename to hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/SubscriptionWebsocketHandlerDstu2.java index 7565681ea54..e20de474463 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/SubscriptionWebsocketHandlerDstu2.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.subscription; +package ca.uhn.fhir.jpa.subscription.dstu2; /* * #%L @@ -27,6 +27,7 @@ import java.util.concurrent.ScheduledFuture; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; +import ca.uhn.fhir.jpa.subscription.ISubscriptionWebsocketHandler; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.hl7.fhir.instance.model.api.IBaseResource; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketReturnResourceHandlerDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/SubscriptionWebsocketReturnResourceHandlerDstu2.java similarity index 99% rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketReturnResourceHandlerDstu2.java rename to hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/SubscriptionWebsocketReturnResourceHandlerDstu2.java index 3ba08bf1c0b..93609253ec0 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketReturnResourceHandlerDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/SubscriptionWebsocketReturnResourceHandlerDstu2.java @@ -1,5 +1,5 @@ -package ca.uhn.fhir.jpa.subscription; +package ca.uhn.fhir.jpa.subscription.dstu2; import java.io.IOException; import java.util.List; @@ -8,6 +8,7 @@ import java.util.concurrent.ScheduledFuture; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; +import ca.uhn.fhir.jpa.subscription.ISubscriptionWebsocketHandler; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.hl7.fhir.instance.model.api.IBaseResource; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/WebSocketSubscriptionDstu2Interceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/WebSocketSubscriptionDstu2Interceptor.java new file mode 100644 index 00000000000..89cef2cd79c --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu2/WebSocketSubscriptionDstu2Interceptor.java @@ -0,0 +1,45 @@ + +package ca.uhn.fhir.jpa.subscription.dstu2; + +import ca.uhn.fhir.jpa.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.subscription.BaseSubscriptionWebsocketInterceptor; +import ca.uhn.fhir.model.dstu2.resource.Subscription; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2017 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +public class WebSocketSubscriptionDstu2Interceptor extends BaseSubscriptionWebsocketInterceptor { + + @Autowired + @Qualifier("mySubscriptionDaoDstu2") + private IFhirResourceDao mySubscriptionDao; + + @Override + public org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType getChannelType() { + return org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType.WEBSOCKET; + } + + @Override + protected IFhirResourceDao getSubscriptionDao() { + return mySubscriptionDao; + } +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/RestHookSubscriptionDstu3Interceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/RestHookSubscriptionDstu3Interceptor.java similarity index 90% rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/RestHookSubscriptionDstu3Interceptor.java rename to hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/RestHookSubscriptionDstu3Interceptor.java index dce43f92387..70a38c80048 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/RestHookSubscriptionDstu3Interceptor.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/RestHookSubscriptionDstu3Interceptor.java @@ -1,5 +1,4 @@ - -package ca.uhn.fhir.jpa.interceptor; +package ca.uhn.fhir.jpa.subscription.dstu3; /*- * #%L @@ -22,22 +21,21 @@ package ca.uhn.fhir.jpa.interceptor; */ import ca.uhn.fhir.jpa.dao.IFhirResourceDao; -import ca.uhn.fhir.jpa.subscription.BaseSubscriptionInterceptor; +import ca.uhn.fhir.jpa.subscription.BaseSubscriptionRestHookInterceptor; import org.hl7.fhir.dstu3.model.Subscription; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -public class RestHookSubscriptionDstu3Interceptor extends BaseSubscriptionInterceptor -{ +public class RestHookSubscriptionDstu3Interceptor extends BaseSubscriptionRestHookInterceptor { + @Autowired + @Qualifier("mySubscriptionDaoDstu3") + private IFhirResourceDao mySubscriptionDao; + @Override protected IFhirResourceDao getSubscriptionDao() { return mySubscriptionDao; } - @Autowired - @Qualifier("mySubscriptionDaoDstu3") - private IFhirResourceDao mySubscriptionDao; - public void setSubscriptionDao(IFhirResourceDao theSubscriptionDao) { mySubscriptionDao = theSubscriptionDao; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/SubscriptionWebsocketHandlerDstu3.java similarity index 98% rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java rename to hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/SubscriptionWebsocketHandlerDstu3.java index 26d3efc59ad..7429429e911 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/SubscriptionWebsocketHandlerDstu3.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.subscription; +package ca.uhn.fhir.jpa.subscription.dstu3; /* * #%L @@ -27,6 +27,7 @@ import java.util.concurrent.ScheduledFuture; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; +import ca.uhn.fhir.jpa.subscription.ISubscriptionWebsocketHandler; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.hl7.fhir.dstu3.model.IdType; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketReturnResourceHandlerDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/SubscriptionWebsocketReturnResourceHandlerDstu3.java similarity index 99% rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketReturnResourceHandlerDstu3.java rename to hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/SubscriptionWebsocketReturnResourceHandlerDstu3.java index 03cbf8f31e7..0b9e886cd41 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketReturnResourceHandlerDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/SubscriptionWebsocketReturnResourceHandlerDstu3.java @@ -1,5 +1,5 @@ -package ca.uhn.fhir.jpa.subscription; +package ca.uhn.fhir.jpa.subscription.dstu3; import java.io.IOException; import java.util.List; @@ -8,6 +8,7 @@ import java.util.concurrent.ScheduledFuture; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; +import ca.uhn.fhir.jpa.subscription.ISubscriptionWebsocketHandler; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.hl7.fhir.dstu3.model.IdType; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/WebSocketSubscriptionDstu3Interceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/WebSocketSubscriptionDstu3Interceptor.java new file mode 100644 index 00000000000..1aefc178664 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dstu3/WebSocketSubscriptionDstu3Interceptor.java @@ -0,0 +1,57 @@ + +package ca.uhn.fhir.jpa.subscription.dstu3; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import ca.uhn.fhir.jpa.subscription.BaseSubscriptionWebsocketInterceptor; +import org.hl7.fhir.dstu3.model.Subscription; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2017 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import ca.uhn.fhir.jpa.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription; +import ca.uhn.fhir.rest.api.RequestTypeEnum; +import ca.uhn.fhir.rest.api.RestOperationTypeEnum; +import ca.uhn.fhir.rest.api.server.RequestDetails; +import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; +import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter; + +public class WebSocketSubscriptionDstu3Interceptor extends BaseSubscriptionWebsocketInterceptor { + + @Autowired + @Qualifier("mySubscriptionDaoDstu3") + private IFhirResourceDao mySubscriptionDao; + + @Override + public org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType getChannelType() { + return org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType.WEBSOCKET; + } + + @Override + protected IFhirResourceDao getSubscriptionDao() { + return mySubscriptionDao; + } +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/r4/RestHookSubscriptionR4Interceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/r4/RestHookSubscriptionR4Interceptor.java similarity index 91% rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/r4/RestHookSubscriptionR4Interceptor.java rename to hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/r4/RestHookSubscriptionR4Interceptor.java index 5090fdb61cd..c86bfb4b68f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/interceptor/r4/RestHookSubscriptionR4Interceptor.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/r4/RestHookSubscriptionR4Interceptor.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.interceptor.r4; +package ca.uhn.fhir.jpa.subscription.r4; /*- * #%L @@ -21,11 +21,11 @@ package ca.uhn.fhir.jpa.interceptor.r4; */ import ca.uhn.fhir.jpa.dao.IFhirResourceDao; -import ca.uhn.fhir.jpa.subscription.BaseSubscriptionInterceptor; +import ca.uhn.fhir.jpa.subscription.BaseSubscriptionRestHookInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -public class RestHookSubscriptionR4Interceptor extends BaseSubscriptionInterceptor { +public class RestHookSubscriptionR4Interceptor extends BaseSubscriptionRestHookInterceptor { @Autowired @Qualifier("mySubscriptionDaoR4") private IFhirResourceDao mySubscriptionDao; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/r4/WebSocketSubscriptionR4Interceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/r4/WebSocketSubscriptionR4Interceptor.java new file mode 100644 index 00000000000..ae9810281ab --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/r4/WebSocketSubscriptionR4Interceptor.java @@ -0,0 +1,44 @@ +package ca.uhn.fhir.jpa.subscription.r4; + +import ca.uhn.fhir.jpa.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.subscription.BaseSubscriptionWebsocketInterceptor; +import org.hl7.fhir.r4.model.Subscription; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2017 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +public class WebSocketSubscriptionR4Interceptor extends BaseSubscriptionWebsocketInterceptor { + + @Autowired + @Qualifier("mySubscriptionDaoR4") + private IFhirResourceDao mySubscriptionDao; + + @Override + public Subscription.SubscriptionChannelType getChannelType() { + return Subscription.SubscriptionChannelType.WEBSOCKET; + } + + @Override + protected IFhirResourceDao getSubscriptionDao() { + return mySubscriptionDao; + } +} diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2InterceptorTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2InterceptorTest.java index 8badff2c2e3..a9270fdb273 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2InterceptorTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2InterceptorTest.java @@ -1,19 +1,16 @@ package ca.uhn.fhir.jpa.dao.dstu2; -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import org.hl7.fhir.dstu3.model.Bundle.BundleType; -import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.dao.DeleteMethodOutcome; +import ca.uhn.fhir.model.dstu2.resource.Bundle; +import ca.uhn.fhir.model.dstu2.resource.Patient; +import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum; +import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum; +import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.rest.api.server.RequestDetails; +import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor; +import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter; +import ca.uhn.fhir.util.TestUtil; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.After; @@ -24,26 +21,15 @@ import org.mockito.ArgumentCaptor; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import ca.uhn.fhir.jpa.dao.DaoConfig; -import ca.uhn.fhir.jpa.dao.DaoMethodOutcome; -import ca.uhn.fhir.jpa.dao.DeleteMethodOutcome; -import ca.uhn.fhir.jpa.entity.ResourceTable; -import ca.uhn.fhir.jpa.interceptor.IJpaServerInterceptor; -import ca.uhn.fhir.jpa.interceptor.JpaServerInterceptorAdapter; -import ca.uhn.fhir.model.dstu2.resource.Bundle; -import ca.uhn.fhir.model.dstu2.resource.Patient; -import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum; -import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum; -import ca.uhn.fhir.model.primitive.IdDt; -import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor; -import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; -import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; -import ca.uhn.fhir.util.TestUtil; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2InterceptorTest.class); - private IJpaServerInterceptor myJpaInterceptor; - private JpaServerInterceptorAdapter myJpaInterceptorAdapter = new JpaServerInterceptorAdapter(); + private IServerOperationInterceptor myJpaInterceptor; + private ServerOperationInterceptorAdapter myJpaInterceptorAdapter = new ServerOperationInterceptorAdapter(); @After public void after() { @@ -54,7 +40,7 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test { @Before public void before() { - myJpaInterceptor = mock(IJpaServerInterceptor.class); + myJpaInterceptor = mock(IServerOperationInterceptor.class); myDaoConfig.getInterceptors().add(myJpaInterceptor); myDaoConfig.getInterceptors().add(myJpaInterceptorAdapter); } @@ -66,17 +52,17 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test { p.addName().addFamily("PATIENT"); Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong(); - ArgumentCaptor detailsCapt; - ArgumentCaptor tableCapt; + ArgumentCaptor detailsCapt; + ArgumentCaptor tableCapt; - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); - assertNotNull(tableCapt.getValue().getId()); - assertEquals(id, tableCapt.getValue().getId()); + assertNotNull(tableCapt.getValue().getIdElement().getIdPart()); + assertEquals(id, tableCapt.getValue().getIdElement().getIdPartAsLong()); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(0)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); /* @@ -87,8 +73,8 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test { Long id2 = myPatientDao.create(p, "Patient?family=PATIENT", mySrd).getId().getIdPartAsLong(); assertEquals(id, id2); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); verify(myJpaInterceptor, times(0)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); @@ -102,14 +88,14 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test { myPatientDao.delete(new IdDt("Patient", id), mySrd); - ArgumentCaptor detailsCapt; - ArgumentCaptor tableCapt; + ArgumentCaptor detailsCapt; + ArgumentCaptor tableCapt; - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceDeleted(detailsCapt.capture(), tableCapt.capture()); - assertNotNull(tableCapt.getValue().getId()); - assertEquals(id, tableCapt.getValue().getId()); + assertNotNull(tableCapt.getValue().getIdElement().getIdPart()); + assertEquals(id, tableCapt.getValue().getIdElement().getIdPartAsLong()); } @@ -132,14 +118,14 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test { Long id2 = myPatientDao.update(p, mySrd).getId().getIdPartAsLong(); assertEquals(id, id2); - ArgumentCaptor detailsCapt; - ArgumentCaptor tableCapt; + ArgumentCaptor detailsCapt; + ArgumentCaptor tableCapt; - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); - assertNotNull(tableCapt.getValue().getId()); - assertEquals(id, tableCapt.getValue().getId()); + assertNotNull(tableCapt.getValue().getIdElement().getIdPart()); + assertEquals(id, tableCapt.getValue().getIdElement().getIdPartAsLong()); /* * Now do a conditional update @@ -151,11 +137,11 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test { id2 = myPatientDao.update(p, "Patient?family=PATIENT1", mySrd).getId().getIdPartAsLong(); assertEquals(id, id2); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); verify(myJpaInterceptor, times(2)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); - assertEquals(id, tableCapt.getAllValues().get(2).getId()); + assertEquals(id, tableCapt.getAllValues().get(2).getIdElement().getIdPartAsLong()); /* * Now do a conditional update where none will match (so this is actually a create) @@ -166,11 +152,11 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test { id2 = myPatientDao.update(p, "Patient?family=ZZZ", mySrd).getId().getIdPartAsLong(); assertNotEquals(id, id2); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(2)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); verify(myJpaInterceptor, times(2)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); - assertEquals(id2, tableCapt.getAllValues().get(3).getId()); + assertEquals(id2, tableCapt.getAllValues().get(3).getIdElement().getIdPartAsLong()); } @@ -347,6 +333,7 @@ public class FhirResourceDaoDstu2InterceptorTest extends BaseJpaDstu2Test { .setUrl("Patient?name=PATIENT") .setMethod(HTTPVerbEnum.DELETE); Bundle resp = mySystemDao.transaction(mySrd, xactBundle); + assertNotNull(resp); verify(myRequestOperationCallback, times(2)).resourceDeleted(any(IBaseResource.class)); verify(myRequestOperationCallback, times(2)).resourceCreated(any(IBaseResource.class)); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3InterceptorTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3InterceptorTest.java index 226a6a88892..3285422969e 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3InterceptorTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3InterceptorTest.java @@ -1,35 +1,36 @@ package ca.uhn.fhir.jpa.dao.dstu3; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.dao.DeleteMethodOutcome; +import ca.uhn.fhir.rest.api.server.RequestDetails; +import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor; +import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter; +import ca.uhn.fhir.util.TestUtil; +import org.hl7.fhir.dstu3.model.Bundle; +import org.hl7.fhir.dstu3.model.Bundle.BundleType; +import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.*; import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; -import org.hl7.fhir.dstu3.model.*; -import org.hl7.fhir.dstu3.model.Bundle.BundleType; -import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.instance.model.api.IIdType; -import org.junit.*; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import ca.uhn.fhir.jpa.dao.DaoConfig; -import ca.uhn.fhir.jpa.dao.DeleteMethodOutcome; -import ca.uhn.fhir.jpa.entity.ResourceTable; -import ca.uhn.fhir.jpa.interceptor.IJpaServerInterceptor; -import ca.uhn.fhir.jpa.interceptor.JpaServerInterceptorAdapter; -import ca.uhn.fhir.rest.api.server.RequestDetails; -import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; -import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor; -import ca.uhn.fhir.util.TestUtil; - public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3InterceptorTest.class); - private IJpaServerInterceptor myJpaInterceptor; - private JpaServerInterceptorAdapter myJpaInterceptorAdapter = new JpaServerInterceptorAdapter(); + private IServerOperationInterceptor myJpaInterceptor; + private ServerOperationInterceptorAdapter myJpaInterceptorAdapter = new ServerOperationInterceptorAdapter(); private IServerOperationInterceptor myServerOperationInterceptor; @After @@ -41,7 +42,7 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test { @Before public void before() { - myJpaInterceptor = mock(IJpaServerInterceptor.class); + myJpaInterceptor = mock(IServerOperationInterceptor.class); myServerOperationInterceptor = mock(IServerOperationInterceptor.class, new Answer() { @Override @@ -64,17 +65,17 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test { p.addName().setFamily("PATIENT"); Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong(); - ArgumentCaptor detailsCapt; - ArgumentCaptor tableCapt; + ArgumentCaptor detailsCapt; + ArgumentCaptor tableCapt; - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); - assertNotNull(tableCapt.getValue().getId()); - assertEquals(id, tableCapt.getValue().getId()); + assertNotNull(tableCapt.getValue().getIdElement().getIdPartAsLong()); + assertEquals(id, tableCapt.getValue().getIdElement().getIdPartAsLong()); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(0)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); /* @@ -85,8 +86,8 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test { Long id2 = myPatientDao.create(p, "Patient?family=PATIENT", mySrd).getId().getIdPartAsLong(); assertEquals(id, id2); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); verify(myJpaInterceptor, times(0)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); @@ -107,14 +108,14 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test { myPatientDao.delete(new IdType("Patient", id), mySrd); - ArgumentCaptor detailsCapt; - ArgumentCaptor tableCapt; + ArgumentCaptor detailsCapt; + ArgumentCaptor tableCapt; - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceDeleted(detailsCapt.capture(), tableCapt.capture()); - assertNotNull(tableCapt.getValue().getId()); - assertEquals(id, tableCapt.getValue().getId()); + assertNotNull(tableCapt.getValue().getIdElement().getIdPartAsLong()); + assertEquals(id, tableCapt.getValue().getIdElement().getIdPartAsLong()); } @@ -130,14 +131,14 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test { Long id2 = myPatientDao.update(p, mySrd).getId().getIdPartAsLong(); assertEquals(id, id2); - ArgumentCaptor detailsCapt; - ArgumentCaptor tableCapt; + ArgumentCaptor detailsCapt; + ArgumentCaptor tableCapt; - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); - assertNotNull(tableCapt.getValue().getId()); - assertEquals(id, tableCapt.getValue().getId()); + assertNotNull(tableCapt.getValue().getIdElement().getIdPartAsLong()); + assertEquals(id, tableCapt.getValue().getIdElement().getIdPartAsLong()); /* * Now do a conditional update @@ -149,11 +150,11 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test { id2 = myPatientDao.update(p, "Patient?family=PATIENT1", mySrd).getId().getIdPartAsLong(); assertEquals(id, id2); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); verify(myJpaInterceptor, times(2)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); - assertEquals(id, tableCapt.getAllValues().get(2).getId()); + assertEquals(id, tableCapt.getAllValues().get(2).getIdElement().getIdPartAsLong()); /* * Now do a conditional update where none will match (so this is actually a create) @@ -164,11 +165,11 @@ public class FhirResourceDaoDstu3InterceptorTest extends BaseJpaDstu3Test { id2 = myPatientDao.update(p, "Patient?family=ZZZ", mySrd).getId().getIdPartAsLong(); assertNotEquals(id, id2); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(2)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); verify(myJpaInterceptor, times(2)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); - assertEquals(id2, tableCapt.getAllValues().get(3).getId()); + assertEquals(id2, tableCapt.getAllValues().get(3).getIdElement().getIdPartAsLong()); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4InterceptorTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4InterceptorTest.java index 37352a6e185..ec7cc6efab5 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4InterceptorTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4InterceptorTest.java @@ -1,35 +1,36 @@ package ca.uhn.fhir.jpa.dao.r4; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.dao.DeleteMethodOutcome; +import ca.uhn.fhir.rest.api.server.RequestDetails; +import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor; +import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter; +import ca.uhn.fhir.util.TestUtil; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Bundle.BundleType; +import org.hl7.fhir.r4.model.Bundle.HTTPVerb; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Patient; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.*; import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; -import org.hl7.fhir.r4.model.*; -import org.hl7.fhir.r4.model.Bundle.BundleType; -import org.hl7.fhir.r4.model.Bundle.HTTPVerb; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.instance.model.api.IIdType; -import org.junit.*; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import ca.uhn.fhir.jpa.dao.DaoConfig; -import ca.uhn.fhir.jpa.dao.DeleteMethodOutcome; -import ca.uhn.fhir.jpa.entity.ResourceTable; -import ca.uhn.fhir.jpa.interceptor.IJpaServerInterceptor; -import ca.uhn.fhir.jpa.interceptor.JpaServerInterceptorAdapter; -import ca.uhn.fhir.rest.api.server.RequestDetails; -import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; -import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor; -import ca.uhn.fhir.util.TestUtil; - public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4InterceptorTest.class); - private IJpaServerInterceptor myJpaInterceptor; - private JpaServerInterceptorAdapter myJpaInterceptorAdapter = new JpaServerInterceptorAdapter(); + private IServerOperationInterceptor myJpaInterceptor; + private ServerOperationInterceptorAdapter myJpaInterceptorAdapter = new ServerOperationInterceptorAdapter(); private IServerOperationInterceptor myServerOperationInterceptor; @After @@ -41,7 +42,7 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test { @Before public void before() { - myJpaInterceptor = mock(IJpaServerInterceptor.class); + myJpaInterceptor = mock(IServerOperationInterceptor.class); myServerOperationInterceptor = mock(IServerOperationInterceptor.class, new Answer() { @Override @@ -64,17 +65,17 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test { p.addName().setFamily("PATIENT"); Long id = myPatientDao.create(p, mySrd).getId().getIdPartAsLong(); - ArgumentCaptor detailsCapt; - ArgumentCaptor tableCapt; + ArgumentCaptor detailsCapt; + ArgumentCaptor tableCapt; - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); - assertNotNull(tableCapt.getValue().getId()); - assertEquals(id, tableCapt.getValue().getId()); + assertNotNull(tableCapt.getValue().getIdElement().getIdPart()); + assertEquals(id, tableCapt.getValue().getIdElement().getIdPartAsLong()); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(0)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); /* @@ -85,8 +86,8 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test { Long id2 = myPatientDao.create(p, "Patient?family=PATIENT", mySrd).getId().getIdPartAsLong(); assertEquals(id, id2); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); verify(myJpaInterceptor, times(0)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); @@ -107,14 +108,14 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test { myPatientDao.delete(new IdType("Patient", id), mySrd); - ArgumentCaptor detailsCapt; - ArgumentCaptor tableCapt; + ArgumentCaptor detailsCapt; + ArgumentCaptor tableCapt; - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceDeleted(detailsCapt.capture(), tableCapt.capture()); - assertNotNull(tableCapt.getValue().getId()); - assertEquals(id, tableCapt.getValue().getId()); + assertNotNull(tableCapt.getValue().getIdElement().getIdPart()); + assertEquals(id, tableCapt.getValue().getIdElement().getIdPartAsLong()); } @@ -130,14 +131,14 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test { Long id2 = myPatientDao.update(p, mySrd).getId().getIdPartAsLong(); assertEquals(id, id2); - ArgumentCaptor detailsCapt; - ArgumentCaptor tableCapt; + ArgumentCaptor detailsCapt; + ArgumentCaptor tableCapt; - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); - assertNotNull(tableCapt.getValue().getId()); - assertEquals(id, tableCapt.getValue().getId()); + assertNotNull(tableCapt.getValue().getIdElement().getIdPart()); + assertEquals(id, tableCapt.getValue().getIdElement().getIdPartAsLong()); /* * Now do a conditional update @@ -149,11 +150,11 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test { id2 = myPatientDao.update(p, "Patient?family=PATIENT1", mySrd).getId().getIdPartAsLong(); assertEquals(id, id2); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(1)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); verify(myJpaInterceptor, times(2)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); - assertEquals(id, tableCapt.getAllValues().get(2).getId()); + assertEquals(id, tableCapt.getAllValues().get(2).getIdElement().getIdPartAsLong()); /* * Now do a conditional update where none will match (so this is actually a create) @@ -164,11 +165,11 @@ public class FhirResourceDaoR4InterceptorTest extends BaseJpaR4Test { id2 = myPatientDao.update(p, "Patient?family=ZZZ", mySrd).getId().getIdPartAsLong(); assertNotEquals(id, id2); - detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); - tableCapt = ArgumentCaptor.forClass(ResourceTable.class); + detailsCapt = ArgumentCaptor.forClass(RequestDetails.class); + tableCapt = ArgumentCaptor.forClass(IBaseResource.class); verify(myJpaInterceptor, times(2)).resourceUpdated(detailsCapt.capture(), tableCapt.capture()); verify(myJpaInterceptor, times(2)).resourceCreated(detailsCapt.capture(), tableCapt.capture()); - assertEquals(id2, tableCapt.getAllValues().get(3).getId()); + assertEquals(id2, tableCapt.getAllValues().get(3).getIdElement().getIdPartAsLong()); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/BaseResourceProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/BaseResourceProviderDstu2Test.java index 0831a17db58..40f4f871892 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/BaseResourceProviderDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/BaseResourceProviderDstu2Test.java @@ -22,7 +22,7 @@ import org.springframework.web.servlet.DispatcherServlet; import ca.uhn.fhir.jpa.config.WebsocketDstu2Config; import ca.uhn.fhir.jpa.config.WebsocketDstu2DispatcherConfig; import ca.uhn.fhir.jpa.dao.dstu2.BaseJpaDstu2Test; -import ca.uhn.fhir.jpa.interceptor.RestHookSubscriptionDstu2Interceptor; +import ca.uhn.fhir.jpa.subscription.dstu2.RestHookSubscriptionDstu2Interceptor; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider; import ca.uhn.fhir.model.dstu2.resource.Bundle; diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/BaseResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/BaseResourceProviderDstu3Test.java index 2e99f38bca2..5017d332482 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/BaseResourceProviderDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/BaseResourceProviderDstu3Test.java @@ -26,7 +26,7 @@ import ca.uhn.fhir.jpa.config.dstu3.WebsocketDstu3DispatcherConfig; import ca.uhn.fhir.jpa.dao.data.ISearchDao; import ca.uhn.fhir.jpa.dao.dstu3.BaseJpaDstu3Test; import ca.uhn.fhir.jpa.dao.dstu3.SearchParamRegistryDstu3; -import ca.uhn.fhir.jpa.interceptor.RestHookSubscriptionDstu3Interceptor; +import ca.uhn.fhir.jpa.subscription.dstu3.RestHookSubscriptionDstu3Interceptor; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc; import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainDstu3; diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java index 36eb014ef51..058103a0cd2 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java @@ -26,7 +26,7 @@ import ca.uhn.fhir.jpa.config.r4.WebsocketR4DispatcherConfig; import ca.uhn.fhir.jpa.dao.data.ISearchDao; import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test; import ca.uhn.fhir.jpa.dao.r4.SearchParamRegistryR4; -import ca.uhn.fhir.jpa.interceptor.r4.RestHookSubscriptionR4Interceptor; +import ca.uhn.fhir.jpa.subscription.r4.RestHookSubscriptionR4Interceptor; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc; import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4; diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu2Test.java index bb1e519d0e0..94258f49e75 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu2Test.java @@ -50,6 +50,7 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test { @After public void afterUnregisterRestHookListener() { + ourLog.info("** AFTER **"); for (IIdType next : mySubscriptionIds) { ourClient.delete().resourceById(next).execute(); } @@ -279,11 +280,11 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test { } private void waitForQueueToDrain() throws InterruptedException { - ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueue().size()); - while (ourRestHookSubscriptionInterceptor.getExecutorQueue().size() > 0) { + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); + while (ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size() > 0) { Thread.sleep(250); } - ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueue().size()); + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); } @BeforeClass diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu3Test.java index af7cfe3ecba..6ced8ff6046 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu3Test.java @@ -21,8 +21,6 @@ import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.*; -import org.springframework.messaging.support.ChannelInterceptor; -import org.springframework.messaging.support.ExecutorSubscribableChannel; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; @@ -153,11 +151,11 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test { } private void waitForQueueToDrain() throws InterruptedException { - ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueue().size()); - while (ourRestHookSubscriptionInterceptor.getExecutorQueue().size() > 0) { + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); + while (ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size() > 0) { Thread.sleep(250); } - ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueue().size()); + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); } @Test diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java index cf10502e1b5..5d00e8fd508 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java @@ -53,6 +53,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B @After public void afterUnregisterRestHookListener() { + ourLog.info("** AFTER **"); myDaoConfig.setAllowMultipleDelete(true); ourLog.info("Deleting all subscriptions"); ourClient.delete().resourceConditionalByUrl("Subscription?status=active").execute(); @@ -73,10 +74,20 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B ourUpdatedObservations.clear(); } - private Subscription createSubscription(String criteria, String payload, String endpoint) { + private void waitForQueueToDrain() throws InterruptedException { + Thread.sleep(1000); + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); + while (ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size() > 0) { + Thread.sleep(250); + } + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); + } + + + private Subscription createSubscription(String criteria, String payload, String endpoint) throws InterruptedException { Subscription subscription = new Subscription(); subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)"); - subscription.setStatus(SubscriptionStatusEnum.ACTIVE); + subscription.setStatus(SubscriptionStatusEnum.REQUESTED); subscription.setCriteria(criteria); Channel channel = new Channel(); @@ -88,10 +99,11 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute(); subscription.setId(methodOutcome.getId().getIdPart()); + waitForQueueToDrain(); return subscription; } - private Observation sendObservation(String code, String system) { + private Observation sendObservation(String code, String system) throws InterruptedException { Observation observation = new Observation(); CodeableConceptDt codeableConcept = new CodeableConceptDt(); observation.setCode(codeableConcept); @@ -106,6 +118,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B String observationId = methodOutcome.getId().getIdPart(); observation.setId(observationId); + waitForQueueToDrain(); return observation; } @@ -123,7 +136,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B Observation observation1 = sendObservation(code, "SNOMED-CT"); // Should see 1 subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(1, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -137,7 +150,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B Observation observation2 = sendObservation(code, "SNOMED-CT"); // Should see two subscription notifications - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(3, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -146,7 +159,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B Observation observationTemp3 = sendObservation(code, "SNOMED-CT"); // Should see only one subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -159,7 +172,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B ourClient.update().resource(observation3).withId(observation3.getIdElement()).execute(); // Should see no subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -173,7 +186,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B ourClient.update().resource(observation3a).withId(observation3a.getIdElement()).execute(); // Should see only one subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(1, ourUpdatedObservations.size()); @@ -196,7 +209,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B Observation observation1 = sendObservation(code, "SNOMED-CT"); // Should see 1 subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(1, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -210,7 +223,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B Observation observation2 = sendObservation(code, "SNOMED-CT"); // Should see two subscription notifications - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(3, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -219,7 +232,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B Observation observationTemp3 = sendObservation(code, "SNOMED-CT"); // Should see only one subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -232,7 +245,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B ourClient.update().resource(observation3).withId(observation3.getIdElement()).execute(); // Should see no subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -246,7 +259,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B ourClient.update().resource(observation3a).withId(observation3a.getIdElement()).execute(); // Should see only one subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(1, ourUpdatedObservations.size()); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test.java index 8073726e378..ad412750bdf 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test.java @@ -64,7 +64,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test extends B ourUpdatedObservations.clear(); } - private Subscription createSubscription(String criteria, String payload, String endpoint) { + private Subscription createSubscription(String criteria, String payload, String endpoint) throws InterruptedException { Subscription subscription = new Subscription(); subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)"); subscription.setStatus(Subscription.SubscriptionStatus.ACTIVE); @@ -79,10 +79,19 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test extends B MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute(); subscription.setId(methodOutcome.getId().getIdPart()); + waitForQueueToDrain(); return subscription; } - private Observation sendObservation(String code, String system) { + private void waitForQueueToDrain() throws InterruptedException { + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); + while (ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size() > 0) { + Thread.sleep(250); + } + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); + } + + private Observation sendObservation(String code, String system) throws InterruptedException { Observation observation = new Observation(); CodeableConcept codeableConcept = new CodeableConcept(); observation.setCode(codeableConcept); @@ -97,6 +106,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test extends B String observationId = methodOutcome.getId().getIdPart(); observation.setId(observationId); + waitForQueueToDrain(); return observation; } @@ -187,7 +197,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test extends B Observation observation1 = sendObservation(code, "SNOMED-CT"); // Should see 1 subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(1, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -201,7 +211,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test extends B Observation observation2 = sendObservation(code, "SNOMED-CT"); // Should see two subscription notifications - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(3, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -210,7 +220,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test extends B Observation observationTemp3 = sendObservation(code, "SNOMED-CT"); // Should see only one subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -223,7 +233,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test extends B ourClient.update().resource(observation3).withId(observation3.getIdElement()).execute(); // Should see no subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -237,7 +247,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test extends B ourClient.update().resource(observation3a).withId(observation3a.getIdElement()).execute(); // Should see only one subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(1, ourUpdatedObservations.size()); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestR4Test.java index bbb4f165f68..46cfcda1a38 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestR4Test.java @@ -316,11 +316,11 @@ public class RestHookTestR4Test extends BaseResourceProviderR4Test { } private void waitForQueueToDrain() throws InterruptedException { - ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueue().size()); - while (ourRestHookSubscriptionInterceptor.getExecutorQueue().size() > 0) { + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); + while (ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size() > 0) { Thread.sleep(250); } - ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueue().size()); + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); } @BeforeClass diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestWithInterceptorRegisteredToDaoConfigR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestWithInterceptorRegisteredToDaoConfigR4Test.java index 43ccafbf509..677265d67c8 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestWithInterceptorRegisteredToDaoConfigR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestWithInterceptorRegisteredToDaoConfigR4Test.java @@ -64,7 +64,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigR4Test extends Base ourUpdatedObservations.clear(); } - private Subscription createSubscription(String criteria, String payload, String endpoint) { + private Subscription createSubscription(String criteria, String payload, String endpoint) throws InterruptedException { Subscription subscription = new Subscription(); subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)"); subscription.setStatus(Subscription.SubscriptionStatus.ACTIVE); @@ -79,10 +79,19 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigR4Test extends Base MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute(); subscription.setId(methodOutcome.getId().getIdPart()); + waitForQueueToDrain(); return subscription; } - private Observation sendObservation(String code, String system) { + private void waitForQueueToDrain() throws InterruptedException { + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); + while (ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size() > 0) { + Thread.sleep(250); + } + ourLog.info("QUEUE HAS {} ITEMS", ourRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); + } + + private Observation sendObservation(String code, String system) throws InterruptedException { Observation observation = new Observation(); CodeableConcept codeableConcept = new CodeableConcept(); observation.setCode(codeableConcept); @@ -97,6 +106,8 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigR4Test extends Base String observationId = methodOutcome.getId().getIdPart(); observation.setId(observationId); + waitForQueueToDrain(); + return observation; } @@ -117,7 +128,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigR4Test extends Base Thread.sleep(500); assertEquals(1, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); - + Subscription subscriptionTemp = ourClient.read(Subscription.class, subscription2.getId()); Assert.assertNotNull(subscriptionTemp); @@ -131,7 +142,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigR4Test extends Base Thread.sleep(500); assertEquals(3, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); - + ourClient.delete().resourceById(new IdDt("Subscription", subscription2.getId())).execute(); Observation observationTemp3 = sendObservation(code, "SNOMED-CT"); @@ -187,10 +198,10 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigR4Test extends Base Observation observation1 = sendObservation(code, "SNOMED-CT"); // Should see 1 subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(1, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); - + Subscription subscriptionTemp = ourClient.read(Subscription.class, subscription2.getId()); Assert.assertNotNull(subscriptionTemp); @@ -201,16 +212,16 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigR4Test extends Base Observation observation2 = sendObservation(code, "SNOMED-CT"); // Should see two subscription notifications - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(3, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); - + ourClient.delete().resourceById(new IdDt("Subscription", subscription2.getId())).execute(); Observation observationTemp3 = sendObservation(code, "SNOMED-CT"); // Should see only one subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -223,7 +234,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigR4Test extends Base ourClient.update().resource(observation3).withId(observation3.getIdElement()).execute(); // Should see no subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(0, ourUpdatedObservations.size()); @@ -237,7 +248,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigR4Test extends Base ourClient.update().resource(observation3a).withId(observation3a.getIdElement()).execute(); // Should see only one subscription notification - Thread.sleep(500); + waitForQueueToDrain(); assertEquals(4, ourCreatedObservations.size()); assertEquals(1, ourUpdatedObservations.size()); diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java index c032b6feb86..003d45439a0 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java @@ -1326,7 +1326,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer searchParams, List matches) throws FHIRException { - ourLog.info("listResources of {} - {}", type, searchParams); + public void listResources(Object theAppInfo, String theType, List theSearchParams, List theMatches) throws FHIRException { + ourLog.info("listResources of {} - {}", theType, theSearchParams); + + if (theSearchParams.size() == 1) { + String name = theSearchParams.get(0).getName(); + if ("name".equals(name)) { + Patient p = new Patient(); + p.addName() + .setFamily(theSearchParams.get(0).getValues().get(0).toString()) + .addGiven("GIVEN1") + .addGiven("GIVEN2"); + p.addName() + .addGiven("GivenOnly1") + .addGiven("GivenOnly2"); + theMatches.add(p); + + p = new Patient(); + p.addName() + .addGiven("GivenOnlyB1") + .addGiven("GivenOnlyB2"); + theMatches.add(p); + + } + } } @Override - public Bundle search(Object appInfo, String type, List searchParams) throws FHIRException { - ourLog.info("search on {} - {}", type, searchParams); + public Bundle search(Object theAppInfo, String theType, List theSearchParams) throws FHIRException { + ourLog.info("search on {} - {}", theType, theSearchParams); return null; } } diff --git a/pom.xml b/pom.xml index 0b1839ffd38..431e6c6693f 100644 --- a/pom.xml +++ b/pom.xml @@ -384,7 +384,7 @@ 5.2.10.Final 5.4.1.Final - 5.7.0.Final + 5.7.1.Final 5.5.4 2.5.3 1.8 @@ -451,7 +451,7 @@ com.squareup.okhttp3 okhttp - 3.4.1 + 3.8.1 commons-cli @@ -877,7 +877,7 @@ org.springframework.data spring-data-jpa - 1.10.4.RELEASE + 1.11.6.RELEASE org.springframework diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 1ced9cc2d7d..cf652388631 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -19,8 +19,11 @@
  • Apache HttpCore (FHIR Client): 4.4.5 -> 4.4.6
  • Phloc Commons (Schematron Validator): 4.4.6 -> 4.4.11
  • Hibernate (JPA): 5.2.9 -> 5.2.10
  • -
  • Spring (JPA): 4.3.7.RELEASE -> 4.3.10.RELEASE
  • -
  • Thymeleaf (Testpage Overlay): 3.0.2.RELEASE -> 3.0.7.RELEASE
  • +
  • Hibernate Search (JPA): 5.7.0 -> 5.7.1
  • +
  • Spring (JPA): 4.3.7 -> 4.3.10
  • +
  • Spring Data JPA (JPA): 1.10.4 -> 1.11.6
  • +
  • Thymeleaf (Testpage Overlay): 3.0.2 -> 3.0.7
  • +
  • OkHttp (Android): 3.4.1 -> 3.8.1
  • ]]>