diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..2421e38 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "files.exclude": { + "**/.classpath": true, + "**/.project": true, + "**/.settings": true, + "**/.factorypath": true + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5adb46c..661ee01 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ hapi-fhir-jpaserver-starter - 3.5.0 + 3.6.0 war @@ -351,9 +351,9 @@ org.apache.maven.plugins maven-compiler-plugin + 3.8.1 - 1.8 - 1.8 + 11 diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java index 092cd37..a3cd5d2 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -1,8 +1,11 @@ package ca.uhn.fhir.jpa.starter; + import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.jpa.api.config.DaoConfig.ClientIdStrategyEnum; import ca.uhn.fhir.rest.api.EncodingEnum; +import java.util.ArrayList; +import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -41,8 +44,17 @@ public class AppProperties { private ClientIdStrategyEnum client_id_strategy = ClientIdStrategyEnum.ALPHANUMERIC; private Validation validation = new Validation(); - private Tester tester = new Tester(); + private List tester = new ArrayList<>(); private Logger logger = new Logger(); + private Subscription subscription = new Subscription(); + + public Subscription getSubscription() { + return subscription; + } + + public void setSubscription(Subscription subscription) { + this.subscription = subscription; + } public Validation getValidation() { return validation; @@ -52,13 +64,6 @@ public class AppProperties { this.validation = validation; } - public Tester getTester() { - return tester; - } - - public void setTester(Tester tester) { - this.tester = tester; - } public Logger getLogger() { return logger; @@ -273,6 +278,14 @@ public class AppProperties { this.reuse_cached_search_results_millis = reuse_cached_search_results_millis; } + public List getTester() { + return tester; + } + + public void setTester(List tester) { + this.tester = tester; + } + public static class Logger { private String name = "fhirtest.access"; @@ -318,8 +331,17 @@ public class AppProperties { private String id = "home"; private String name = "Local Tester"; - private String address = "http://localhost:8080/fhir"; + private String server_address = "http://localhost:8080/fhir"; private Boolean refuse_to_fetch_third_party_urls = true; + private FhirVersionEnum fhir_version = FhirVersionEnum.R4; + + public FhirVersionEnum getFhir_version() { + return fhir_version; + } + + public void setFhir_version(FhirVersionEnum fhir_version) { + this.fhir_version = fhir_version; + } public String getId() { return id; @@ -337,12 +359,12 @@ public class AppProperties { this.name = name; } - public String getAddress() { - return address; + public String getServer_address() { + return server_address; } - public void setAddress(String address) { - this.address = address; + public void setServer_address(String server_address) { + this.server_address = server_address; } public Boolean getRefuse_to_fetch_third_party_urls() { @@ -375,4 +397,35 @@ public class AppProperties { this.responses_enabled = responses_enabled; } } + + public static class Subscription { + + public Boolean getEmail_enabled() { + return email_enabled; + } + + public void setEmail_enabled(Boolean email_enabled) { + this.email_enabled = email_enabled; + } + + public Boolean getResthook_enabled() { + return resthook_enabled; + } + + public void setResthook_enabled(Boolean resthook_enabled) { + this.resthook_enabled = resthook_enabled; + } + + public Boolean getWebsocket_enabled() { + return websocket_enabled; + } + + public void setWebsocket_enabled(Boolean websocket_enabled) { + this.websocket_enabled = websocket_enabled; + } + + private Boolean email_enabled = false; + private Boolean resthook_enabled = false; + private Boolean websocket_enabled = false; + } } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java index 5b89775..be03b5f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -16,7 +16,6 @@ public class Application { public static void main(String[] args) { - System.setProperty("spring.profiles.active", "r4"); System.setProperty("spring.batch.job.enabled", "false"); SpringApplication.run(Application.class, args); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java b/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java deleted file mode 100644 index a7bdc3e..0000000 --- a/src/main/java/ca/uhn/fhir/jpa/starter/ApplicationContext.java +++ /dev/null @@ -1,56 +0,0 @@ -package ca.uhn.fhir.jpa.starter; - -import ca.uhn.fhir.context.FhirVersionEnum; -import ca.uhn.fhir.jpa.empi.EmpiConfig; -import ca.uhn.fhir.jpa.empi.config.EmpiConsumerConfig; -import ca.uhn.fhir.jpa.empi.config.EmpiSubmitterConfig; -import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig; -import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig; -import ca.uhn.fhir.jpa.subscription.match.config.WebsocketDispatcherConfig; -import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; - -/** - * The class is unused for Spring Boot - */ -public class ApplicationContext extends AnnotationConfigWebApplicationContext { - - - public ApplicationContext() { - FhirVersionEnum fhirVersion = HapiProperties.getFhirVersion(); - this.getEnvironment().setActiveProfiles(fhirVersion.toString().toLowerCase()); - - - if (fhirVersion == FhirVersionEnum.DSTU2) { - register(FhirServerConfigDstu2.class, FhirServerConfigCommon.class); - } else if (fhirVersion == FhirVersionEnum.DSTU3) { - register(FhirServerConfigDstu3.class, FhirServerConfigCommon.class); - } else if (fhirVersion == FhirVersionEnum.R4) { - register(FhirServerConfigR4.class, FhirServerConfigCommon.class); - } else if (fhirVersion == FhirVersionEnum.R5) { - register(FhirServerConfigR5.class, FhirServerConfigCommon.class); - } else { - throw new IllegalStateException(); - } - - if (HapiProperties.getSubscriptionWebsocketEnabled()) { - register(WebsocketDispatcherConfig.class); - } - - if (HapiProperties.getSubscriptionEmailEnabled() - || HapiProperties.getSubscriptionRestHookEnabled() - || HapiProperties.getSubscriptionWebsocketEnabled()) { - register(SubscriptionSubmitterConfig.class); - register(SubscriptionProcessorConfig.class); - register(SubscriptionChannelConfig.class); - } - - if (HapiProperties.getEmpiEnabled()) { - register(EmpiSubmitterConfig.class); - register(EmpiConsumerConfig.class); - register(EmpiConfig.class); - } - - } - -} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java index 686bf45..e359e3d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -4,6 +4,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.IInterceptorService; +import ca.uhn.fhir.jpa.api.IDaoRegistry; import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; @@ -12,6 +13,7 @@ import ca.uhn.fhir.jpa.bulk.provider.BulkDataExportProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; import ca.uhn.fhir.jpa.partition.PartitionManagementProvider; import ca.uhn.fhir.jpa.provider.GraphQLProvider; +import ca.uhn.fhir.jpa.provider.IJpaSystemProvider; import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2; import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider; @@ -49,6 +51,9 @@ import javax.servlet.ServletException; import org.hl7.fhir.dstu3.model.Bundle; import org.hl7.fhir.dstu3.model.Meta; import org.hl7.fhir.r4.model.Bundle.BundleType; +import org.springframework.aop.framework.Advised; +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpHeaders; import org.springframework.web.cors.CorsConfiguration; @@ -58,6 +63,24 @@ public class BaseJpaRestfulServer extends RestfulServer { AppProperties hapiProperties; + @Autowired + DaoRegistry daoRegistry; + + @Autowired + DaoConfig daoConfig; + + @Autowired + ISearchParamRegistry searchParamRegistry; + + @Autowired + IFhirSystemDao fhirSystemDao; + + @Autowired + ResourceProviderFactory resourceProviders; + + @Autowired + IJpaSystemProvider jpaSystemProvider; + public BaseJpaRestfulServer(AppProperties appProperties) { this.hapiProperties = appProperties; } @@ -69,12 +92,13 @@ public class BaseJpaRestfulServer extends RestfulServer { protected void initialize() throws ServletException { super.initialize(); + ApplicationContext appCtx = (ApplicationContext) getServletContext() + .getAttribute("org.springframework.web.context.WebApplicationContext.ROOT"); + /* * Create a FhirContext object that uses the version of FHIR * specified in the properties file. */ - ApplicationContext appCtx = (ApplicationContext) getServletContext() - .getAttribute("org.springframework.web.context.WebApplicationContext.ROOT"); // Customize supported resource types Set supportedResourceTypes = HapiProperties.getSupportedResourceTypes(); @@ -83,37 +107,16 @@ public class BaseJpaRestfulServer extends RestfulServer { } if (!supportedResourceTypes.isEmpty()) { - DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class); daoRegistry.setSupportedResourceTypes(supportedResourceTypes); } - /* - * ResourceProviders are fetched from the Spring context - */ - FhirVersionEnum fhirVersion = HapiProperties.getFhirVersion(); - ResourceProviderFactory resourceProviders; - Object systemProvider; - if (fhirVersion == FhirVersionEnum.DSTU2) { - resourceProviders = appCtx.getBean("myResourceProvidersDstu2", ResourceProviderFactory.class); - systemProvider = appCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class); - } else if (fhirVersion == FhirVersionEnum.DSTU3) { - resourceProviders = appCtx.getBean("myResourceProvidersDstu3", ResourceProviderFactory.class); - systemProvider = appCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class); - } else if (fhirVersion == FhirVersionEnum.R4) { - resourceProviders = appCtx.getBean("myResourceProvidersR4", ResourceProviderFactory.class); - systemProvider = appCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class); - } else if (fhirVersion == FhirVersionEnum.R5) { - resourceProviders = appCtx.getBean("myResourceProvidersR5", ResourceProviderFactory.class); - systemProvider = appCtx.getBean("mySystemProviderR5", JpaSystemProviderR5.class); - } else { - throw new IllegalStateException(); - } - setFhirContext(appCtx.getBean(FhirContext.class)); + setFhirContext(fhirSystemDao.getContext()); registerProviders(resourceProviders.createProviders()); - registerProvider(systemProvider); + registerProvider(jpaSystemProvider); + FhirVersionEnum fhirVersion = fhirSystemDao.getContext().getVersion().getVersion(); /* * The conformance provider exports the supported resources, search parameters, etc for * this server. The JPA version adds resourceProviders counts to the exported statement, so it @@ -122,34 +125,30 @@ public class BaseJpaRestfulServer extends RestfulServer { * You can also create your own subclass of the conformance provider if you need to * provide further customization of your server's CapabilityStatement */ - DaoConfig daoConfig = appCtx.getBean(DaoConfig.class); - ISearchParamRegistry searchParamRegistry = appCtx.getBean(ISearchParamRegistry.class); + + if (fhirVersion == FhirVersionEnum.DSTU2) { - IFhirSystemDao systemDao = appCtx - .getBean("mySystemDaoDstu2", IFhirSystemDao.class); - JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, + + JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, fhirSystemDao, daoConfig); confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server"); setServerConformanceProvider(confProvider); } else { if (fhirVersion == FhirVersionEnum.DSTU3) { - IFhirSystemDao systemDao = appCtx - .getBean("mySystemDaoDstu3", IFhirSystemDao.class); - JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, + + JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, fhirSystemDao, daoConfig, searchParamRegistry); confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server"); setServerConformanceProvider(confProvider); } else if (fhirVersion == FhirVersionEnum.R4) { - IFhirSystemDao systemDao = appCtx - .getBean("mySystemDaoR4", IFhirSystemDao.class); - JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, + + JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, fhirSystemDao, daoConfig, searchParamRegistry); confProvider.setImplementationDescription("HAPI FHIR R4 Server"); setServerConformanceProvider(confProvider); } else if (fhirVersion == FhirVersionEnum.R5) { - IFhirSystemDao systemDao = appCtx - .getBean("mySystemDaoR5", IFhirSystemDao.class); - JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao, + + JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, fhirSystemDao, daoConfig, searchParamRegistry); confProvider.setImplementationDescription("HAPI FHIR R5 Server"); setServerConformanceProvider(confProvider); @@ -185,6 +184,7 @@ public class BaseJpaRestfulServer extends RestfulServer { * a performance hit when performing searches that return lots of results, * but makes the server much more scalable. */ + setPagingProvider(appCtx.getBean(DatabaseBackedPagingProvider.class)); /* @@ -349,4 +349,16 @@ public class BaseJpaRestfulServer extends RestfulServer { } } + protected T getBeanWithoutProxy(Object bean) { + + if (AopUtils.isAopProxy(bean) && bean instanceof Advised) { + try { + return (T) ((Advised) bean).getTargetSource().getTarget(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return (T)bean; + } + } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java index 4768e17..d81361b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -31,18 +31,10 @@ public class FhirServerConfigCommon { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class); - private Boolean enableIndexMissingFields = HapiProperties.getEnableIndexMissingFields(); - private Boolean autoCreatePlaceholderReferenceTargets = HapiProperties.getAutoCreatePlaceholderReferenceTargets(); - private Boolean enforceReferentialIntegrityOnWrite = HapiProperties.getEnforceReferentialIntegrityOnWrite(); - private Boolean enforceReferentialIntegrityOnDelete = HapiProperties.getEnforceReferentialIntegrityOnDelete(); - private Boolean allowContainsSearches = HapiProperties.getAllowContainsSearches(); - private Boolean allowMultipleDelete = HapiProperties.getAllowMultipleDelete(); - private Boolean allowExternalReferences = HapiProperties.getAllowExternalReferences(); - private Boolean expungeEnabled = HapiProperties.getExpungeEnabled(); - private Boolean allowPlaceholderReferences = HapiProperties.getAllowPlaceholderReferences(); + private Boolean subscriptionRestHookEnabled = HapiProperties.getSubscriptionRestHookEnabled(); private Boolean subscriptionEmailEnabled = HapiProperties.getSubscriptionEmailEnabled(); - private Boolean allowOverrideDefaultSearchParams = HapiProperties.getAllowOverrideDefaultSearchParams(); + private String emailFrom = HapiProperties.getEmailFrom(); private Boolean emailEnabled = HapiProperties.getEmailEnabled(); private String emailHost = HapiProperties.getEmailHost(); @@ -118,26 +110,26 @@ public class FhirServerConfigCommon { retVal.setExpireSearchResultsAfterMillis(retainCachedSearchesMinutes * 60 * 1000); // Subscriptions are enabled by channel type - if (HapiProperties.getSubscriptionRestHookEnabled()) { + if (appProperties.getSubscription().getResthook_enabled()) { ourLog.info("Enabling REST-hook subscriptions"); retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK); } - if (HapiProperties.getSubscriptionEmailEnabled()) { + if (appProperties.getSubscription().getEmail_enabled()) { ourLog.info("Enabling email subscriptions"); retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL); } - if (HapiProperties.getSubscriptionWebsocketEnabled()) { + if (appProperties.getSubscription().getWebsocket_enabled()) { ourLog.info("Enabling websocket subscriptions"); retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET); } - retVal.setFilterParameterEnabled(HapiProperties.getFilterSearchEnabled()); + retVal.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); return retVal; } @Bean - public PartitionSettings partitionSettings() { + public PartitionSettings partitionSettings(AppProperties appProperties) { PartitionSettings retVal = new PartitionSettings(); // Partitioning diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java index 587f313..68190ec 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -17,7 +17,6 @@ import javax.sql.DataSource; @Configuration @Profile("r4") -@ConditionalOnClass(DataSource.class) public class FhirServerConfigR4 extends BaseJavaConfigR4 { @Autowired diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java index dbcca69..45a7808 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java @@ -33,18 +33,22 @@ public class FhirTesterConfig { * deploying your server to a place with a fully qualified domain name, * you might want to use that instead of using the variable. */ - @Bean - public TesterConfig testerConfig(AppProperties appProperties) { - TesterConfig retVal = new TesterConfig(); - retVal - .addServer() - .withId(appProperties.getTester().getId()) - .withFhirVersion(appProperties.getFhir_version()) - .withBaseUrl(appProperties.getTester().getAddress()) - .withName(appProperties.getTester().getName()); - retVal.setRefuseToFetchThirdPartyUrls(appProperties.getTester().getRefuse_to_fetch_third_party_urls()); - return retVal; - } + @Bean + public TesterConfig testerConfig(AppProperties appProperties) { + TesterConfig retVal = new TesterConfig(); + appProperties.getTester().stream().forEach(t -> { + retVal + .addServer() + .withId(t.getId()) + .withFhirVersion(t.getFhir_version()) + .withBaseUrl(t.getServer_address()) + .withName(t.getName()); + retVal.setRefuseToFetchThirdPartyUrls( + t.getRefuse_to_fetch_third_party_urls()); + + }); + return retVal; + } } //@formatter:on diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 4c0c72c..13ec39d 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -2,9 +2,12 @@ spring: datasource: url: 'jdbc:h2:file:./target/database/h2dflkjglkj' username: sa - password: + password: null driverClassName: org.h2.Driver max-active: 15 + profiles: + ### This is the FHIR version. Choose between, dstu2, dstu3, r4 or r5 + active: r4 hapi: fhir: allow_cascading_deletes: true @@ -21,8 +24,7 @@ hapi: enforce_referential_integrity_on_write: false etag_support_enabled: true expunge_enabled: true - fhir_version: DSTU3 - daoconfig_client_id_strategy: + daoconfig_client_id_strategy: null fhirpath_interceptor_enabled: false filter_search_enabled: true graphql_enabled: true @@ -40,16 +42,28 @@ hapi: retain_cached_searches_mins: 60 reuse_cached_search_results_millis: 60000 tester: - id: home - name: Local Tester - server_address: 'http://localhost:8080/fhir' - refuse_to_fetch_third_party_urls: false + - + id: home + name: Local Tester + server_address: 'http://localhost:8080/fhir' + refuse_to_fetch_third_party_urls: false + fhir_version: R4 + - + id: global + name: Global Tester + server_address: "http://hapi.fhir.org/baseR4" + refuse_to_fetch_third_party_urls: false + fhir_version: R4 validation: requests_enabled: true responses_enabled: true - binary_storage_enabled: true bulk_export_enabled: true + partitioning_multitenancy_enabled: + subscription: + email_enabled: false + resthook_enabled: false + websocket_enabled: false elasticsearch: debug: pretty_print_json_log: false @@ -59,4 +73,4 @@ elasticsearch: required_index_status: YELLOW rest_url: 'http://localhost:9200' schema_management_strategy: CREATE - username: SomeUsername \ No newline at end of file + username: SomeUsername