|
|
|
|
@@ -2,6 +2,9 @@ package ca.uhn.fhir.jpa.starter;
|
|
|
|
|
|
|
|
|
|
import ca.uhn.fhir.context.FhirContext;
|
|
|
|
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
|
|
|
|
import ca.uhn.fhir.empi.provider.EmpiProviderDstu3;
|
|
|
|
|
import ca.uhn.fhir.empi.provider.EmpiProviderR4;
|
|
|
|
|
import ca.uhn.fhir.empi.rules.config.EmpiSettings;
|
|
|
|
|
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
|
|
|
|
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
|
|
|
|
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
|
|
|
|
@@ -10,6 +13,8 @@ import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
|
|
|
|
import ca.uhn.fhir.jpa.binstore.BinaryStorageInterceptor;
|
|
|
|
|
import ca.uhn.fhir.jpa.bulk.BulkDataExportProvider;
|
|
|
|
|
import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor;
|
|
|
|
|
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
|
|
|
|
import ca.uhn.fhir.jpa.partition.PartitionManagementProvider;
|
|
|
|
|
import ca.uhn.fhir.jpa.provider.GraphQLProvider;
|
|
|
|
|
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
|
|
|
|
|
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
|
|
|
|
|
@@ -37,11 +42,9 @@ import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
|
|
|
|
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
|
|
|
|
|
import ca.uhn.fhir.validation.IValidatorModule;
|
|
|
|
|
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.TreeSet;
|
|
|
|
|
import org.hl7.fhir.dstu3.model.Bundle;
|
|
|
|
|
import org.hl7.fhir.r4.model.Bundle.BundleType;
|
|
|
|
|
import org.hl7.fhir.dstu3.model.Meta;
|
|
|
|
|
import org.hl7.fhir.r4.model.Bundle.BundleType;
|
|
|
|
|
import org.springframework.context.ApplicationContext;
|
|
|
|
|
import org.springframework.http.HttpHeaders;
|
|
|
|
|
import org.springframework.web.cors.CorsConfiguration;
|
|
|
|
|
@@ -49,7 +52,9 @@ import org.springframework.web.cors.CorsConfiguration;
|
|
|
|
|
import javax.servlet.ServletException;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
import java.util.TreeSet;
|
|
|
|
|
|
|
|
|
|
public class JpaRestfulServer extends RestfulServer {
|
|
|
|
|
|
|
|
|
|
@@ -65,12 +70,12 @@ public class JpaRestfulServer extends RestfulServer {
|
|
|
|
|
* specified in the properties file.
|
|
|
|
|
*/
|
|
|
|
|
ApplicationContext appCtx = (ApplicationContext) getServletContext()
|
|
|
|
|
.getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
|
|
|
|
|
.getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
|
|
|
|
|
// Customize supported resource types
|
|
|
|
|
Set<String> supportedResourceTypes = HapiProperties.getSupportedResourceTypes();
|
|
|
|
|
|
|
|
|
|
if (!supportedResourceTypes.isEmpty() && !supportedResourceTypes.contains("SearchParameter")) {
|
|
|
|
|
supportedResourceTypes.add("SearchParameter");
|
|
|
|
|
supportedResourceTypes.add("SearchParameter");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!supportedResourceTypes.isEmpty()) {
|
|
|
|
|
@@ -115,30 +120,30 @@ public class JpaRestfulServer extends RestfulServer {
|
|
|
|
|
*/
|
|
|
|
|
if (fhirVersion == FhirVersionEnum.DSTU2) {
|
|
|
|
|
IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDao = appCtx
|
|
|
|
|
.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
|
|
|
|
|
.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
|
|
|
|
|
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao,
|
|
|
|
|
appCtx.getBean(DaoConfig.class));
|
|
|
|
|
appCtx.getBean(DaoConfig.class));
|
|
|
|
|
confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server");
|
|
|
|
|
setServerConformanceProvider(confProvider);
|
|
|
|
|
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
|
|
|
|
|
IFhirSystemDao<Bundle, Meta> systemDao = appCtx
|
|
|
|
|
.getBean("mySystemDaoDstu3", IFhirSystemDao.class);
|
|
|
|
|
.getBean("mySystemDaoDstu3", IFhirSystemDao.class);
|
|
|
|
|
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao,
|
|
|
|
|
appCtx.getBean(DaoConfig.class), appCtx.getBean(ISearchParamRegistry.class));
|
|
|
|
|
appCtx.getBean(DaoConfig.class), appCtx.getBean(ISearchParamRegistry.class));
|
|
|
|
|
confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server");
|
|
|
|
|
setServerConformanceProvider(confProvider);
|
|
|
|
|
} else if (fhirVersion == FhirVersionEnum.R4) {
|
|
|
|
|
IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDao = appCtx
|
|
|
|
|
.getBean("mySystemDaoR4", IFhirSystemDao.class);
|
|
|
|
|
.getBean("mySystemDaoR4", IFhirSystemDao.class);
|
|
|
|
|
JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao,
|
|
|
|
|
appCtx.getBean(DaoConfig.class), appCtx.getBean(ISearchParamRegistry.class));
|
|
|
|
|
appCtx.getBean(DaoConfig.class), appCtx.getBean(ISearchParamRegistry.class));
|
|
|
|
|
confProvider.setImplementationDescription("HAPI FHIR R4 Server");
|
|
|
|
|
setServerConformanceProvider(confProvider);
|
|
|
|
|
} else if (fhirVersion == FhirVersionEnum.R5) {
|
|
|
|
|
IFhirSystemDao<org.hl7.fhir.r5.model.Bundle, org.hl7.fhir.r5.model.Meta> systemDao = appCtx
|
|
|
|
|
.getBean("mySystemDaoR5", IFhirSystemDao.class);
|
|
|
|
|
.getBean("mySystemDaoR5", IFhirSystemDao.class);
|
|
|
|
|
JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao,
|
|
|
|
|
appCtx.getBean(DaoConfig.class), appCtx.getBean(ISearchParamRegistry.class));
|
|
|
|
|
appCtx.getBean(DaoConfig.class), appCtx.getBean(ISearchParamRegistry.class));
|
|
|
|
|
confProvider.setImplementationDescription("HAPI FHIR R5 Server");
|
|
|
|
|
setServerConformanceProvider(confProvider);
|
|
|
|
|
} else {
|
|
|
|
|
@@ -219,7 +224,7 @@ public class JpaRestfulServer extends RestfulServer {
|
|
|
|
|
// manual triggering of a subscription delivery, enable this provider
|
|
|
|
|
if (false) { // <-- DISABLED RIGHT NOW
|
|
|
|
|
SubscriptionTriggeringProvider retriggeringProvider = appCtx
|
|
|
|
|
.getBean(SubscriptionTriggeringProvider.class);
|
|
|
|
|
.getBean(SubscriptionTriggeringProvider.class);
|
|
|
|
|
registerProvider(retriggeringProvider);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -245,7 +250,7 @@ public class JpaRestfulServer extends RestfulServer {
|
|
|
|
|
config.addExposedHeader("Location");
|
|
|
|
|
config.addExposedHeader("Content-Location");
|
|
|
|
|
config.setAllowedMethods(
|
|
|
|
|
Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
|
|
|
|
|
Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
|
|
|
|
|
config.setAllowCredentials(HapiProperties.getCorsAllowedCredentials());
|
|
|
|
|
|
|
|
|
|
// Create the interceptor and register it
|
|
|
|
|
@@ -256,13 +261,13 @@ public class JpaRestfulServer extends RestfulServer {
|
|
|
|
|
// If subscriptions are enabled, we want to register the interceptor that
|
|
|
|
|
// will activate them and match results against them
|
|
|
|
|
if (HapiProperties.getSubscriptionWebsocketEnabled() ||
|
|
|
|
|
HapiProperties.getSubscriptionEmailEnabled() ||
|
|
|
|
|
HapiProperties.getSubscriptionRestHookEnabled()) {
|
|
|
|
|
HapiProperties.getSubscriptionEmailEnabled() ||
|
|
|
|
|
HapiProperties.getSubscriptionRestHookEnabled()) {
|
|
|
|
|
// Loads subscription interceptors (SubscriptionActivatingInterceptor, SubscriptionMatcherInterceptor)
|
|
|
|
|
// with activation of scheduled subscription
|
|
|
|
|
|
|
|
|
|
SubscriptionSubmitInterceptorLoader subscriptionInterceptorLoader = appCtx
|
|
|
|
|
.getBean(SubscriptionSubmitInterceptorLoader.class);
|
|
|
|
|
.getBean(SubscriptionSubmitInterceptorLoader.class);
|
|
|
|
|
subscriptionInterceptorLoader.start();
|
|
|
|
|
|
|
|
|
|
// Subscription debug logging
|
|
|
|
|
@@ -275,43 +280,19 @@ public class JpaRestfulServer extends RestfulServer {
|
|
|
|
|
IInterceptorBroadcaster interceptorBroadcaster = appCtx.getBean(IInterceptorBroadcaster.class);
|
|
|
|
|
if (HapiProperties.getAllowCascadingDeletes()) {
|
|
|
|
|
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(getFhirContext(),
|
|
|
|
|
daoRegistry, interceptorBroadcaster);
|
|
|
|
|
daoRegistry, interceptorBroadcaster);
|
|
|
|
|
getInterceptorService().registerInterceptor(cascadingDeleteInterceptor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Binary Storage
|
|
|
|
|
if (HapiProperties.isBinaryStorageEnabled()) {
|
|
|
|
|
BinaryStorageInterceptor binaryStorageInterceptor = appCtx
|
|
|
|
|
.getBean(BinaryStorageInterceptor.class);
|
|
|
|
|
.getBean(BinaryStorageInterceptor.class);
|
|
|
|
|
getInterceptorService().registerInterceptor(binaryStorageInterceptor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validation
|
|
|
|
|
IValidatorModule validatorModule;
|
|
|
|
|
// FIXME KHS
|
|
|
|
|
/*
|
|
|
|
|
switch (fhirVersion) {
|
|
|
|
|
case DSTU2:
|
|
|
|
|
validatorModule = appCtx.getBean("myInstanceValidatorDstu2", IValidatorModule.class);
|
|
|
|
|
break;
|
|
|
|
|
case DSTU3:
|
|
|
|
|
validatorModule = appCtx.getBean("myInstanceValidatorDstu3", IValidatorModule.class);
|
|
|
|
|
break;
|
|
|
|
|
case R4:
|
|
|
|
|
validatorModule = appCtx.getBean("myInstanceValidatorR4", IValidatorModule.class);
|
|
|
|
|
break;
|
|
|
|
|
case R5:
|
|
|
|
|
validatorModule = appCtx.getBean("myInstanceValidatorR5", IValidatorModule.class);
|
|
|
|
|
break;
|
|
|
|
|
// These versions are not supported by HAPI FHIR JPA
|
|
|
|
|
case DSTU2_HL7ORG:
|
|
|
|
|
case DSTU2_1:
|
|
|
|
|
default:
|
|
|
|
|
validatorModule = null;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
validatorModule = appCtx.getBean(IValidatorModule.class);
|
|
|
|
|
IValidatorModule validatorModule = appCtx.getBean(IValidatorModule.class);
|
|
|
|
|
if (validatorModule != null) {
|
|
|
|
|
if (HapiProperties.getValidateRequestsEnabled()) {
|
|
|
|
|
RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
|
|
|
|
|
@@ -343,19 +324,21 @@ public class JpaRestfulServer extends RestfulServer {
|
|
|
|
|
});
|
|
|
|
|
DaoConfig config = appCtx.getBean(DaoConfig.class);
|
|
|
|
|
config.setBundleTypesAllowedForStorage(
|
|
|
|
|
Collections.unmodifiableSet(new TreeSet<>(allowedBundleTypes)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bulk Export
|
|
|
|
|
if (HapiProperties.getBulkExportEnabled()) {
|
|
|
|
|
registerProvider(appCtx.getBean(BulkDataExportProvider.class));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (HapiProperties.getEmpiEnabled()) {
|
|
|
|
|
// FIXME KHS
|
|
|
|
|
Collections.unmodifiableSet(new TreeSet<>(allowedBundleTypes)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bulk Export
|
|
|
|
|
if (HapiProperties.getBulkExportEnabled()) {
|
|
|
|
|
registerProvider(appCtx.getBean(BulkDataExportProvider.class));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (HapiProperties.getPartitioningEnabled()) {
|
|
|
|
|
PartitionSettings partitionSettings = appCtx.getBean(PartitionSettings.class);
|
|
|
|
|
partitionSettings.setPartitioningEnabled(true);
|
|
|
|
|
PartitionSettings.CrossPartitionReferenceMode mode = PartitionSettings.CrossPartitionReferenceMode.valueOf(HapiProperties.getPartitioningCrossPartitionReferenceMode());
|
|
|
|
|
partitionSettings.setAllowReferencesAcrossPartitions(mode);
|
|
|
|
|
partitionSettings.setIncludePartitionInSearchHashes(HapiProperties.getIncludePartitionInSearchHashes());
|
|
|
|
|
registerProvider(appCtx.getBean(PartitionManagementProvider.class));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|