From 395a87ee84ba22e541b60aafd1496f2a96796274 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Fri, 27 Aug 2021 13:34:47 -0400 Subject: [PATCH 001/192] Bump dep version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 80dc78f3e30..79d8fe73d74 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0 + 5.6.0-PRE2-SNAPSHOT hapi-fhir-jpaserver-starter From 5038b5bd2c746a2d9c3407ade42a968cd191c743 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Fri, 27 Aug 2021 13:50:42 -0400 Subject: [PATCH 002/192] Remove javamail and replace with simple-java-mail --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 79d8fe73d74..bee8ba77b6a 100644 --- a/pom.xml +++ b/pom.xml @@ -67,12 +67,12 @@ - com.sun.mail - javax.mail + org.simplejavamail + simple-java-mail - javax.activation - activation + jakarta.annotation + jakarta.annotation-api From 6e876c15029334c615514721a0968fbad198cc1b Mon Sep 17 00:00:00 2001 From: Tadgh Date: Fri, 27 Aug 2021 16:29:06 -0400 Subject: [PATCH 003/192] WIP --- pom.xml | 6 +++ .../uhn/fhir/jpa/starter/AppProperties.java | 19 +++++++++ .../jpa/starter/BaseJpaRestfulServer.java | 5 +++ .../jpa/starter/FhirServerConfigCommon.java | 39 ++++++++++--------- src/main/resources/application.yaml | 4 ++ 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index bee8ba77b6a..1e434d68d39 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,12 @@ hapi-fhir-base ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-jpaserver-subscription + ${project.version} + 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 4c69373a25f..98113b2a425 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -74,6 +74,9 @@ public class AppProperties { private Boolean use_apache_address_strategy = false; private Boolean use_apache_address_strategy_https = false; + private Integer bundle_batch_pool_size = 20; + private Integer bundle_batch_pool_max_size = 100; + public Boolean getUse_apache_address_strategy() { return use_apache_address_strategy; } @@ -471,6 +474,22 @@ public void setInstall_transitive_ig_dependencies(boolean install_transitive_ig_ this.install_transitive_ig_dependencies = install_transitive_ig_dependencies; } + public Integer getBundle_batch_pool_size() { + return this.bundle_batch_pool_size; + } + + public void setBundle_batch_pool_size(Integer bundle_batch_pool_size) { + this.bundle_batch_pool_size = bundle_batch_pool_size; + } + + public Integer getBundle_batch_pool_max_size() { + return bundle_batch_pool_max_size; + } + + public void setBundle_batch_pool_max_size(Integer bundle_batch_pool_max_size) { + this.bundle_batch_pool_max_size = bundle_batch_pool_max_size; + } + public static class Cors { private Boolean allow_Credentials = true; private List allowed_origin = ImmutableList.of("*"); 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 dc16873fff1..2ff07f16787 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -373,6 +373,11 @@ protected void initialize() throws ServletException { daoConfig.setResourceServerIdStrategy(DaoConfig.IdStrategyEnum.UUID); daoConfig.setResourceClientIdStrategy(appProperties.getClient_id_strategy()); } + //Parallel Batch GET execution settings + daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_size()); + daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_max_size()); + System.out.println("BATCH SIZE IS " + appProperties.getBundle_batch_pool_size()); + System.out.println("BATCH MAX SIZE IS " + appProperties.getBundle_batch_pool_max_size()); if (appProperties.getImplementationGuides() != null) { Map guides = appProperties.getImplementationGuides(); 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 8777e0ab1f7..74d46bc8709 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -8,10 +8,16 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings.CrossPartitionReferenceMode; import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory; +import ca.uhn.fhir.jpa.subscription.match.deliver.email.EmailSenderImpl; import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender; -import ca.uhn.fhir.jpa.subscription.match.deliver.email.JavaMailEmailSender; +import ca.uhn.fhir.rest.server.mail.MailConfig; import com.google.common.base.Strings; +import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.dstu2.model.Subscription; +import org.simplejavamail.api.email.Email; +import org.simplejavamail.api.mailer.Mailer; +import org.simplejavamail.api.mailer.config.TransportStrategy; +import org.simplejavamail.mailer.MailerBuilder; import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -205,23 +211,20 @@ public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) { @Bean() public IEmailSender emailSender(AppProperties appProperties, Optional subscriptionDeliveryHandlerFactory) { if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) { - JavaMailEmailSender retVal = new JavaMailEmailSender(); - - AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail(); - retVal.setSmtpServerHostname(email.getHost()); - retVal.setSmtpServerPort(email.getPort()); - retVal.setSmtpServerUsername(email.getUsername()); - retVal.setSmtpServerPassword(email.getPassword()); - retVal.setAuth(email.getAuth()); - retVal.setStartTlsEnable(email.getStartTlsEnable()); - retVal.setStartTlsRequired(email.getStartTlsRequired()); - retVal.setQuitWait(email.getQuitWait()); - - if(subscriptionDeliveryHandlerFactory.isPresent()) - subscriptionDeliveryHandlerFactory.get().setEmailSender(retVal); - - return retVal; - } + AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail(); + MailConfig mailConfig = new MailConfig(); + mailConfig.setSmtpHostname(email.getHost()); + mailConfig.setSmtpUseStartTLS(email.getStartTlsRequired()); + mailConfig.setSmtpPort(email.getPort()); + mailConfig.setSmtpUsername(email.getUsername()); + mailConfig.setSmtpPassword(email.getPassword()); + EmailSenderImpl emailSender = new EmailSenderImpl(mailConfig); + + if(subscriptionDeliveryHandlerFactory.isPresent()) { + subscriptionDeliveryHandlerFactory.get().setEmailSender(emailSender); + } + + } return null; } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7be442375ad..02cbd8027af 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -99,6 +99,10 @@ hapi: search-coord-max-pool-size: 100 search-coord-queue-capacity: 200 + # Threadpool size for BATCH'ed GETs in a bundle. +# bundle_batch_pool_size: 10 +# bundle_batch_pool_max_size: 50 + # logger: # error_format: 'ERROR - ${requestVerb} ${requestUrl}' # format: >- From a8a98c311cadb9793c0ec423ccf7b6b2aafeae4e Mon Sep 17 00:00:00 2001 From: Tadgh Date: Sat, 28 Aug 2021 12:52:56 -0400 Subject: [PATCH 004/192] Remove print --- src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 2 -- 1 file changed, 2 deletions(-) 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 2ff07f16787..3d287c09ff5 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -376,8 +376,6 @@ protected void initialize() throws ServletException { //Parallel Batch GET execution settings daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_size()); daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_max_size()); - System.out.println("BATCH SIZE IS " + appProperties.getBundle_batch_pool_size()); - System.out.println("BATCH MAX SIZE IS " + appProperties.getBundle_batch_pool_max_size()); if (appProperties.getImplementationGuides() != null) { Map guides = appProperties.getImplementationGuides(); From e26364670d4d497e93a0baff74824710508d3841 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Sat, 28 Aug 2021 18:52:41 -0400 Subject: [PATCH 005/192] Remove bean override --- src/main/java/ca/uhn/fhir/jpa/starter/Application.java | 8 -------- src/main/resources/application.yaml | 3 --- .../ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java | 1 - .../ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java | 1 - .../java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java | 1 - .../ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java | 1 - 6 files changed, 15 deletions(-) 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 e823d5f3ddb..383d03a9aa0 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -29,14 +29,6 @@ public class Application extends SpringBootServletInitializer { public static void main(String[] args) { - /* - * https://github.com/hapifhir/hapi-fhir-jpaserver-starter/issues/246 - * This will be allowed for a short period until we know how MDM should be configured - * or don't have multiple equal bean instantiations. - * - * This will require changes in the main project as stated in the Github comment - * */ - System.setProperty("spring.main.allow-bean-definition-overriding","true"); System.setProperty("spring.batch.job.enabled", "false"); SpringApplication.run(Application.class, args); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 02cbd8027af..8861c3e7301 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -31,9 +31,6 @@ spring: batch: job: enabled: false - main: -# TODO 5.6.0 -> Prevent duplicate bean definitions in the Spring batch config in HAPI: see: - allow-bean-definition-overriding: true hapi: fhir: ### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5 diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java index 0b408deb2c7..964fae24a6f 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -21,7 +21,6 @@ "spring.batch.job.enabled=false", "hapi.fhir.fhir_version=dstu2", "spring.datasource.url=jdbc:h2:mem:dbr2", - "spring.main.allow-bean-definition-overriding=true" }) public class ExampleServerDstu2IT { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index 91cb4baeb30..b4ca6c3cec3 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -46,7 +46,6 @@ "hapi.fhir.subscription.websocket_enabled=true", "hapi.fhir.allow_external_references=true", "hapi.fhir.allow_placeholder_references=true", - "spring.main.allow-bean-definition-overriding=true" }) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index 6a7fc52df23..055d1ab25d7 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -39,7 +39,6 @@ "hapi.fhir.fhir_version=r5", "hapi.fhir.subscription.websocket_enabled=true", "hapi.fhir.subscription.websocket_enabled=true", - "spring.main.allow-bean-definition-overriding=true" }) public class ExampleServerR5IT { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java index d8ae7cfa1a1..29af5e7482a 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -25,7 +25,6 @@ "hapi.fhir.fhir_version=r4", "hapi.fhir.subscription.websocket_enabled=true", "hapi.fhir.partitioning.partitioning_include_in_search_hashes=false", - "spring.main.allow-bean-definition-overriding=true" }) public class MultitenantServerR4IT { From 6e2836b91dafb1230269ddb837af1150d1739e8d Mon Sep 17 00:00:00 2001 From: Tadgh Date: Tue, 7 Sep 2021 18:36:58 -0400 Subject: [PATCH 006/192] Bump version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1e434d68d39..20f740eb260 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.6.0-PRE2-SNAPSHOT + 5.6.0-PRE1_NIH-SNAPSHOT hapi-fhir-jpaserver-starter From f3ea6803da25d610847cf04a051854cda48a8357 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 9 Sep 2021 14:41:38 -0400 Subject: [PATCH 007/192] Add broken test --- .../fhir/jpa/starter/ExampleServerR4IT.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 6d995238411..7b0548747a7 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -1,9 +1,12 @@ package ca.uhn.fhir.jpa.starter; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.partition.SystemRequestDetails; +import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; @@ -86,6 +89,57 @@ private Patient getGoldenResourcePatient() { } } + @Test + public void testBatchPutWithIdenticalTags() { + String batchPuts = "{\n" + + "\t\"resourceType\": \"Bundle\",\n" + + "\t\"id\": \"patients\",\n" + + "\t\"type\": \"batch\",\n" + + "\t\"entry\": [\n" + + "\t\t{\n" + + "\t\t\t\"request\": {\n" + + "\t\t\t\t\"method\": \"PUT\",\n" + + "\t\t\t\t\"url\": \"Patient/pat-1\"\n" + + "\t\t\t},\n" + + "\t\t\t\"resource\": {\n" + + "\t\t\t\t\"resourceType\": \"Patient\",\n" + + "\t\t\t\t\"id\": \"pat-1\",\n" + + "\t\t\t\t\"meta\": {\n" + + "\t\t\t\t\t\"tag\": [\n" + + "\t\t\t\t\t\t{\n" + + "\t\t\t\t\t\t\t\"system\": \"http://mysystem.org\",\n" + + "\t\t\t\t\t\t\t\"code\": \"value2\"\n" + + "\t\t\t\t\t\t}\n" + + "\t\t\t\t\t]\n" + + "\t\t\t\t}\n" + + "\t\t\t},\n" + + "\t\t\t\"fullUrl\": \"/Patient/pat-1\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"request\": {\n" + + "\t\t\t\t\"method\": \"PUT\",\n" + + "\t\t\t\t\"url\": \"Patient/pat-2\"\n" + + "\t\t\t},\n" + + "\t\t\t\"resource\": {\n" + + "\t\t\t\t\"resourceType\": \"Patient\",\n" + + "\t\t\t\t\"id\": \"pat-2\",\n" + + "\t\t\t\t\"meta\": {\n" + + "\t\t\t\t\t\"tag\": [\n" + + "\t\t\t\t\t\t{\n" + + "\t\t\t\t\t\t\t\"system\": \"http://mysystem.org\",\n" + + "\t\t\t\t\t\t\t\"code\": \"value2\"\n" + + "\t\t\t\t\t\t}\n" + + "\t\t\t\t\t]\n" + + "\t\t\t\t}\n" + + "\t\t\t},\n" + + "\t\t\t\"fullUrl\": \"/Patient/pat-2\"\n" + + "\t\t}\n" + + "\t]\n" + + "}"; + Bundle bundle = FhirContext.forR4().newJsonParser().parseResource(Bundle.class, batchPuts); + ourClient.transaction().withBundle(bundle).execute(); + } + @Test @Order(1) void testWebsocketSubscription() throws Exception { From e41c186bddfe67411423b5dcd76280ea761cece3 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 9 Sep 2021 14:53:54 -0400 Subject: [PATCH 008/192] Update for new style of container bean --- .../java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java | 5 +++-- .../ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java | 7 ++++--- .../ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java | 7 ++++--- .../java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java | 7 ++++--- .../java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java | 7 ++++--- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java index 75db0f8c957..cc6aaba7581 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java @@ -14,6 +14,7 @@ import org.hibernate.search.mapper.orm.automaticindexing.session.AutomaticIndexingSynchronizationStrategyNames; import org.hibernate.search.mapper.orm.cfg.HibernateOrmMapperSettings; import org.hibernate.search.mapper.orm.schema.management.SchemaManagementStrategyName; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy; import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; import org.springframework.core.env.CompositePropertySource; @@ -25,7 +26,7 @@ public class EnvironmentHelper { - public static Properties getHibernateProperties(ConfigurableEnvironment environment) { + public static Properties getHibernateProperties(ConfigurableEnvironment environment, ConfigurableListableBeanFactory theBeanFactory) { Properties properties = new Properties(); Map jpaProps = getPropertiesStartingWith(environment, "spring.jpa.properties"); for (Map.Entry entry : jpaProps.entrySet()) { @@ -41,7 +42,7 @@ public static Properties getHibernateProperties(ConfigurableEnvironment environm //properties.putIfAbsent(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory)); //hapi-fhir-jpaserver-base "sensible defaults" - Map hapiJpaPropertyMap = new HapiFhirLocalContainerEntityManagerFactoryBean().getJpaPropertyMap(); + Map hapiJpaPropertyMap = new HapiFhirLocalContainerEntityManagerFactoryBean(theBeanFactory).getJpaPropertyMap(); hapiJpaPropertyMap.forEach(properties::putIfAbsent); //hapi-fhir-jpaserver-starter defaults diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java index 6e26d41fafe..67bcd40b782 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java @@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU2Condition; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -58,8 +59,8 @@ public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @Override @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(theBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -67,7 +68,7 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { } catch (Exception e) { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, theBeanFactory)); return retVal; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index 367c0ec6809..4fbde9c5317 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -10,6 +10,7 @@ import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -62,8 +63,8 @@ public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @Override @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(theBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -72,7 +73,7 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, theBeanFactory)); return retVal; } 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 a53b0578711..c2f228788b4 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; import ca.uhn.fhir.jpa.starter.cql.StarterCqlR4Config; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.*; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.orm.jpa.JpaTransactionManager; @@ -58,8 +59,8 @@ public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @Override @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(theBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -68,7 +69,7 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, theBeanFactory)); return retVal; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index 2c6d72eaa46..0a9bd72d4dd 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -6,6 +6,7 @@ import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -59,8 +60,8 @@ public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @Override @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(theBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -69,7 +70,7 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, theBeanFactory)); return retVal; } From 370d68a55cf366c53e40934d28fed689925f4567 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 16 Sep 2021 01:00:35 -0400 Subject: [PATCH 009/192] Bump for new version --- pom.xml | 2 +- .../ca/uhn/fhir/jpa/starter/EnvironmentHelper.java | 2 +- .../uhn/fhir/jpa/starter/FhirServerConfigDstu3.java | 12 ++++-------- .../ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java | 8 ++------ .../ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java | 12 ++++-------- 5 files changed, 12 insertions(+), 24 deletions(-) diff --git a/pom.xml b/pom.xml index 20f740eb260..bc2f2a2bf0b 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.6.0-PRE1_NIH-SNAPSHOT + 5.6.0-PRE5_NIH hapi-fhir-jpaserver-starter diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java index cc6aaba7581..88e372ca83d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java @@ -74,7 +74,7 @@ public static Properties getHibernateProperties(ConfigurableEnvironment environm ElasticsearchHibernatePropertiesBuilder builder = new ElasticsearchHibernatePropertiesBuilder(); IndexStatus requiredIndexStatus = environment.getProperty("elasticsearch.required_index_status", IndexStatus.class); builder.setRequiredIndexStatus(requireNonNullElse(requiredIndexStatus, IndexStatus.YELLOW)); - builder.setRestUrl(getElasticsearchServerUrl(environment)); + builder.setHosts(getElasticsearchServerUrl(environment)); builder.setUsername(getElasticsearchServerUsername(environment)); builder.setPassword(getElasticsearchServerPassword(environment)); builder.setProtocol(getElasticsearchServerProtocol(environment)); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index 4fbde9c5317..3c7029362f2 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -89,16 +89,12 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM public ElasticsearchSvcImpl elasticsearchSvc() { if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); - String elasticsearchHost; - if (elasticsearchUrl.startsWith("http")) { - elasticsearchHost = elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3, elasticsearchUrl.lastIndexOf(":")); - } else { - elasticsearchHost = elasticsearchUrl.substring(0, elasticsearchUrl.indexOf(":")); - } + if (elasticsearchUrl.startsWith("http")) { + elasticsearchUrl =elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3); + } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - int elasticsearchPort = Integer.parseInt(elasticsearchUrl.substring(elasticsearchUrl.lastIndexOf(":")+1)); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(elasticsearchUrl, elasticsearchUsername, elasticsearchPassword); } else { return null; } 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 c2f228788b4..8e4892aba77 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -85,17 +85,13 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM public ElasticsearchSvcImpl elasticsearchSvc() { if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); - String elasticsearchHost; if (elasticsearchUrl.startsWith("http")) { - elasticsearchHost = elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3, elasticsearchUrl.lastIndexOf(":")); - } else { - elasticsearchHost = elasticsearchUrl.substring(0, elasticsearchUrl.indexOf(":")); + elasticsearchUrl =elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3); } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - int elasticsearchPort = Integer.parseInt(elasticsearchUrl.substring(elasticsearchUrl.lastIndexOf(":")+1)); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(elasticsearchUrl, elasticsearchUsername, elasticsearchPassword); } else { return null; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index 0a9bd72d4dd..9ad27d63baf 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -86,16 +86,12 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM public ElasticsearchSvcImpl elasticsearchSvc() { if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); - String elasticsearchHost; - if (elasticsearchUrl.startsWith("http")) { - elasticsearchHost = elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3, elasticsearchUrl.lastIndexOf(":")); - } else { - elasticsearchHost = elasticsearchUrl.substring(0, elasticsearchUrl.indexOf(":")); - } + if (elasticsearchUrl.startsWith("http")) { + elasticsearchUrl =elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3); + } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - int elasticsearchPort = Integer.parseInt(elasticsearchUrl.substring(elasticsearchUrl.lastIndexOf(":")+1)); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(elasticsearchUrl, elasticsearchUsername, elasticsearchPassword); } else { return null; } From ac75421a7b869ce7b16fe5cb89882eacc539a374 Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Tue, 5 Oct 2021 15:07:08 -0400 Subject: [PATCH 010/192] Update to 5.6.0-PRE7_NIH-SNAPSHOT and activate advanced index --- pom.xml | 2 +- .../java/ca/uhn/fhir/jpa/starter/AppProperties.java | 11 ++++++++++- .../uhn/fhir/jpa/starter/FhirServerConfigCommon.java | 1 + src/main/resources/application.yaml | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index bc2f2a2bf0b..73a4ce00d00 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.6.0-PRE5_NIH + 5.6.0-PRE7_NIH-SNAPSHOT hapi-fhir-jpaserver-starter 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 98113b2a425..aa140154d7d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -23,6 +23,7 @@ public class AppProperties { private Boolean cql_enabled = false; private Boolean mdm_enabled = false; + private boolean advanced_lucene_indexing = false; private Boolean allow_cascading_deletes = false; private Boolean allow_contains_searches = true; private Boolean allow_external_references = false; @@ -206,7 +207,15 @@ public void setClient_id_strategy( this.client_id_strategy = client_id_strategy; } - public Boolean getAllow_cascading_deletes() { + public boolean getAdvanced_lucene_indexing() { + return this.advanced_lucene_indexing; + } + + public void setAdvanced_lucene_indexing(boolean theAdvanced_lucene_indexing) { + advanced_lucene_indexing = theAdvanced_lucene_indexing; + } + + public Boolean getAllow_cascading_deletes() { return allow_cascading_deletes; } 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 74d46bc8709..63f675ff6d8 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -120,6 +120,7 @@ public DaoConfig daoConfig(AppProperties appProperties) { } retVal.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); + retVal.setAdvancedLuceneIndexing(appProperties.getAdvanced_lucene_indexing()); return retVal; } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 8861c3e7301..e775be29d71 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -71,6 +71,8 @@ hapi: # enable_repository_validating_interceptor: false # enable_index_missing_fields: false # enable_index_contained_resource: false +# advanced_lucene_indexing: false + advanced_lucene_indexing: true # enforce_referential_integrity_on_delete: false # enforce_referential_integrity_on_write: false # etag_support_enabled: true From 3272b8c0d22bc532dbe276afecb2e72a2b563431 Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Tue, 5 Oct 2021 16:06:19 -0400 Subject: [PATCH 011/192] Disable default flyway processing --- src/main/resources/application.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index e775be29d71..4f509d6a417 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,4 +1,6 @@ spring: + flyway: + enabled: false datasource: url: 'jdbc:h2:file:./target/database/h2' #url: jdbc:h2:mem:test_mem From 097db1642f14baa4817b82bdde529885bb35dfee Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Thu, 7 Oct 2021 15:14:06 -0400 Subject: [PATCH 012/192] Add local_base_urls configuration to feed DaoConfig.setTreatBaseUrlsAsLocal() --- .../ca/uhn/fhir/jpa/starter/AppProperties.java | 16 +++++++++++----- .../fhir/jpa/starter/FhirServerConfigCommon.java | 2 ++ .../resources/application-integrationtest.yaml | 2 ++ 3 files changed, 15 insertions(+), 5 deletions(-) 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 aa140154d7d..78d666060cb 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -11,10 +11,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; @ConfigurationProperties(prefix = "hapi.fhir") @Configuration @@ -77,6 +74,7 @@ public class AppProperties { private Integer bundle_batch_pool_size = 20; private Integer bundle_batch_pool_max_size = 100; + private List local_base_urls = new ArrayList<>(); public Boolean getUse_apache_address_strategy() { return use_apache_address_strategy; @@ -190,7 +188,11 @@ public void setSupported_resource_types(List supported_resource_types) { this.supported_resource_types = supported_resource_types; } - public Logger getLogger() { + public List getSupported_resource_types(List supported_resource_types) { + return this.supported_resource_types; + } + + public Logger getLogger() { return logger; } @@ -499,6 +501,10 @@ public void setBundle_batch_pool_max_size(Integer bundle_batch_pool_max_size) { this.bundle_batch_pool_max_size = bundle_batch_pool_max_size; } + public List getLocal_base_urls() { + return local_base_urls; + } + public static class Cors { private Boolean allow_Credentials = true; private List allowed_origin = ImmutableList.of("*"); 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 63f675ff6d8..7310fe09208 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -26,6 +26,7 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; +import java.util.HashSet; import java.util.Optional; /** @@ -121,6 +122,7 @@ public DaoConfig daoConfig(AppProperties appProperties) { retVal.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); retVal.setAdvancedLuceneIndexing(appProperties.getAdvanced_lucene_indexing()); + retVal.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls())); return retVal; } diff --git a/src/test/resources/application-integrationtest.yaml b/src/test/resources/application-integrationtest.yaml index b19a14bbb50..6afbcbf1c66 100644 --- a/src/test/resources/application-integrationtest.yaml +++ b/src/test/resources/application-integrationtest.yaml @@ -34,6 +34,8 @@ hapi: # fhirpath_interceptor_enabled: false # filter_search_enabled: true # graphql_enabled: true +# local_base_urls: +# - http://hapi.fhir.org/baseR4 #partitioning: # cross_partition_reference_mode: true # multitenancy_enabled: true From ea3f10ec86774abfaedf220f46a7b515f9751d26 Mon Sep 17 00:00:00 2001 From: jkv Date: Wed, 10 Nov 2021 20:57:31 +0100 Subject: [PATCH 013/192] Added OpenAPI / Swagger option --- pom.xml | 6 ++++++ src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java | 9 +++++++++ .../ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 5 +++++ src/main/resources/application.yaml | 2 ++ 4 files changed, 22 insertions(+) diff --git a/pom.xml b/pom.xml index 94f096c6af1..a7d67e56f53 100644 --- a/pom.xml +++ b/pom.xml @@ -112,6 +112,12 @@ hapi-fhir-jpaserver-mdm ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-server-openapi + ${project.version} + ca.uhn.hapi.fhir 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 fd92001cca2..87b4181af6f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -22,6 +22,7 @@ public class AppProperties { private Boolean cql_enabled = false; + private Boolean openapi_enabled = false; private Boolean mdm_enabled = false; private Boolean allow_cascading_deletes = false; private Boolean allow_contains_searches = true; @@ -75,6 +76,14 @@ public class AppProperties { private Boolean use_apache_address_strategy = false; private Boolean use_apache_address_strategy_https = false; + public Boolean getOpenapi_enabled() { + return openapi_enabled; + } + + public void setOpenapi_enabled(Boolean openapi_enabled) { + this.openapi_enabled = openapi_enabled; + } + public Boolean getUse_apache_address_strategy() { return use_apache_address_strategy; } 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 dc16873fff1..b58c41cb20d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -28,6 +28,7 @@ import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.narrative.INarrativeGenerator; import ca.uhn.fhir.narrative2.NullNarrativeGenerator; +import ca.uhn.fhir.rest.openapi.OpenApiInterceptor; import ca.uhn.fhir.rest.server.ApacheProxyAddressStrategy; import ca.uhn.fhir.rest.server.ETagSupportEnum; import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy; @@ -357,6 +358,10 @@ protected void initialize() throws ServletException { daoConfig.setDeferIndexingForCodesystemsOfSize(appProperties.getDefer_indexing_for_codesystems_of_size()); + if (appProperties.getOpenapi_enabled()) { + registerInterceptor(new OpenApiInterceptor()); + } + // Bulk Export if (appProperties.getBulk_export_enabled()) { registerProvider(bulkDataExportProvider); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index c4c393d6dfe..1c51699f1e8 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -36,6 +36,8 @@ spring: allow-bean-definition-overriding: true hapi: fhir: + ### This enables the swagger-ui at /fhir/swagger-ui/index.html as well as the /fhir/api-docs (see https://hapifhir.io/hapi-fhir/docs/server_plain/openapi.html) + openapi_enabled: true ### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5 fhir_version: R4 ### enable to use the ApacheProxyAddressStrategy which uses X-Forwarded-* headers From 16559ea17cf679812fabe8e2b2c2a05dc757e751 Mon Sep 17 00:00:00 2001 From: jkv Date: Thu, 18 Nov 2021 19:48:40 +0100 Subject: [PATCH 014/192] Upgraded to 5.6.0 Subscription tests fail ... --- pom.xml | 2 +- .../ca/uhn/fhir/jpa/starter/Application.java | 10 -------- .../fhir/jpa/starter/EnvironmentHelper.java | 8 ++++--- .../jpa/starter/FhirServerConfigCommon.java | 24 +++++++++---------- .../jpa/starter/FhirServerConfigDstu2.java | 8 ++++--- .../jpa/starter/FhirServerConfigDstu3.java | 12 ++++++---- .../fhir/jpa/starter/FhirServerConfigR4.java | 12 ++++++---- .../fhir/jpa/starter/FhirServerConfigR5.java | 12 ++++++---- src/main/resources/application.yaml | 5 ++-- 9 files changed, 46 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index a7d67e56f53..6b677e8ce46 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.1 + 5.6.0 hapi-fhir-jpaserver-starter 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 e823d5f3ddb..2cf60f56344 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -29,16 +29,6 @@ public class Application extends SpringBootServletInitializer { public static void main(String[] args) { - /* - * https://github.com/hapifhir/hapi-fhir-jpaserver-starter/issues/246 - * This will be allowed for a short period until we know how MDM should be configured - * or don't have multiple equal bean instantiations. - * - * This will require changes in the main project as stated in the Github comment - * */ - System.setProperty("spring.main.allow-bean-definition-overriding","true"); - - System.setProperty("spring.batch.job.enabled", "false"); SpringApplication.run(Application.class, args); //Server is now accessible at eg. http://localhost:8080/fhir/metadata diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java index 75db0f8c957..96a958f187f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java @@ -14,6 +14,7 @@ import org.hibernate.search.mapper.orm.automaticindexing.session.AutomaticIndexingSynchronizationStrategyNames; import org.hibernate.search.mapper.orm.cfg.HibernateOrmMapperSettings; import org.hibernate.search.mapper.orm.schema.management.SchemaManagementStrategyName; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy; import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; import org.springframework.core.env.CompositePropertySource; @@ -25,7 +26,8 @@ public class EnvironmentHelper { - public static Properties getHibernateProperties(ConfigurableEnvironment environment) { + public static Properties getHibernateProperties(ConfigurableEnvironment environment, + ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { Properties properties = new Properties(); Map jpaProps = getPropertiesStartingWith(environment, "spring.jpa.properties"); for (Map.Entry entry : jpaProps.entrySet()) { @@ -41,7 +43,7 @@ public static Properties getHibernateProperties(ConfigurableEnvironment environm //properties.putIfAbsent(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory)); //hapi-fhir-jpaserver-base "sensible defaults" - Map hapiJpaPropertyMap = new HapiFhirLocalContainerEntityManagerFactoryBean().getJpaPropertyMap(); + Map hapiJpaPropertyMap = new HapiFhirLocalContainerEntityManagerFactoryBean(myConfigurableListableBeanFactory).getJpaPropertyMap(); hapiJpaPropertyMap.forEach(properties::putIfAbsent); //hapi-fhir-jpaserver-starter defaults @@ -73,7 +75,7 @@ public static Properties getHibernateProperties(ConfigurableEnvironment environm ElasticsearchHibernatePropertiesBuilder builder = new ElasticsearchHibernatePropertiesBuilder(); IndexStatus requiredIndexStatus = environment.getProperty("elasticsearch.required_index_status", IndexStatus.class); builder.setRequiredIndexStatus(requireNonNullElse(requiredIndexStatus, IndexStatus.YELLOW)); - builder.setRestUrl(getElasticsearchServerUrl(environment)); + builder.setHosts(getElasticsearchServerUrl(environment)); builder.setUsername(getElasticsearchServerUsername(environment)); builder.setPassword(getElasticsearchServerPassword(environment)); builder.setProtocol(getElasticsearchServerProtocol(environment)); 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 4ec59123ed0..1e296d9bd3b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -8,8 +8,9 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings.CrossPartitionReferenceMode; import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory; +import ca.uhn.fhir.jpa.subscription.match.deliver.email.EmailSenderImpl; import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender; -import ca.uhn.fhir.jpa.subscription.match.deliver.email.JavaMailEmailSender; +import ca.uhn.fhir.rest.server.mail.MailConfig; import com.google.common.base.Strings; import org.hl7.fhir.dstu2.model.Subscription; import org.springframework.boot.env.YamlPropertySourceLoader; @@ -207,22 +208,21 @@ public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) { @Bean() public IEmailSender emailSender(AppProperties appProperties, Optional subscriptionDeliveryHandlerFactory) { if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) { - JavaMailEmailSender retVal = new JavaMailEmailSender(); + MailConfig mailConfig = new MailConfig(); AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail(); - retVal.setSmtpServerHostname(email.getHost()); - retVal.setSmtpServerPort(email.getPort()); - retVal.setSmtpServerUsername(email.getUsername()); - retVal.setSmtpServerPassword(email.getPassword()); - retVal.setAuth(email.getAuth()); - retVal.setStartTlsEnable(email.getStartTlsEnable()); - retVal.setStartTlsRequired(email.getStartTlsRequired()); - retVal.setQuitWait(email.getQuitWait()); + mailConfig.setSmtpHostname(email.getHost()); + mailConfig.setSmtpPort(email.getPort()); + mailConfig.setSmtpUsername(email.getUsername()); + mailConfig.setSmtpPassword(email.getPassword()); + mailConfig.setSmtpUseStartTLS(email.getStartTlsEnable()); + + IEmailSender emailSender = new EmailSenderImpl(mailConfig); if(subscriptionDeliveryHandlerFactory.isPresent()) - subscriptionDeliveryHandlerFactory.get().setEmailSender(retVal); + subscriptionDeliveryHandlerFactory.get().setEmailSender(emailSender); - return retVal; + return emailSender; } return null; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java index 6e26d41fafe..25548bf3f51 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java @@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU2Condition; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -58,8 +59,9 @@ public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @Override @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -67,7 +69,7 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { } catch (Exception e) { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, myConfigurableListableBeanFactory)); return retVal; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index 367c0ec6809..84822ddd3f4 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -10,6 +10,7 @@ import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -62,8 +63,9 @@ public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @Override @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -72,7 +74,8 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, + myConfigurableListableBeanFactory)); return retVal; } @@ -96,8 +99,7 @@ public ElasticsearchSvcImpl elasticsearchSvc() { } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - int elasticsearchPort = Integer.parseInt(elasticsearchUrl.substring(elasticsearchUrl.lastIndexOf(":")+1)); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchUsername, elasticsearchPassword); } else { return null; } 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 a53b0578711..842256a26fa 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; import ca.uhn.fhir.jpa.starter.cql.StarterCqlR4Config; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.*; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.orm.jpa.JpaTransactionManager; @@ -58,8 +59,9 @@ public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @Override @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -68,7 +70,8 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, + myConfigurableListableBeanFactory)); return retVal; } @@ -93,8 +96,7 @@ public ElasticsearchSvcImpl elasticsearchSvc() { String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - int elasticsearchPort = Integer.parseInt(elasticsearchUrl.substring(elasticsearchUrl.lastIndexOf(":")+1)); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchUsername, elasticsearchPassword); } else { return null; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index 2c6d72eaa46..3cb696833d9 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -6,6 +6,7 @@ import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -59,8 +60,9 @@ public DatabaseBackedPagingProvider databaseBackedPagingProvider() { @Override @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { + LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); retVal.setPersistenceUnitName("HAPI_PU"); try { @@ -69,7 +71,8 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() { throw new ConfigurationException("Could not set the data source due to a configuration issue", e); } - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment)); + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, + myConfigurableListableBeanFactory)); return retVal; } @@ -93,8 +96,7 @@ public ElasticsearchSvcImpl elasticsearchSvc() { } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - int elasticsearchPort = Integer.parseInt(elasticsearchUrl.substring(elasticsearchUrl.lastIndexOf(":")+1)); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchUsername, elasticsearchPassword); } else { return null; } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 1c51699f1e8..7dd9ece39b1 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -10,6 +10,8 @@ spring: # database connection pool size hikari: maximum-pool-size: 10 + flyway: + check-location: false jpa: properties: hibernate.format_sql: false @@ -31,9 +33,6 @@ spring: batch: job: enabled: false - main: -# TODO 5.6.0 -> Prevent duplicate bean definitions in the Spring batch config in HAPI: see: - allow-bean-definition-overriding: true hapi: fhir: ### This enables the swagger-ui at /fhir/swagger-ui/index.html as well as the /fhir/api-docs (see https://hapifhir.io/hapi-fhir/docs/server_plain/openapi.html) From 96450874af60f9bbac1b00afb8da6ecb5fc39fdf Mon Sep 17 00:00:00 2001 From: jkv Date: Thu, 18 Nov 2021 20:17:30 +0100 Subject: [PATCH 015/192] Bumped version of Spring Boot in order to fix same issue as https://github.com/Haulmont/jmix-security/issues/90 --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 6b677e8ce46..338e9c9fda2 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ 8 + 2.5.6 @@ -69,6 +70,7 @@ com.sun.mail javax.mail + 1.6.2 javax.activation From 0203a366685f1dea772148b1a8e2b8f9eea1823d Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Sat, 20 Nov 2021 16:07:26 +0100 Subject: [PATCH 016/192] Update application.yaml See https://github.com/hapifhir/hapi-fhir-jpaserver-starter/issues/292 --- src/main/resources/application.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7dd9ece39b1..bca18601146 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -12,6 +12,7 @@ spring: maximum-pool-size: 10 flyway: check-location: false + baselineOnMigrate: true jpa: properties: hibernate.format_sql: false From e39d84ed36439f3361d3601477e28bd6e6d0d504 Mon Sep 17 00:00:00 2001 From: chgl Date: Sat, 20 Nov 2021 13:55:29 +0100 Subject: [PATCH 017/192] documented use of Values.extraEnv --- charts/hapi-fhir-jpaserver/Chart.yaml | 6 ++--- charts/hapi-fhir-jpaserver/README.md | 28 ++++++++++++++++----- charts/hapi-fhir-jpaserver/README.md.gotmpl | 15 +++++++++++ charts/hapi-fhir-jpaserver/values.yaml | 11 ++++++++ 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index 0b839154c3d..b4cb3ac9213 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -18,6 +18,6 @@ annotations: # added, changed, deprecated, removed, fixed, and security. - kind: changed description: | - updated HAPI FHIR starter image to 5.5.1 -appVersion: v5.5.1 -version: 0.6.0 + updated HAPI FHIR starter image to 5.6.0 +appVersion: v5.6.0 +version: 0.7.0 diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index e1e549606a8..efbf65d54be 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -1,6 +1,6 @@ # HAPI FHIR JPA Server Starter Helm Chart -![Version: 0.6.0](https://img.shields.io/badge/Version-0.6.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v5.5.1](https://img.shields.io/badge/AppVersion-v5.5.1-informational?style=flat-square) +![Version: 0.7.0](https://img.shields.io/badge/Version-0.7.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v5.6.0](https://img.shields.io/badge/AppVersion-v5.6.0-informational?style=flat-square) This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment. @@ -11,6 +11,9 @@ helm repo add hapifhir https://hapifhir.github.io/hapi-fhir-jpaserver-starter/ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver ``` +> ⚠ By default, the included [PostgreSQL Helm chart](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrading) +> auto-generates a random password for the database which may cause problems when upgrading the chart (see [here for details](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrading)). + ## Values | Key | Type | Default | Description | @@ -24,11 +27,12 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | externalDatabase.password | string | `""` | database password | | externalDatabase.port | int | `5432` | database port number | | externalDatabase.user | string | `"fhir"` | username for the external database | +| extraEnv | list | `[]` | extra environment variables to set on the server container | | fullnameOverride | string | `""` | override the chart fullname | | image.flavor | string | `"distroless"` | the flavor or variant of the image to use. appended to the image tag by `-`. | -| image.pullPolicy | string | `"IfNotPresent"` | | -| image.registry | string | `"docker.io"` | | -| image.repository | string | `"hapiproject/hapi"` | | +| image.pullPolicy | string | `"IfNotPresent"` | image pullPolicy to use | +| image.registry | string | `"docker.io"` | registry where the HAPI FHIR server image is hosted | +| image.repository | string | `"hapiproject/hapi"` | the path inside the repository | | image.tag | string | `""` | defaults to `Chart.appVersion` | | imagePullSecrets | list | `[]` | image pull secrets to use when pulling the image | | ingress.annotations | object | `{}` | provide any additional annotations which may be required. Evaluated as a template. | @@ -61,8 +65,8 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | securityContext.readOnlyRootFilesystem | bool | `true` | | | securityContext.runAsNonRoot | bool | `true` | | | securityContext.runAsUser | int | `65532` | | -| service.port | int | `8080` | | -| service.type | string | `"ClusterIP"` | | +| service.port | int | `8080` | port where the server will be exposed at | +| service.type | string | `"ClusterIP"` | service type | | startupProbe.failureThreshold | int | `10` | | | startupProbe.initialDelaySeconds | int | `60` | | | startupProbe.periodSeconds | int | `30` | | @@ -70,5 +74,17 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | startupProbe.timeoutSeconds | int | `30` | | | tolerations | list | `[]` | pod tolerations | +## Development + +To update the Helm chart when a new version of the `hapiproject/hapi` image is released, the [Chart.yaml](Chart.yaml)'s +`appVersion` and `version` fields need to be updated accordingly. Afterwards, re-generate the [README.md](README.md) +by running: + +```sh +$ helm-docs +INFO[2021-11-20T12:38:04Z] Found Chart directories [charts/hapi-fhir-jpaserver] +INFO[2021-11-20T12:38:04Z] Generating README Documentation for chart /usr/src/app/charts/hapi-fhir-jpaserver +``` + ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.5.0](https://github.com/norwoodj/helm-docs/releases/v1.5.0) diff --git a/charts/hapi-fhir-jpaserver/README.md.gotmpl b/charts/hapi-fhir-jpaserver/README.md.gotmpl index c599d14392e..e345f8be8cb 100644 --- a/charts/hapi-fhir-jpaserver/README.md.gotmpl +++ b/charts/hapi-fhir-jpaserver/README.md.gotmpl @@ -11,6 +11,21 @@ helm repo add hapifhir https://hapifhir.github.io/hapi-fhir-jpaserver-starter/ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver ``` +> ⚠ By default, the included [PostgreSQL Helm chart](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrading) +> auto-generates a random password for the database which may cause problems when upgrading the chart (see [here for details](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrading)). + {{ template "chart.valuesSection" . }} +## Development + +To update the Helm chart when a new version of the `hapiproject/hapi` image is released, the [Chart.yaml](Chart.yaml)'s +`appVersion` and `version` fields need to be updated accordingly. Afterwards, re-generate the [README.md](README.md) +by running: + +```sh +$ helm-docs +INFO[2021-11-20T12:38:04Z] Found Chart directories [charts/hapi-fhir-jpaserver] +INFO[2021-11-20T12:38:04Z] Generating README Documentation for chart /usr/src/app/charts/hapi-fhir-jpaserver +``` + {{ template "helm-docs.versionFooter" . }} diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index 5e3c63bfb3c..13feab2de7e 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -2,13 +2,16 @@ replicaCount: 1 image: + # -- registry where the HAPI FHIR server image is hosted registry: docker.io + # -- the path inside the repository repository: hapiproject/hapi # -- defaults to `Chart.appVersion` tag: "" # -- the flavor or variant of the image to use. # appended to the image tag by `-`. flavor: "distroless" + # -- image pullPolicy to use pullPolicy: IfNotPresent # -- image pull secrets to use when pulling the image @@ -42,7 +45,9 @@ securityContext: # service to expose the server service: + # -- service type type: ClusterIP + # -- port where the server will be exposed at port: 8080 ingress: @@ -157,3 +162,9 @@ networkPolicy: # matchLabels: # app.kubernetes.io/name: {{ $.Release.Name }} allowedFrom: [] + +# -- extra environment variables to set on the server container +extraEnv: + [] + # - name: SPRING_FLYWAY_BASELINE_ON_MIGRATE + # value: "true" From 304f779a2bbccd98471b0e831ce912058ee07025 Mon Sep 17 00:00:00 2001 From: chgl Date: Tue, 23 Nov 2021 00:11:28 +0100 Subject: [PATCH 018/192] added options for specifying a PodDisruptionBudget --- charts/hapi-fhir-jpaserver/Chart.yaml | 3 +++ charts/hapi-fhir-jpaserver/README.md | 3 +++ .../templates/poddisruptionbudget.yaml | 19 +++++++++++++++++++ charts/hapi-fhir-jpaserver/values.yaml | 9 +++++++++ 4 files changed, 34 insertions(+) create mode 100644 charts/hapi-fhir-jpaserver/templates/poddisruptionbudget.yaml diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index b4cb3ac9213..dd2c479314a 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -19,5 +19,8 @@ annotations: - kind: changed description: | updated HAPI FHIR starter image to 5.6.0 + - kind: added + description: | + added support for configuring PodDisruptionBudget for the server pods appVersion: v5.6.0 version: 0.7.0 diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index efbf65d54be..9208bd6f967 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -47,6 +47,9 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | networkPolicy.explicitNamespacesSelector | object | `{}` | a Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed | | nodeSelector | object | `{}` | node selector for the pod | | podAnnotations | object | `{}` | annotations applied to the server pod | +| podDisruptionBudget.enabled | bool | `false` | Enable PodDisruptionBudget for the server pods. uses policy/v1/PodDisruptionBudget thus requiring k8s 1.21+ | +| podDisruptionBudget.maxUnavailable | string | `""` | maximum unavailable instances | +| podDisruptionBudget.minAvailable | int | `1` | minimum available instances | | podSecurityContext | object | `{}` | pod security context | | postgresql.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | | | postgresql.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | | diff --git a/charts/hapi-fhir-jpaserver/templates/poddisruptionbudget.yaml b/charts/hapi-fhir-jpaserver/templates/poddisruptionbudget.yaml new file mode 100644 index 00000000000..8c35cdd9019 --- /dev/null +++ b/charts/hapi-fhir-jpaserver/templates/poddisruptionbudget.yaml @@ -0,0 +1,19 @@ + +{{- if .Values.podDisruptionBudget.enabled }} +kind: PodDisruptionBudget +apiVersion: policy/v1 +metadata: + name: {{ include "hapi-fhir-jpaserver.fullname" . }} + labels: + {{- include "hapi-fhir-jpaserver.labels" . | nindent 4 }} +spec: + {{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "hapi-fhir-jpaserver.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index 13feab2de7e..5fb71ddb257 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -168,3 +168,12 @@ extraEnv: [] # - name: SPRING_FLYWAY_BASELINE_ON_MIGRATE # value: "true" + +podDisruptionBudget: + # -- Enable PodDisruptionBudget for the server pods. + # uses policy/v1/PodDisruptionBudget thus requiring k8s 1.21+ + enabled: false + # -- minimum available instances + minAvailable: 1 + # -- maximum unavailable instances + maxUnavailable: "" From 8ce44c2ae114cfcada91eacc5002c155fcffa9d0 Mon Sep 17 00:00:00 2001 From: chgl Date: Tue, 23 Nov 2021 00:12:26 +0100 Subject: [PATCH 019/192] simplified chart release workflow the Ubuntu runner base image already includes Helm 3.7.0 --- .github/workflows/chart-release.yaml | 5 ----- .github/workflows/chart-test.yaml | 5 ----- .../hapi-fhir-jpaserver/templates/poddisruptionbudget.yaml | 1 - 3 files changed, 11 deletions(-) diff --git a/.github/workflows/chart-release.yaml b/.github/workflows/chart-release.yaml index 5d30c2f47e7..ae2045ceb05 100644 --- a/.github/workflows/chart-release.yaml +++ b/.github/workflows/chart-release.yaml @@ -21,11 +21,6 @@ jobs: git config user.name "$GITHUB_ACTOR" git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - - name: Install Helm - uses: azure/setup-helm@v1 - with: - version: v3.7.0 - - name: Add bitnami repo run: helm repo add bitnami https://charts.bitnami.com/bitnami diff --git a/.github/workflows/chart-test.yaml b/.github/workflows/chart-test.yaml index 90bb32a8208..b3eb576bf83 100644 --- a/.github/workflows/chart-test.yaml +++ b/.github/workflows/chart-test.yaml @@ -43,11 +43,6 @@ jobs: with: fetch-depth: 0 - - name: Set up Helm - uses: azure/setup-helm@v1 - with: - version: v3.7.0 - - name: Set up chart-testing uses: helm/chart-testing-action@v2.1.0 diff --git a/charts/hapi-fhir-jpaserver/templates/poddisruptionbudget.yaml b/charts/hapi-fhir-jpaserver/templates/poddisruptionbudget.yaml index 8c35cdd9019..bae8dad8a9a 100644 --- a/charts/hapi-fhir-jpaserver/templates/poddisruptionbudget.yaml +++ b/charts/hapi-fhir-jpaserver/templates/poddisruptionbudget.yaml @@ -1,4 +1,3 @@ - {{- if .Values.podDisruptionBudget.enabled }} kind: PodDisruptionBudget apiVersion: policy/v1 From 6092200db727123afdde4b4422b16f5d7f3624a5 Mon Sep 17 00:00:00 2001 From: ppalacin Date: Thu, 25 Nov 2021 12:00:23 +0100 Subject: [PATCH 020/192] Support HTTPS --- .../jpa/starter/FhirServerConfigDstu3.java | 28 +++++++++--------- .../fhir/jpa/starter/FhirServerConfigR4.java | 29 +++++++++---------- .../fhir/jpa/starter/FhirServerConfigR5.java | 12 ++++---- 3 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index 84822ddd3f4..9f80a5ef7e7 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -89,20 +89,20 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM @Bean() public ElasticsearchSvcImpl elasticsearchSvc() { - if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { - String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); - String elasticsearchHost; - if (elasticsearchUrl.startsWith("http")) { - elasticsearchHost = elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3, elasticsearchUrl.lastIndexOf(":")); - } else { - elasticsearchHost = elasticsearchUrl.substring(0, elasticsearchUrl.indexOf(":")); - } - String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); - String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchUsername, elasticsearchPassword); - } else { - return null; - } + if (Boolean.TRUE.equals(EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment))) { + String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); + String elasticsearchHost = elasticsearchUrl; + String elasticsearchProtocol = EnvironmentHelper.getElasticsearchServerProtocol(configurableEnvironment); + if (elasticsearchUrl.startsWith("http")) { + elasticsearchProtocol = elasticsearchUrl.split("://")[0]; + elasticsearchHost = elasticsearchUrl.split("://")[1]; + } + String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); + String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); + return new ElasticsearchSvcImpl(elasticsearchProtocol, elasticsearchHost, elasticsearchUsername, elasticsearchPassword); + } else { + return null; + } } } 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 842256a26fa..7959645f31e 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -85,21 +85,20 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM @Bean() public ElasticsearchSvcImpl elasticsearchSvc() { - if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { - String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); - String elasticsearchHost; - if (elasticsearchUrl.startsWith("http")) { - elasticsearchHost = elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3, elasticsearchUrl.lastIndexOf(":")); - } else { - elasticsearchHost = elasticsearchUrl.substring(0, elasticsearchUrl.indexOf(":")); - } - - String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); - String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchUsername, elasticsearchPassword); - } else { - return null; - } + if (Boolean.TRUE.equals(EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment))) { + String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); + String elasticsearchHost = elasticsearchUrl; + String elasticsearchProtocol = EnvironmentHelper.getElasticsearchServerProtocol(configurableEnvironment); + if (elasticsearchUrl.startsWith("http")) { + elasticsearchProtocol = elasticsearchUrl.split("://")[0]; + elasticsearchHost = elasticsearchUrl.split("://")[1]; + } + String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); + String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); + return new ElasticsearchSvcImpl(elasticsearchProtocol, elasticsearchHost, elasticsearchUsername, elasticsearchPassword); + } else { + return null; + } } } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index 3cb696833d9..556bef1ff38 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -86,17 +86,17 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM @Bean() public ElasticsearchSvcImpl elasticsearchSvc() { - if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { + if (Boolean.TRUE.equals(EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment))) { String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); String elasticsearchHost; + String elasticsearchProtocol = EnvironmentHelper.getElasticsearchServerProtocol(configurableEnvironment); if (elasticsearchUrl.startsWith("http")) { - elasticsearchHost = elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3, elasticsearchUrl.lastIndexOf(":")); - } else { - elasticsearchHost = elasticsearchUrl.substring(0, elasticsearchUrl.indexOf(":")); - } + elasticsearchProtocol = elasticsearchUrl.split("://")[0]; + elasticsearchHost = elasticsearchUrl.split("://")[1]; + } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(elasticsearchProtocol, elasticsearchHost, elasticsearchUsername, elasticsearchPassword); } else { return null; } From ff8302a04e09176777fae9e44cf62ca6fd224f43 Mon Sep 17 00:00:00 2001 From: ppalacin Date: Thu, 25 Nov 2021 12:20:04 +0100 Subject: [PATCH 021/192] Use default application.yaml --- src/main/resources/application.yaml | 176 ++++++++++++++-------------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index bca18601146..b1ec01c0a97 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -17,20 +17,20 @@ spring: properties: hibernate.format_sql: false hibernate.show_sql: false -# hibernate.dialect: org.hibernate.dialect.h2dialect -# hibernate.hbm2ddl.auto: update -# hibernate.jdbc.batch_size: 20 -# hibernate.cache.use_query_cache: false -# hibernate.cache.use_second_level_cache: false -# hibernate.cache.use_structured_entries: false -# hibernate.cache.use_minimal_puts: false -### These settings will enable fulltext search with lucene -# hibernate.search.enabled: true -# hibernate.search.backend.type: lucene -# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiLuceneAnalysisConfigurer -# hibernate.search.backend.directory.type: local-filesystem -# hibernate.search.backend.directory.root: target/lucenefiles -# hibernate.search.backend.lucene_version: lucene_current + # hibernate.dialect: org.hibernate.dialect.h2dialect + # hibernate.hbm2ddl.auto: update + # hibernate.jdbc.batch_size: 20 + # hibernate.cache.use_query_cache: false + # hibernate.cache.use_second_level_cache: false + # hibernate.cache.use_structured_entries: false + # hibernate.cache.use_minimal_puts: false + ### These settings will enable fulltext search with lucene + # hibernate.search.enabled: true + # hibernate.search.backend.type: lucene + # hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiLuceneAnalysisConfigurer + # hibernate.search.backend.directory.type: local-filesystem + # hibernate.search.backend.directory.root: target/lucenefiles + # hibernate.search.backend.lucene_version: lucene_current batch: job: enabled: false @@ -40,57 +40,57 @@ hapi: openapi_enabled: true ### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5 fhir_version: R4 -### enable to use the ApacheProxyAddressStrategy which uses X-Forwarded-* headers -### to determine the FHIR server address -# use_apache_address_strategy: false -### forces the use of the https:// protocol for the returned server address. -### alternatively, it may be set using the X-Forwarded-Proto header. -# use_apache_address_strategy_https: false -### enable to set the Server URL -# server_address: http://hapi.fhir.org/baseR4 -# defer_indexing_for_codesystems_of_size: 101 -# install_transitive_ig_dependencies: true -# implementationguides: -### example from registry (packages.fhir.org) -# swiss: -# name: swiss.mednet.fhir -# version: 0.8.0 -# example not from registry -# ips_1_0_0: -# url: https://build.fhir.org/ig/HL7/fhir-ips/package.tgz -# name: hl7.fhir.uv.ips -# version: 1.0.0 -# supported_resource_types: -# - Patient -# - Observation -# allow_cascading_deletes: true -# allow_contains_searches: true -# allow_external_references: true -# allow_multiple_delete: true -# allow_override_default_search_params: true -# auto_create_placeholder_reference_targets: false -# cql_enabled: true -# default_encoding: JSON -# default_pretty_print: true -# default_page_size: 20 -# delete_expunge_enabled: true -# enable_repository_validating_interceptor: false -# enable_index_missing_fields: false -# enable_index_contained_resource: false -# enforce_referential_integrity_on_delete: false -# enforce_referential_integrity_on_write: false -# etag_support_enabled: true -# expunge_enabled: true -# daoconfig_client_id_strategy: null -# client_id_strategy: ALPHANUMERIC -# fhirpath_interceptor_enabled: false -# filter_search_enabled: true -# graphql_enabled: true -# narrative_enabled: true -# mdm_enabled: true -# partitioning: -# allow_references_across_partitions: false -# partitioning_include_in_search_hashes: false + ### enable to use the ApacheProxyAddressStrategy which uses X-Forwarded-* headers + ### to determine the FHIR server address + # use_apache_address_strategy: false + ### forces the use of the https:// protocol for the returned server address. + ### alternatively, it may be set using the X-Forwarded-Proto header. + # use_apache_address_strategy_https: false + ### enable to set the Server URL + # server_address: http://hapi.fhir.org/baseR4 + # defer_indexing_for_codesystems_of_size: 101 + # install_transitive_ig_dependencies: true + # implementationguides: + ### example from registry (packages.fhir.org) + # swiss: + # name: swiss.mednet.fhir + # version: 0.8.0 + # example not from registry + # ips_1_0_0: + # url: https://build.fhir.org/ig/HL7/fhir-ips/package.tgz + # name: hl7.fhir.uv.ips + # version: 1.0.0 + # supported_resource_types: + # - Patient + # - Observation + # allow_cascading_deletes: true + # allow_contains_searches: true + # allow_external_references: true + # allow_multiple_delete: true + # allow_override_default_search_params: true + # auto_create_placeholder_reference_targets: false + # cql_enabled: true + # default_encoding: JSON + # default_pretty_print: true + # default_page_size: 20 + # delete_expunge_enabled: true + # enable_repository_validating_interceptor: false + # enable_index_missing_fields: false + # enable_index_contained_resource: false + # enforce_referential_integrity_on_delete: false + # enforce_referential_integrity_on_write: false + # etag_support_enabled: true + # expunge_enabled: true + # daoconfig_client_id_strategy: null + # client_id_strategy: ALPHANUMERIC + # fhirpath_interceptor_enabled: false + # filter_search_enabled: true + # graphql_enabled: true + # narrative_enabled: true + # mdm_enabled: true + # partitioning: + # allow_references_across_partitions: false + # partitioning_include_in_search_hashes: false cors: allow_Credentials: true # These are allowed_origin patterns, see: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/cors/CorsConfiguration.html#setAllowedOriginPatterns-java.util.List- @@ -102,30 +102,30 @@ hapi: search-coord-max-pool-size: 100 search-coord-queue-capacity: 200 -# logger: -# error_format: 'ERROR - ${requestVerb} ${requestUrl}' -# format: >- -# Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] -# Operation[${operationType} ${operationName} ${idOrResourceName}] -# UA[${requestHeader.user-agent}] Params[${requestParameters}] -# ResponseEncoding[${responseEncodingNoDefault}] -# log_exceptions: true -# name: fhirtest.access -# max_binary_size: 104857600 -# max_page_size: 200 -# retain_cached_searches_mins: 60 -# reuse_cached_search_results_millis: 60000 + # logger: + # error_format: 'ERROR - ${requestVerb} ${requestUrl}' + # format: >- + # Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] + # Operation[${operationType} ${operationName} ${idOrResourceName}] + # UA[${requestHeader.user-agent}] Params[${requestParameters}] + # ResponseEncoding[${responseEncodingNoDefault}] + # log_exceptions: true + # name: fhirtest.access + # max_binary_size: 104857600 + # max_page_size: 200 + # retain_cached_searches_mins: 60 + # reuse_cached_search_results_millis: 60000 tester: - home: - name: Local Tester - server_address: 'http://localhost:8080/fhir' - refuse_to_fetch_third_party_urls: false - fhir_version: R4 - global: - name: Global Tester - server_address: "http://hapi.fhir.org/baseR4" - refuse_to_fetch_third_party_urls: false - fhir_version: R4 + home: + name: Local Tester + server_address: 'http://localhost:8080/fhir' + refuse_to_fetch_third_party_urls: false + fhir_version: R4 + 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 From e077091db42555d1e588d20fdbc34a0781ebd643 Mon Sep 17 00:00:00 2001 From: Ally Shaban Date: Wed, 1 Dec 2021 07:58:43 +0300 Subject: [PATCH 022/192] registering ValueSetOperationProvider --- .../java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 b58c41cb20d..ff533059e24 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -22,6 +22,7 @@ import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider; import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; +import ca.uhn.fhir.jpa.provider.ValueSetOperationProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor; import ca.uhn.fhir.mdm.provider.MdmProviderLoader; @@ -92,6 +93,8 @@ public class BaseJpaRestfulServer extends RestfulServer { @Autowired PartitionManagementProvider partitionManagementProvider; @Autowired + ValueSetOperationProvider valueSetOperationProvider; + @Autowired BinaryStorageInterceptor binaryStorageInterceptor; @Autowired IPackageInstallerSvc packageInstallerSvc; @@ -367,6 +370,9 @@ protected void initialize() throws ServletException { registerProvider(bulkDataExportProvider); } + // valueSet Operations i.e $expand + registerProvider(valueSetOperationProvider); + // Partitioning if (appProperties.getPartitioning() != null) { registerInterceptor(new RequestTenantPartitionInterceptor()); From 8c6a1a713e85833ba180388c97c1c9e004fa76ac Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Thu, 9 Dec 2021 14:54:20 -0500 Subject: [PATCH 023/192] Upgrade to 5.7.0-PRE4-SNAPSHOT for testing --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bb5986d73c5..2c7ebb6c92f 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.6.0 + 5.7.0-PRE4-SNAPSHOT hapi-fhir-jpaserver-starter From bfa6ed1c1ec2348fe7cf853f7549c6aa565595ed Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Thu, 9 Dec 2021 16:14:13 -0500 Subject: [PATCH 024/192] Share elasticsearch configuration --- .../jpa/starter/BaseJpaRestfulServer.java | 2 +- .../fhir/jpa/starter/ElasticsearchConfig.java | 33 +++++++++++++++++++ .../jpa/starter/FhirServerConfigDstu3.java | 19 +---------- .../fhir/jpa/starter/FhirServerConfigR4.java | 19 +---------- .../fhir/jpa/starter/FhirServerConfigR5.java | 23 ++----------- 5 files changed, 39 insertions(+), 57 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java 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 736c3daa80e..e272c981152 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -11,11 +11,11 @@ import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.binstore.BinaryStorageInterceptor; import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider; +import ca.uhn.fhir.jpa.graphql.GraphQLProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc; import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; 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.JpaCapabilityStatementProvider; import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java new file mode 100644 index 00000000000..fd27e84ee36 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java @@ -0,0 +1,33 @@ +package ca.uhn.fhir.jpa.starter; + +import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.ConfigurableEnvironment; + +/** Shared configuration for Elasticsearch */ +@Configuration +public class ElasticsearchConfig { + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ElasticsearchConfig.class); + + @Autowired + private ConfigurableEnvironment configurableEnvironment; + + @Bean() + public ElasticsearchSvcImpl elasticsearchSvc() { + if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { + String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); + if (elasticsearchUrl.startsWith("http")) { + elasticsearchUrl =elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3); + } + String elasticsearchProtocol = EnvironmentHelper.getElasticsearchServerProtocol(configurableEnvironment); + String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); + String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); + ourLog.info("Configuring elasticsearch {} {}", elasticsearchProtocol, elasticsearchUrl); + return new ElasticsearchSvcImpl(elasticsearchProtocol, elasticsearchUrl, elasticsearchUsername, elasticsearchPassword); + } else { + return null; + } + } +} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index 0baa646bf85..074d5b74ee9 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -3,7 +3,6 @@ import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; -import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU3Condition; import ca.uhn.fhir.jpa.starter.cql.StarterCqlDstu3Config; import javax.annotation.PostConstruct; @@ -22,7 +21,7 @@ @Configuration @Conditional(OnDSTU3Condition.class) -@Import(StarterCqlDstu3Config.class) +@Import({StarterCqlDstu3Config.class, ElasticsearchConfig.class}) public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { @Autowired @@ -87,20 +86,4 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM retVal.setEntityManagerFactory(entityManagerFactory); return retVal; } - - @Bean() - public ElasticsearchSvcImpl elasticsearchSvc() { - if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { - String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); - if (elasticsearchUrl.startsWith("http")) { - elasticsearchUrl =elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3); - } - String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); - String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(elasticsearchUrl, elasticsearchUsername, elasticsearchPassword); - } else { - return null; - } - } - } 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 4148bd46b73..c37d4468d7f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -3,7 +3,6 @@ import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.jpa.config.BaseJavaConfigR4; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; -import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; import ca.uhn.fhir.jpa.starter.cql.StarterCqlR4Config; import org.springframework.beans.factory.annotation.Autowired; @@ -19,7 +18,7 @@ @Configuration @Conditional(OnR4Condition.class) -@Import(StarterCqlR4Config.class) +@Import({StarterCqlR4Config.class, ElasticsearchConfig.class}) public class FhirServerConfigR4 extends BaseJavaConfigR4 { @Autowired @@ -83,20 +82,4 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM return retVal; } - @Bean() - public ElasticsearchSvcImpl elasticsearchSvc() { - if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { - String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); - if (elasticsearchUrl.startsWith("http")) { - elasticsearchUrl =elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3); - } - - String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); - String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(elasticsearchUrl, elasticsearchUsername, elasticsearchPassword); - } else { - return null; - } - } - } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index ccd7074433b..a4305db8888 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -5,12 +5,10 @@ import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition; +import ca.uhn.fhir.jpa.starter.cql.StarterCqlR4Config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Conditional; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.*; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -21,6 +19,7 @@ @Configuration @Conditional(OnR5Condition.class) +@Import({ElasticsearchConfig.class}) public class FhirServerConfigR5 extends BaseJavaConfigR5 { @Autowired @@ -84,20 +83,4 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM return retVal; } - @Bean() - public ElasticsearchSvcImpl elasticsearchSvc() { - if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { - String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); - if (elasticsearchUrl.startsWith("http")) { - elasticsearchUrl =elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3); - } - String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); - String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(elasticsearchUrl, elasticsearchUsername, elasticsearchPassword); - } else { - return null; - } - } - - } From 8568132896cdfa60febe99d89ebcc77367b0bf93 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Sat, 11 Dec 2021 17:08:36 +0100 Subject: [PATCH 025/192] Fixed compile issues --- .../java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java | 5 +++-- .../java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java | 5 +++-- .../java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index 9f80a5ef7e7..c795f971c65 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -2,6 +2,7 @@ import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3; +import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU3Condition; @@ -88,7 +89,7 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM } @Bean() - public ElasticsearchSvcImpl elasticsearchSvc() { + public ElasticsearchSvcImpl elasticsearchSvc(PartitionSettings thePartitionSetings) { if (Boolean.TRUE.equals(EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment))) { String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); String elasticsearchHost = elasticsearchUrl; @@ -99,7 +100,7 @@ public ElasticsearchSvcImpl elasticsearchSvc() { } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(elasticsearchProtocol, elasticsearchHost, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(thePartitionSetings, elasticsearchUrl, elasticsearchUsername, elasticsearchPassword); } else { return null; } 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 7959645f31e..e49ca4af1e4 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -2,6 +2,7 @@ import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.jpa.config.BaseJavaConfigR4; +import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; @@ -84,7 +85,7 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM } @Bean() - public ElasticsearchSvcImpl elasticsearchSvc() { + public ElasticsearchSvcImpl elasticsearchSvc(PartitionSettings thePartitionSetings) { if (Boolean.TRUE.equals(EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment))) { String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); String elasticsearchHost = elasticsearchUrl; @@ -95,7 +96,7 @@ public ElasticsearchSvcImpl elasticsearchSvc() { } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(elasticsearchProtocol, elasticsearchHost, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(thePartitionSetings, elasticsearchUrl, elasticsearchUsername, elasticsearchPassword); } else { return null; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index 556bef1ff38..2bb392c0315 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -2,6 +2,7 @@ import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.jpa.config.BaseJavaConfigR5; +import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition; @@ -85,7 +86,7 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM } @Bean() - public ElasticsearchSvcImpl elasticsearchSvc() { + public ElasticsearchSvcImpl elasticsearchSvc(PartitionSettings thePartitionSetings) { if (Boolean.TRUE.equals(EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment))) { String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); String elasticsearchHost; @@ -96,7 +97,7 @@ public ElasticsearchSvcImpl elasticsearchSvc() { } String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(elasticsearchProtocol, elasticsearchHost, elasticsearchUsername, elasticsearchPassword); + return new ElasticsearchSvcImpl(thePartitionSetings, elasticsearchUrl, elasticsearchUsername, elasticsearchPassword); } else { return null; } From 21f5d1dcbb74674294715802182199f8f39ec813 Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Thu, 16 Dec 2021 17:14:31 -0500 Subject: [PATCH 026/192] Fix misconfiguration modelConfig is part of DaoConfig and should not have a separate lifecycle. --- .../ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java | 4 ++-- src/main/resources/application.yaml | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) 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 47e06dd7f6e..80f75f5a719 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -160,8 +160,8 @@ public HibernatePropertiesProvider jpaStarterDialectProvider(LocalContainerEntit } @Bean - public ModelConfig modelConfig(AppProperties appProperties) { - ModelConfig modelConfig = new ModelConfig(); + public ModelConfig modelConfig(AppProperties appProperties, DaoConfig daoConfig) { + ModelConfig modelConfig = daoConfig.getModelConfig(); modelConfig.setAllowContainsSearches(appProperties.getAllow_contains_searches()); modelConfig.setAllowExternalReferences(appProperties.getAllow_external_references()); modelConfig.setDefaultSearchParamsCanBeOverridden(appProperties.getAllow_override_default_search_params()); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 049d8012ee0..d7abaf2eb69 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,6 +1,8 @@ spring: flyway: enabled: false + check-location: false + baselineOnMigrate: true datasource: url: 'jdbc:h2:file:./target/database/h2' #url: jdbc:h2:mem:test_mem @@ -12,9 +14,6 @@ spring: # database connection pool size hikari: maximum-pool-size: 10 - flyway: - check-location: false - baselineOnMigrate: true jpa: properties: hibernate.format_sql: false @@ -92,6 +91,8 @@ hapi: # graphql_enabled: true # narrative_enabled: true # mdm_enabled: true +# local_base_urls: +# - https://hapi.fhir.org/baseR4 # partitioning: # allow_references_across_partitions: false # partitioning_include_in_search_hashes: false From 42e3e78bbcb922a3c6f468830c397ab7122adf49 Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Fri, 17 Dec 2021 18:05:49 -0500 Subject: [PATCH 027/192] Bump to 5.7.0-PRE8-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2c7ebb6c92f..77319080b88 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.7.0-PRE4-SNAPSHOT + 5.7.0-PRE8-SNAPSHOT hapi-fhir-jpaserver-starter From 22e0e1e4bf44bfbb8a5384b6c1d236cb39cdce3f Mon Sep 17 00:00:00 2001 From: Vadim Peretokin Date: Mon, 3 Jan 2022 14:00:34 +0100 Subject: [PATCH 028/192] Typo fix in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb2dcfb7a8e..57cd00ed017 100644 --- a/README.md +++ b/README.md @@ -368,7 +368,7 @@ using the `gcr.io/distroless/java-debian10:11` base image: docker build --target=release-distroless -t hapi-fhir:distroless . ``` -Note that distroless images are also automatically build and pushed to the container registry, +Note that distroless images are also automatically built and pushed to the container registry, see the `-distroless` suffix in the image tags. ## Adding custom operations From 528d2bc087ae2f5bf49b2fb38d17dba134feda63 Mon Sep 17 00:00:00 2001 From: Jaison B Date: Wed, 5 Jan 2022 15:02:57 -0700 Subject: [PATCH 029/192] Add configuration flag to enable storing of resources in lucene index (#304) * Add configuration flag to enable storing of resources in lucene index * Fix build issue * Fix code review suggestions Co-authored-by: Jaison B --- README.md | 8 ++++++-- .../java/ca/uhn/fhir/jpa/starter/AppProperties.java | 11 ++++++++++- .../uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 4 ++-- .../uhn/fhir/jpa/starter/FhirServerConfigCommon.java | 12 ++++++------ src/main/resources/application.yaml | 1 + .../uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java | 1 + 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index bb2dcfb7a8e..8e6a36c3bbc 100644 --- a/README.md +++ b/README.md @@ -354,10 +354,14 @@ elasticsearch.schema_management_strategy=CREATE Set `hapi.fhir.lastn_enabled=true` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file to enable the $lastn operation on this server. Note that the $lastn operation relies on Elasticsearch, so for $lastn to work, indexing must be enabled using Elasticsearch. +## Enabling Resource to be stored in Lucene Index + +Set `hapi.fhir.store_resource_in_lucene_index_enabled` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file to enable storing of resource json along with Lucene/Elasticsearch index mappings. + ## Changing cached search results time -It is possible to change the cached search results time. The option `reuse_cached_search_results_millis` in the [application.yaml] is 6000 miliseconds by default. -Set `reuse_cached_search_results_millis: -1` in the [application.yaml] file to ignore the cache time every search. +It is possible to change the cached search results time. The option `reuse_cached_search_results_millis` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) is 6000 miliseconds by default. +Set `reuse_cached_search_results_millis: -1` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file to ignore the cache time every search. ## Build the distroless variant of the image (for lower footprint and improved security) 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 2a7df3811e0..1118df7fd55 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -66,6 +66,7 @@ public class AppProperties { private Map implementationGuides = null; private Boolean lastn_enabled = false; + private boolean store_resource_in_lucene_index_enabled = false; private NormalizedQuantitySearchLevel normalized_quantity_search_level = NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED; private Integer search_coord_core_pool_size = 20; @@ -469,7 +470,15 @@ public void setLastn_enabled(Boolean lastn_enabled) { this.lastn_enabled = lastn_enabled; } - public NormalizedQuantitySearchLevel getNormalized_quantity_search_level() { + public boolean getStore_resource_in_lucene_index_enabled() { + return store_resource_in_lucene_index_enabled; + } + + public void setStore_resource_in_lucene_index_enabled(Boolean store_resource_in_lucene_index_enabled) { + this.store_resource_in_lucene_index_enabled = store_resource_in_lucene_index_enabled; + } + + public NormalizedQuantitySearchLevel getNormalized_quantity_search_level() { return this.normalized_quantity_search_level; } 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 e272c981152..36ef8efd364 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -407,8 +407,8 @@ protected void initialize() throws ServletException { daoConfig.setLastNEnabled(true); } + daoConfig.setStoreResourceInLuceneIndex(appProperties.getStore_resource_in_lucene_index_enabled()); daoConfig.getModelConfig().setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); - - daoConfig.getModelConfig().setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); + daoConfig.getModelConfig().setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); } } 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 80f75f5a719..3dcc0b14664 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -11,6 +11,7 @@ import ca.uhn.fhir.jpa.subscription.match.deliver.email.EmailSenderImpl; import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender; import ca.uhn.fhir.rest.server.mail.MailConfig; +import ca.uhn.fhir.rest.server.mail.MailSvc; import com.google.common.base.Strings; import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.dstu2.model.Subscription; @@ -69,7 +70,7 @@ public FhirServerConfigCommon(AppProperties appProperties) { if (appProperties.getSubscription().getEmail() != null) { ourLog.info("Email subscriptions enabled"); } - + if (appProperties.getEnable_index_contained_resource() == Boolean.TRUE) { ourLog.info("Indexed on contained resource enabled"); } @@ -145,7 +146,7 @@ public PartitionSettings partitionSettings(AppProperties appProperties) { if(appProperties.getPartitioning().getAllow_references_across_partitions()) { retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.ALLOWED_UNQUALIFIED); } else { - retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.NOT_ALLOWED); + retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.NOT_ALLOWED); } } @@ -178,7 +179,7 @@ public ModelConfig modelConfig(AppProperties appProperties, DaoConfig daoConfig) } modelConfig.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); - + modelConfig.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); return modelConfig; } @@ -225,10 +226,9 @@ public IEmailSender emailSender(AppProperties appProperties, Optional theSubscriptionDeliveryHandlerFactory.setEmailSender(emailSender)); return emailSender; } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index d7abaf2eb69..17b1dfb4b58 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -154,6 +154,7 @@ hapi: # startTlsRequired: # quitWait: # lastn_enabled: true +# store_resource_in_lucene_index_enabled: true ### This is configuration for normalized quantity serach level default is 0 ### 0: NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED - default ### 1: NORMALIZED_QUANTITY_STORAGE_SUPPORTED diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 24dfada96cb..1387354f75e 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -42,6 +42,7 @@ "spring.datasource.url=jdbc:h2:mem:dbr4", "hapi.fhir.fhir_version=r4", "hapi.fhir.lastn_enabled=true", + "hapi.fhir.store_resource_in_lucene_index_enabled=true", "elasticsearch.enabled=true", // Because the port is set randomly, we will set the rest_url using the Initializer. // "elasticsearch.rest_url='http://localhost:9200'", From 5312f78b956d4ad4863580035972263586d616c3 Mon Sep 17 00:00:00 2001 From: Jaison B Date: Mon, 24 Jan 2022 16:21:50 -0700 Subject: [PATCH 030/192] Add ES native aggregation builder for lastN --- pom.xml | 2 +- src/main/resources/application.yaml | 35 ++++++++++++++++------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/pom.xml b/pom.xml index 77319080b88..e8e5d4847e2 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.7.0-PRE8-SNAPSHOT + 5.7.0-PRE9-SNAPSHOT hapi-fhir-jpaserver-starter diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 17b1dfb4b58..9313f4fe74d 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -5,7 +5,7 @@ spring: baselineOnMigrate: true datasource: url: 'jdbc:h2:file:./target/database/h2' - #url: jdbc:h2:mem:test_mem +# url: jdbc:h2:mem:test_mem username: sa password: null driverClassName: org.h2.Driver @@ -18,6 +18,7 @@ spring: properties: hibernate.format_sql: false hibernate.show_sql: false + hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect # hibernate.dialect: org.hibernate.dialect.h2dialect # hibernate.hbm2ddl.auto: update # hibernate.jdbc.batch_size: 20 @@ -26,8 +27,12 @@ spring: # hibernate.cache.use_structured_entries: false # hibernate.cache.use_minimal_puts: false ### These settings will enable fulltext search with lucene -# hibernate.search.enabled: true + hibernate.search.enabled: true +# hibernate.search.automatic_indexing.strategy: session +# hibernate.search.automatic_indexing.synchronization.strategy: sync + hibernate.search.backend.type: elasticsearch # hibernate.search.backend.type: lucene + hibernate.search.backedn.analysis.configurer: ca.uhn.fhir.jpa.search.elastic.HapiElasticsearchAnalysisConfigurer # hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiLuceneAnalysisConfigurer # hibernate.search.backend.directory.type: local-filesystem # hibernate.search.backend.directory.root: target/lucenefiles @@ -153,21 +158,21 @@ hapi: # startTlsEnable: # startTlsRequired: # quitWait: -# lastn_enabled: true -# store_resource_in_lucene_index_enabled: true + lastn_enabled: true + store_resource_in_lucene_index_enabled: true ### This is configuration for normalized quantity serach level default is 0 ### 0: NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED - default ### 1: NORMALIZED_QUANTITY_STORAGE_SUPPORTED ### 2: NORMALIZED_QUANTITY_SEARCH_SUPPORTED # normalized_quantity_search_level: 2 -#elasticsearch: -# debug: -# pretty_print_json_log: false -# refresh_after_write: false -# enabled: false -# password: SomePassword -# required_index_status: YELLOW -# rest_url: 'localhost:9200' -# protocol: 'http' -# schema_management_strategy: CREATE -# username: SomeUsername +elasticsearch: + debug: + pretty_print_json_log: true + refresh_after_write: false + enabled: true + password: smilecdr + required_index_status: YELLOW + rest_url: 'localhost:19200' + protocol: 'http' + schema_management_strategy: CREATE + username: elastic From d2984d2c0c1a0744624a60bc083035890040897b Mon Sep 17 00:00:00 2001 From: Jaison B Date: Mon, 24 Jan 2022 16:25:24 -0700 Subject: [PATCH 031/192] Revert "Add ES native aggregation builder for lastN" This reverts commit 5312f78b956d4ad4863580035972263586d616c3. --- pom.xml | 2 +- src/main/resources/application.yaml | 35 +++++++++++++---------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/pom.xml b/pom.xml index e8e5d4847e2..77319080b88 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.7.0-PRE9-SNAPSHOT + 5.7.0-PRE8-SNAPSHOT hapi-fhir-jpaserver-starter diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 9313f4fe74d..17b1dfb4b58 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -5,7 +5,7 @@ spring: baselineOnMigrate: true datasource: url: 'jdbc:h2:file:./target/database/h2' -# url: jdbc:h2:mem:test_mem + #url: jdbc:h2:mem:test_mem username: sa password: null driverClassName: org.h2.Driver @@ -18,7 +18,6 @@ spring: properties: hibernate.format_sql: false hibernate.show_sql: false - hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect # hibernate.dialect: org.hibernate.dialect.h2dialect # hibernate.hbm2ddl.auto: update # hibernate.jdbc.batch_size: 20 @@ -27,12 +26,8 @@ spring: # hibernate.cache.use_structured_entries: false # hibernate.cache.use_minimal_puts: false ### These settings will enable fulltext search with lucene - hibernate.search.enabled: true -# hibernate.search.automatic_indexing.strategy: session -# hibernate.search.automatic_indexing.synchronization.strategy: sync - hibernate.search.backend.type: elasticsearch +# hibernate.search.enabled: true # hibernate.search.backend.type: lucene - hibernate.search.backedn.analysis.configurer: ca.uhn.fhir.jpa.search.elastic.HapiElasticsearchAnalysisConfigurer # hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiLuceneAnalysisConfigurer # hibernate.search.backend.directory.type: local-filesystem # hibernate.search.backend.directory.root: target/lucenefiles @@ -158,21 +153,21 @@ hapi: # startTlsEnable: # startTlsRequired: # quitWait: - lastn_enabled: true - store_resource_in_lucene_index_enabled: true +# lastn_enabled: true +# store_resource_in_lucene_index_enabled: true ### This is configuration for normalized quantity serach level default is 0 ### 0: NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED - default ### 1: NORMALIZED_QUANTITY_STORAGE_SUPPORTED ### 2: NORMALIZED_QUANTITY_SEARCH_SUPPORTED # normalized_quantity_search_level: 2 -elasticsearch: - debug: - pretty_print_json_log: true - refresh_after_write: false - enabled: true - password: smilecdr - required_index_status: YELLOW - rest_url: 'localhost:19200' - protocol: 'http' - schema_management_strategy: CREATE - username: elastic +#elasticsearch: +# debug: +# pretty_print_json_log: false +# refresh_after_write: false +# enabled: false +# password: SomePassword +# required_index_status: YELLOW +# rest_url: 'localhost:9200' +# protocol: 'http' +# schema_management_strategy: CREATE +# username: SomeUsername From 0f133274a1fd43e09abf7559962e6196ddc606a9 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 26 Jan 2022 16:31:41 -0800 Subject: [PATCH 032/192] bump version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 338e9c9fda2..cd08e13c289 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.6.0 + 5.7.0-PRE9-SNAPSHOT hapi-fhir-jpaserver-starter From bbd9428d6e32d75ca55203532bf9565a5f23bd83 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 26 Jan 2022 18:45:45 -0800 Subject: [PATCH 033/192] Update for 5.7.x changes --- .../java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 2 +- .../ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java | 6 ++++-- .../java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java | 5 ++++- .../java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java | 5 ++++- .../java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java | 5 ++++- 5 files changed, 17 insertions(+), 6 deletions(-) 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 ff533059e24..3e6174331a8 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -11,11 +11,11 @@ import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.binstore.BinaryStorageInterceptor; import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider; +import ca.uhn.fhir.jpa.graphql.GraphQLProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc; import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; 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.JpaCapabilityStatementProvider; import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; 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 1e296d9bd3b..b055252ccbd 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -10,7 +10,9 @@ import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory; import ca.uhn.fhir.jpa.subscription.match.deliver.email.EmailSenderImpl; import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender; +import ca.uhn.fhir.rest.server.mail.IMailSvc; import ca.uhn.fhir.rest.server.mail.MailConfig; +import ca.uhn.fhir.rest.server.mail.MailSvc; import com.google.common.base.Strings; import org.hl7.fhir.dstu2.model.Subscription; import org.springframework.boot.env.YamlPropertySourceLoader; @@ -217,9 +219,9 @@ public IEmailSender emailSender(AppProperties appProperties, Optional Date: Wed, 26 Jan 2022 20:28:05 -0800 Subject: [PATCH 034/192] Fix h2 dialect, replace mail dep --- pom.xml | 24 +++++++++++-------- .../uhn/fhir/jpa/starter/mdm/MdmConfig.java | 6 ----- src/main/resources/application.yaml | 4 ++-- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index cd08e13c289..329070b8cbb 100644 --- a/pom.xml +++ b/pom.xml @@ -67,16 +67,20 @@ - - com.sun.mail - javax.mail - 1.6.2 - - - javax.activation - activation - - + + + + + + + + + + + + + org.simplejavamail + simple-java-mail diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java index 301c8833150..39718f6c9ad 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java @@ -24,11 +24,6 @@ @Import({MdmConsumerConfig.class, MdmSubmitterConfig.class}) public class MdmConfig { - @Bean - MdmRuleValidator mdmRuleValidator(FhirContext theFhirContext, ISearchParamRegistry theSearchParamRegistry) { - return new MdmRuleValidator(theFhirContext, theSearchParamRegistry); - } - @Bean IMdmSettings mdmSettings(@Autowired MdmRuleValidator theMdmRuleValidator, AppProperties appProperties) throws IOException { DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); @@ -36,5 +31,4 @@ IMdmSettings mdmSettings(@Autowired MdmRuleValidator theMdmRuleValidator, AppPro String json = IOUtils.toString(resource.getInputStream(), Charsets.UTF_8); return new MdmSettings(theMdmRuleValidator).setEnabled(appProperties.getMdm_enabled()).setScriptText(json); } - } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index b1ec01c0a97..1ad52569f90 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -17,7 +17,7 @@ spring: properties: hibernate.format_sql: false hibernate.show_sql: false - # hibernate.dialect: org.hibernate.dialect.h2dialect + hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect # hibernate.hbm2ddl.auto: update # hibernate.jdbc.batch_size: 20 # hibernate.cache.use_query_cache: false @@ -87,7 +87,7 @@ hapi: # filter_search_enabled: true # graphql_enabled: true # narrative_enabled: true - # mdm_enabled: true + mdm_enabled: true # partitioning: # allow_references_across_partitions: false # partitioning_include_in_search_hashes: false From 4952c00df7d878660d4bd64b4616ef1c140abd4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Feb 2022 00:59:55 +0000 Subject: [PATCH 035/192] Bump postgresql from 42.2.23 to 42.2.25 Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.2.23 to 42.2.25. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.2.23...REL42.2.25) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e8e5d4847e2..d9a0387bc15 100644 --- a/pom.xml +++ b/pom.xml @@ -63,7 +63,7 @@ org.postgresql postgresql - 42.2.23 + 42.2.25 From eac87fca9b1864bfcbd315bc5b25d1fdd1f24972 Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Wed, 2 Feb 2022 10:35:41 -0500 Subject: [PATCH 036/192] bump Hapi PRE version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 77319080b88..62cb82356d6 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.7.0-PRE8-SNAPSHOT + 5.7.0-PRE10-SNAPSHOT hapi-fhir-jpaserver-starter From 56f43324fd816df95610c9ffb60b4cc2b52f1c0a Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Thu, 3 Feb 2022 13:25:22 -0500 Subject: [PATCH 037/192] Bump to Hapi 6.0-SNAPSHOT and register the ValueSet provider. --- pom.xml | 2 +- .../ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 62cb82356d6..7a12c7686ee 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.7.0-PRE10-SNAPSHOT + 6.0.0-PRE1-SNAPSHOT hapi-fhir-jpaserver-starter 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 36ef8efd364..ca6a3622f5f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -16,11 +16,7 @@ import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc; import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; import ca.uhn.fhir.jpa.partition.PartitionManagementProvider; -import ca.uhn.fhir.jpa.provider.IJpaSystemProvider; -import ca.uhn.fhir.jpa.provider.JpaCapabilityStatementProvider; -import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; -import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider; -import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; +import ca.uhn.fhir.jpa.provider.*; import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor; @@ -78,6 +74,8 @@ public class BaseJpaRestfulServer extends RestfulServer { @Autowired IJpaSystemProvider jpaSystemProvider; @Autowired + ValueSetOperationProvider myValueSetOperationProvider; + @Autowired IInterceptorBroadcaster interceptorBroadcaster; @Autowired DatabaseBackedPagingProvider databaseBackedPagingProvider; @@ -141,7 +139,7 @@ protected void initialize() throws ServletException { registerProviders(resourceProviderFactory.createProviders()); registerProvider(jpaSystemProvider); - + registerProvider(myValueSetOperationProvider); /* * 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 From e45ba6ce5b1c56a7b5803c96e811d6eefe1b141d Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Thu, 17 Feb 2022 23:12:10 +0100 Subject: [PATCH 038/192] Version bump to 5.7.0 and a few other components now draw the version from parent --- pom.xml | 12 ++++-------- src/main/resources/application.yaml | 6 +++++- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index d9a0387bc15..69aef165fbf 100644 --- a/pom.xml +++ b/pom.xml @@ -14,18 +14,17 @@ ca.uhn.hapi.fhir hapi-fhir - 5.7.0-PRE9-SNAPSHOT + 5.7.0 hapi-fhir-jpaserver-starter 8 - 2.5.6 - 3.6.3 + 3.8.3 war @@ -57,13 +56,10 @@ mysql mysql-connector-java - 8.0.25 - org.postgresql postgresql - 42.2.25 @@ -164,7 +160,7 @@ org.yaml snakeyaml - 1.29 + 1.30 @@ -197,7 +193,7 @@ org.webjars bootstrap - 3.4.1 + 5.1.3 org.webjars diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 03abf0bdcb7..cc298f4cc5d 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -18,7 +18,11 @@ spring: properties: hibernate.format_sql: false hibernate.show_sql: false - # hibernate.dialect: org.hibernate.dialect.h2dialect + #Hibernate dialect is automatically detected except Postgres and H2. + #If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect + #If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect + + hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect # hibernate.hbm2ddl.auto: update # hibernate.jdbc.batch_size: 20 # hibernate.cache.use_query_cache: false From 3fd880399c81c27094617877483ea6a6b9e09c0b Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Fri, 18 Feb 2022 01:03:49 +0100 Subject: [PATCH 039/192] Update application.yaml Momentarily added `allow-circular-references: true` --- src/main/resources/application.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index cc298f4cc5d..73c5418ee32 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,4 +1,6 @@ spring: + main: + allow-circular-references: true flyway: enabled: false check-location: false From fa8999bd9b0c4a6e91e397838841d0cd9d180017 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 17 Feb 2022 16:11:57 -0800 Subject: [PATCH 040/192] bump to real version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 329070b8cbb..f8e4aac8731 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.7.0-PRE9-SNAPSHOT + 5.7.0 hapi-fhir-jpaserver-starter From 94f47f4736df7293c44336462139ed17dee947d4 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Mon, 21 Feb 2022 16:13:35 -0800 Subject: [PATCH 041/192] Bump version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 69aef165fbf..a08affeef25 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.7.0 + 6.0.0-PRE3-SNAPSHOT hapi-fhir-jpaserver-starter From 0e4926e59bd3aaef09a424fc709f1077cc05dd8c Mon Sep 17 00:00:00 2001 From: Tadgh Date: Mon, 21 Feb 2022 16:24:08 -0800 Subject: [PATCH 042/192] Remove search coord thread pool --- .../uhn/fhir/jpa/starter/AppProperties.java | 21 ------------------- .../jpa/starter/FhirServerConfigDstu2.java | 12 ----------- .../jpa/starter/FhirServerConfigDstu3.java | 13 ------------ .../fhir/jpa/starter/FhirServerConfigR4.java | 15 ++----------- .../fhir/jpa/starter/FhirServerConfigR5.java | 13 ------------ 5 files changed, 2 insertions(+), 72 deletions(-) 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 1118df7fd55..b3534081bbd 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -69,9 +69,6 @@ public class AppProperties { private boolean store_resource_in_lucene_index_enabled = false; private NormalizedQuantitySearchLevel normalized_quantity_search_level = NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED; - private Integer search_coord_core_pool_size = 20; - private Integer search_coord_max_pool_size = 100; - private Integer search_coord_queue_capacity = 200; private Boolean use_apache_address_strategy = false; private Boolean use_apache_address_strategy_https = false; @@ -486,24 +483,6 @@ public void setNormalized_quantity_search_level(NormalizedQuantitySearchLevel no this.normalized_quantity_search_level = normalized_quantity_search_level; } - public Integer getSearch_coord_core_pool_size() { return search_coord_core_pool_size; } - - public void setSearch_coord_core_pool_size(Integer search_coord_core_pool_size) { - this.search_coord_core_pool_size = search_coord_core_pool_size; - } - - public Integer getSearch_coord_max_pool_size() { return search_coord_max_pool_size; } - - public void setSearch_coord_max_pool_size(Integer search_coord_max_pool_size) { - this.search_coord_max_pool_size = search_coord_max_pool_size; - } - - public Integer getSearch_coord_queue_capacity() { return search_coord_queue_capacity; } - - public void setSearch_coord_queue_capacity(Integer search_coord_queue_capacity) { - this.search_coord_queue_capacity = search_coord_queue_capacity; - } - public boolean getInstall_transitive_ig_dependencies() { return install_transitive_ig_dependencies; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java index 25548bf3f51..e01d6564113 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java @@ -33,18 +33,6 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 { @Autowired AppProperties appProperties; - @PostConstruct - public void initSettings() { - if(appProperties.getSearch_coord_core_pool_size() != null) { - setSearchCoordCorePoolSize(appProperties.getSearch_coord_core_pool_size()); - } - if(appProperties.getSearch_coord_max_pool_size() != null) { - setSearchCoordMaxPoolSize(appProperties.getSearch_coord_max_pool_size()); - } - if(appProperties.getSearch_coord_queue_capacity() != null) { - setSearchCoordQueueCapacity(appProperties.getSearch_coord_queue_capacity()); - } - } @Override public DatabaseBackedPagingProvider databaseBackedPagingProvider() { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index 074d5b74ee9..b258d90bfea 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -35,19 +35,6 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { @Autowired AppProperties appProperties; - @PostConstruct - public void initSettings() { - if(appProperties.getSearch_coord_core_pool_size() != null) { - setSearchCoordCorePoolSize(appProperties.getSearch_coord_core_pool_size()); - } - if(appProperties.getSearch_coord_max_pool_size() != null) { - setSearchCoordMaxPoolSize(appProperties.getSearch_coord_max_pool_size()); - } - if(appProperties.getSearch_coord_queue_capacity() != null) { - setSearchCoordQueueCapacity(appProperties.getSearch_coord_queue_capacity()); - } - } - @Override public DatabaseBackedPagingProvider databaseBackedPagingProvider() { 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 206ad80e5bc..3bb3c0e01d2 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -2,6 +2,7 @@ import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.jpa.config.BaseJavaConfigR4; +import ca.uhn.fhir.jpa.config.r4.JpaR4Config; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; import ca.uhn.fhir.jpa.starter.cql.StarterCqlR4Config; @@ -22,7 +23,7 @@ @Configuration @Conditional(OnR4Condition.class) @Import({StarterCqlR4Config.class, ElasticsearchConfig.class}) -public class FhirServerConfigR4 extends BaseJavaConfigR4 { +public class FhirServerConfigR4 extends JpaR4Config { @Autowired private DataSource myDataSource; @@ -35,18 +36,6 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 { @Autowired AppProperties appProperties; - @PostConstruct - public void initSettings() { - if(appProperties.getSearch_coord_core_pool_size() != null) { - setSearchCoordCorePoolSize(appProperties.getSearch_coord_core_pool_size()); - } - if(appProperties.getSearch_coord_max_pool_size() != null) { - setSearchCoordMaxPoolSize(appProperties.getSearch_coord_max_pool_size()); - } - if(appProperties.getSearch_coord_queue_capacity() != null) { - setSearchCoordQueueCapacity(appProperties.getSearch_coord_queue_capacity()); - } - } @Override public DatabaseBackedPagingProvider databaseBackedPagingProvider() { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index 6d6d64fc023..9c16871578a 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -34,19 +34,6 @@ public class FhirServerConfigR5 extends BaseJavaConfigR5 { @Autowired AppProperties appProperties; - @PostConstruct - public void initSettings() { - if(appProperties.getSearch_coord_core_pool_size() != null) { - setSearchCoordCorePoolSize(appProperties.getSearch_coord_core_pool_size()); - } - if(appProperties.getSearch_coord_max_pool_size() != null) { - setSearchCoordMaxPoolSize(appProperties.getSearch_coord_max_pool_size()); - } - if(appProperties.getSearch_coord_queue_capacity() != null) { - setSearchCoordQueueCapacity(appProperties.getSearch_coord_queue_capacity()); - } - } - @Override public DatabaseBackedPagingProvider databaseBackedPagingProvider() { DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); From 1a528978b87bc8c78420fac4281cc1e01d7a3b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20MacLean?= Date: Tue, 22 Feb 2022 09:36:41 +0100 Subject: [PATCH 043/192] Added instructions about removing Hibernate dialect To fix the problem raised in [this](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/issues/318) issue. --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index a377bf16b7b..2f2b01f620f 100644 --- a/README.md +++ b/README.md @@ -189,6 +189,13 @@ spring: password: admin driverClassName: com.mysql.jdbc.Driver ``` + +Also, make sure you are not setting the Hibernate dialect explicitly, in other words remove any lines similar to: + +``` +hibernate.dialect: {some none MySQL dialect} +``` + On some systems, it might be necessary to override hibernate's default naming strategy. The naming strategy must be set using spring.jpa.hibernate.physical_naming_strategy. ```yaml @@ -279,6 +286,8 @@ spring: driverClassName: com.mysql.jdbc.Driver ``` +Also, make sure you are not setting the Hibernate Dialect explicitly, see more details in the section about MySQL. + ## Running hapi-fhir-jpaserver directly from IntelliJ as Spring Boot Make sure you run with the maven profile called ```boot``` and NOT also ```jetty```. Then you are ready to press debug the project directly without any extra Application Servers. From 28e86bdb8ddb10fb0cb3d906a6b8a25cb8c12d47 Mon Sep 17 00:00:00 2001 From: Jaison Baskaran Date: Wed, 23 Feb 2022 09:38:42 -0700 Subject: [PATCH 044/192] Bump HAPI-FHIR version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7a12c7686ee..0ee8f08b7cb 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.0.0-PRE1-SNAPSHOT + 6.0.0-PRE2-SNAPSHOT hapi-fhir-jpaserver-starter From f2ba86d7db3780b3be0028c04cb0d0be8f7b0105 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 23 Feb 2022 09:29:22 -0800 Subject: [PATCH 045/192] Move to newlines --- .../java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 3bb3c0e01d2..a7f6b0a8b4c 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -2,6 +2,7 @@ import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.jpa.config.BaseJavaConfigR4; +import ca.uhn.fhir.jpa.config.HapiJpaConfig; import ca.uhn.fhir.jpa.config.r4.JpaR4Config; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; @@ -22,7 +23,11 @@ @Configuration @Conditional(OnR4Condition.class) -@Import({StarterCqlR4Config.class, ElasticsearchConfig.class}) +@Import({ + StarterCqlR4Config.class, + ElasticsearchConfig.class + }) +@Import({JpaR4Config.class, HapiJpaConfig.class}) public class FhirServerConfigR4 extends JpaR4Config { @Autowired From 810b090846d6c2365d709ed119745cd3d293778d Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 23 Feb 2022 17:24:21 -0500 Subject: [PATCH 046/192] fix to work with latest hapi-fhir --- .../uhn/fhir/jpa/starter/AppProperties.java | 5 +- .../ca/uhn/fhir/jpa/starter/Application.java | 2 +- .../jpa/starter/BaseJpaRestfulServer.java | 31 ++--- .../fhir/jpa/starter/ElasticsearchConfig.java | 2 +- .../fhir/jpa/starter/EnvironmentHelper.java | 5 +- .../jpa/starter/FhirServerConfigCommon.java | 9 +- .../jpa/starter/FhirServerConfigDstu2.java | 71 ++---------- .../jpa/starter/FhirServerConfigDstu3.java | 73 ++---------- .../fhir/jpa/starter/FhirServerConfigR4.java | 76 ++---------- .../fhir/jpa/starter/FhirServerConfigR5.java | 71 ++---------- .../fhir/jpa/starter/StarterJpaConfig.java | 109 ++++++++++++++++++ .../uhn/fhir/jpa/starter/mdm/MdmConfig.java | 5 +- src/main/resources/application.yaml | 2 +- 13 files changed, 163 insertions(+), 298 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java 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 b3534081bbd..5d5c1731e65 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -11,7 +11,10 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; @ConfigurationProperties(prefix = "hapi.fhir") @Configuration 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 2cf60f56344..0ba207207d5 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -1,7 +1,7 @@ package ca.uhn.fhir.jpa.starter; -import ca.uhn.fhir.jpa.starter.mdm.MdmConfig; import ca.uhn.fhir.jpa.starter.annotations.OnEitherVersion; +import ca.uhn.fhir.jpa.starter.mdm.MdmConfig; 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; 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 a41e399b874..b7e15a30ad3 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -16,13 +16,8 @@ import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc; import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; import ca.uhn.fhir.jpa.partition.PartitionManagementProvider; -import ca.uhn.fhir.jpa.provider.IJpaSystemProvider; -import ca.uhn.fhir.jpa.provider.JpaCapabilityStatementProvider; -import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2; -import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider; -import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; +import ca.uhn.fhir.jpa.provider.*; import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; -import ca.uhn.fhir.jpa.provider.ValueSetOperationProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor; import ca.uhn.fhir.mdm.provider.MdmProviderLoader; @@ -30,17 +25,8 @@ import ca.uhn.fhir.narrative.INarrativeGenerator; import ca.uhn.fhir.narrative2.NullNarrativeGenerator; import ca.uhn.fhir.rest.openapi.OpenApiInterceptor; -import ca.uhn.fhir.rest.server.ApacheProxyAddressStrategy; -import ca.uhn.fhir.rest.server.ETagSupportEnum; -import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy; -import ca.uhn.fhir.rest.server.IncomingRequestAddressStrategy; -import ca.uhn.fhir.rest.server.RestfulServer; -import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor; -import ca.uhn.fhir.rest.server.interceptor.FhirPathFilterInterceptor; -import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor; -import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor; -import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; -import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor; +import ca.uhn.fhir.rest.server.*; +import ca.uhn.fhir.rest.server.interceptor.*; import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor; import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy; @@ -49,19 +35,16 @@ import ca.uhn.fhir.validation.ResultSeverityEnum; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import javax.servlet.ServletException; import org.hl7.fhir.r4.model.Bundle.BundleType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpHeaders; import org.springframework.web.cors.CorsConfiguration; +import javax.servlet.ServletException; +import java.util.*; +import java.util.stream.Collectors; + public class BaseJpaRestfulServer extends RestfulServer { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseJpaRestfulServer.class); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java index fd27e84ee36..21216e6dd59 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java @@ -14,7 +14,7 @@ public class ElasticsearchConfig { @Autowired private ConfigurableEnvironment configurableEnvironment; - @Bean() + @Bean public ElasticsearchSvcImpl elasticsearchSvc() { if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java index 96a958f187f..11b612811c1 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java @@ -22,7 +22,10 @@ import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.PropertySource; -import java.util.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; public class EnvironmentHelper { 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 fb99b7f0dc8..eda9ae4c2dc 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -14,8 +14,6 @@ import ca.uhn.fhir.rest.server.mail.MailConfig; import ca.uhn.fhir.rest.server.mail.MailSvc; import com.google.common.base.Strings; -import java.util.HashSet; -import java.util.Optional; import org.hl7.fhir.dstu2.model.Subscription; import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.context.annotation.Bean; @@ -25,6 +23,9 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; +import java.util.HashSet; +import java.util.Optional; + /** * This is the primary configuration file for the example server */ @@ -74,7 +75,7 @@ public FhirServerConfigCommon(AppProperties appProperties) { /** * Configure FHIR properties around the the JPA server via this bean */ - @Bean() + @Bean public DaoConfig daoConfig(AppProperties appProperties) { DaoConfig retVal = new DaoConfig(); @@ -209,7 +210,7 @@ public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) { return binaryStorageSvc; } - @Bean() + @Bean public IEmailSender emailSender(AppProperties appProperties, Optional subscriptionDeliveryHandlerFactory) { if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) { MailConfig mailConfig = new MailConfig(); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java index e01d6564113..b8011389d20 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java @@ -1,73 +1,16 @@ package ca.uhn.fhir.jpa.starter; -import ca.uhn.fhir.context.ConfigurationException; -import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2; -import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; +import ca.uhn.fhir.jpa.config.JpaDstu2Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU2Condition; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; - -import javax.annotation.PostConstruct; -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; +import org.springframework.context.annotation.Import; @Configuration @Conditional(OnDSTU2Condition.class) -public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 { - - @Autowired - private DataSource myDataSource; - - /** - * We override the paging provider definition so that we can customize - * the default/max page sizes for search results. You can set these however - * you want, although very large page sizes will require a lot of RAM. - */ - @Autowired - AppProperties appProperties; - - - @Override - public DatabaseBackedPagingProvider databaseBackedPagingProvider() { - DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); - pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); - pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); - return pagingProvider; - } - - @Autowired - private ConfigurableEnvironment configurableEnvironment; - - @Override - @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory( - ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); - retVal.setPersistenceUnitName("HAPI_PU"); - - try { - retVal.setDataSource(myDataSource); - } catch (Exception e) { - throw new ConfigurationException("Could not set the data source due to a configuration issue", e); - } - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, myConfigurableListableBeanFactory)); - return retVal; - } - - @Bean - @Primary - public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { - JpaTransactionManager retVal = new JpaTransactionManager(); - retVal.setEntityManagerFactory(entityManagerFactory); - return retVal; - } - - +@Import({ + StarterJpaConfig.class, + JpaDstu2Config.class +}) +public class FhirServerConfigDstu2 { } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java index b258d90bfea..35d1dabb49c 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -1,76 +1,19 @@ package ca.uhn.fhir.jpa.starter; -import ca.uhn.fhir.context.ConfigurationException; -import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3; -import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; +import ca.uhn.fhir.jpa.config.dstu3.JpaDstu3Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU3Condition; import ca.uhn.fhir.jpa.starter.cql.StarterCqlDstu3Config; -import javax.annotation.PostConstruct; -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.annotation.Bean; +import ca.uhn.fhir.jpa.starter.mdm.MdmConfig; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.Primary; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @Configuration @Conditional(OnDSTU3Condition.class) -@Import({StarterCqlDstu3Config.class, ElasticsearchConfig.class}) -public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { - - @Autowired - private DataSource myDataSource; - - /** - * We override the paging provider definition so that we can customize - * the default/max page sizes for search results. You can set these however - * you want, although very large page sizes will require a lot of RAM. - */ - @Autowired - AppProperties appProperties; - - - @Override - public DatabaseBackedPagingProvider databaseBackedPagingProvider() { - DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); - pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); - pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); - return pagingProvider; - } - - @Autowired - private ConfigurableEnvironment configurableEnvironment; - - @Override - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory( - ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); - retVal.setPersistenceUnitName("HAPI_PU"); - - try { - retVal.setDataSource(myDataSource); - } catch (Exception e) { - throw new ConfigurationException("Could not set the data source due to a configuration issue", e); - } - - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, - myConfigurableListableBeanFactory)); - - return retVal; - } - - @Bean - @Primary - public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { - JpaTransactionManager retVal = new JpaTransactionManager(); - retVal.setEntityManagerFactory(entityManagerFactory); - return retVal; - } +@Import({ + StarterJpaConfig.class, + JpaDstu3Config.class, + StarterCqlDstu3Config.class, + ElasticsearchConfig.class}) +public class FhirServerConfigDstu3 { } 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 a7f6b0a8b4c..c31cf529edd 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -1,82 +1,20 @@ package ca.uhn.fhir.jpa.starter; -import ca.uhn.fhir.context.ConfigurationException; -import ca.uhn.fhir.jpa.config.BaseJavaConfigR4; -import ca.uhn.fhir.jpa.config.HapiJpaConfig; import ca.uhn.fhir.jpa.config.r4.JpaR4Config; -import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; import ca.uhn.fhir.jpa.starter.cql.StarterCqlR4Config; -import javax.annotation.PostConstruct; -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.annotation.Bean; +import ca.uhn.fhir.jpa.starter.mdm.MdmConfig; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.Primary; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @Configuration @Conditional(OnR4Condition.class) @Import({ - StarterCqlR4Config.class, - ElasticsearchConfig.class - }) -@Import({JpaR4Config.class, HapiJpaConfig.class}) -public class FhirServerConfigR4 extends JpaR4Config { - - @Autowired - private DataSource myDataSource; - - /** - * We override the paging provider definition so that we can customize - * the default/max page sizes for search results. You can set these however - * you want, although very large page sizes will require a lot of RAM. - */ - @Autowired - AppProperties appProperties; - - - @Override - public DatabaseBackedPagingProvider databaseBackedPagingProvider() { - DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); - pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); - pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); - return pagingProvider; - } - - @Autowired - private ConfigurableEnvironment configurableEnvironment; - - @Override - @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory( - ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); - retVal.setPersistenceUnitName("HAPI_PU"); - - try { - retVal.setDataSource(myDataSource); - } catch (Exception e) { - throw new ConfigurationException("Could not set the data source due to a configuration issue", e); - } - - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, - myConfigurableListableBeanFactory)); - return retVal; - } - - @Bean - @Primary - public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { - JpaTransactionManager retVal = new JpaTransactionManager(); - retVal.setEntityManagerFactory(entityManagerFactory); - return retVal; - } - + StarterJpaConfig.class, + JpaR4Config.class, + StarterCqlR4Config.class, + ElasticsearchConfig.class +}) +public class FhirServerConfigR4 { } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java index 9c16871578a..8ee03df272d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -1,74 +1,17 @@ package ca.uhn.fhir.jpa.starter; -import ca.uhn.fhir.context.ConfigurationException; -import ca.uhn.fhir.jpa.config.BaseJavaConfigR5; -import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; +import ca.uhn.fhir.jpa.config.r5.JpaR5Config; import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition; -import javax.annotation.PostConstruct; -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.Primary; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @Configuration @Conditional(OnR5Condition.class) -@Import({ElasticsearchConfig.class}) -public class FhirServerConfigR5 extends BaseJavaConfigR5 { - - @Autowired - private DataSource myDataSource; - - /** - * We override the paging provider definition so that we can customize - * the default/max page sizes for search results. You can set these however - * you want, although very large page sizes will require a lot of RAM. - */ - @Autowired - AppProperties appProperties; - - @Override - public DatabaseBackedPagingProvider databaseBackedPagingProvider() { - DatabaseBackedPagingProvider pagingProvider = super.databaseBackedPagingProvider(); - pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); - pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); - return pagingProvider; - } - - @Autowired - private ConfigurableEnvironment configurableEnvironment; - - @Override - @Bean() - public LocalContainerEntityManagerFactoryBean entityManagerFactory( - ConfigurableListableBeanFactory myConfigurableListableBeanFactory) { - LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(myConfigurableListableBeanFactory); - retVal.setPersistenceUnitName("HAPI_PU"); - - try { - retVal.setDataSource(myDataSource); - } catch (Exception e) { - throw new ConfigurationException("Could not set the data source due to a configuration issue", e); - } - - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, - myConfigurableListableBeanFactory)); - return retVal; - } - - @Bean - @Primary - public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { - JpaTransactionManager retVal = new JpaTransactionManager(); - retVal.setEntityManagerFactory(entityManagerFactory); - return retVal; - } - +@Import({ + StarterJpaConfig.class, + JpaR5Config.class, + ElasticsearchConfig.class +}) +public class FhirServerConfigR5 { } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java new file mode 100644 index 00000000000..07fd0282cb5 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java @@ -0,0 +1,109 @@ +package ca.uhn.fhir.jpa.starter; + +import ca.uhn.fhir.context.ConfigurationException; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.api.IDaoRegistry; +import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; +import ca.uhn.fhir.jpa.batch.config.NonPersistedBatchConfigurer; +import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil; +import ca.uhn.fhir.jpa.config.util.ResourceCountCacheUtil; +import ca.uhn.fhir.jpa.config.util.ValidationSupportConfigUtil; +import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl; +import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc; +import ca.uhn.fhir.jpa.provider.DaoRegistryResourceSupportedSvc; +import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; +import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc; +import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl; +import ca.uhn.fhir.jpa.util.ResourceCountCache; +import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain; +import ca.uhn.fhir.rest.api.IResourceSupportedSvc; +import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport; +import org.springframework.batch.core.configuration.annotation.BatchConfigurer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +@Configuration +public class StarterJpaConfig { + @Bean + public IFulltextSearchSvc fullTextSearchSvc() { + return new FulltextSearchSvcImpl(); + } + + @Bean + public IStaleSearchDeletingSvc staleSearchDeletingSvc() { + return new StaleSearchDeletingSvcImpl(); + } + + @Primary + @Bean + public CachingValidationSupport validationSupportChain(JpaValidationSupportChain theJpaValidationSupportChain) { + return ValidationSupportConfigUtil.newCachingValidationSupport(theJpaValidationSupportChain); + } + + @Bean + public BatchConfigurer batchConfigurer() { + return new NonPersistedBatchConfigurer(); + } + + @Autowired + AppProperties appProperties; + @Autowired + private DataSource myDataSource; + @Autowired + private ConfigurableEnvironment configurableEnvironment; + + /** + * Customize the default/max page sizes for search results. You can set these however + * you want, although very large page sizes will require a lot of RAM. + */ + @Bean + public DatabaseBackedPagingProvider databaseBackedPagingProvider() { + DatabaseBackedPagingProvider pagingProvider = new DatabaseBackedPagingProvider(); + pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); + pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); + return pagingProvider; + } + + @Bean + public IResourceSupportedSvc resourceSupportedSvc(IDaoRegistry theDaoRegistry) { + return new DaoRegistryResourceSupportedSvc(theDaoRegistry); + } + + @Bean(name = "myResourceCountsCache") + public ResourceCountCache resourceCountsCache(IFhirSystemDao theSystemDao) { + return ResourceCountCacheUtil.newResourceCountCache(theSystemDao); + } + + @Primary + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + ConfigurableListableBeanFactory myConfigurableListableBeanFactory, FhirContext theFhirContext) { + LocalContainerEntityManagerFactoryBean retVal = HapiEntityManagerFactoryUtil.newEntityManagerFactory(myConfigurableListableBeanFactory, theFhirContext); + retVal.setPersistenceUnitName("HAPI_PU"); + + try { + retVal.setDataSource(myDataSource); + } catch (Exception e) { + throw new ConfigurationException("Could not set the data source due to a configuration issue", e); + } + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, myConfigurableListableBeanFactory)); + return retVal; + } + + @Bean + @Primary + public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { + JpaTransactionManager retVal = new JpaTransactionManager(); + retVal.setEntityManagerFactory(entityManagerFactory); + return retVal; + } +} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java index 39718f6c9ad..50dfe9e0489 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java @@ -1,15 +1,12 @@ package ca.uhn.fhir.jpa.starter.mdm; -import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.mdm.config.MdmConsumerConfig; import ca.uhn.fhir.jpa.mdm.config.MdmSubmitterConfig; import ca.uhn.fhir.jpa.starter.AppProperties; import ca.uhn.fhir.mdm.api.IMdmSettings; import ca.uhn.fhir.mdm.rules.config.MdmRuleValidator; import ca.uhn.fhir.mdm.rules.config.MdmSettings; -import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; import com.google.common.base.Charsets; -import java.io.IOException; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -19,6 +16,8 @@ import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; +import java.io.IOException; + @Configuration @Conditional(MdmConfigCondition.class) @Import({MdmConsumerConfig.class, MdmSubmitterConfig.class}) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7ea0ccc7c7f..7083b7d3ecb 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -99,7 +99,7 @@ hapi: # mdm_enabled: true # local_base_urls: # - https://hapi.fhir.org/baseR4 - mdm_enabled: true + mdm_enabled: false # partitioning: # allow_references_across_partitions: false # partitioning_include_in_search_hashes: false From 24a20a7e973aef9674204bbce202cac860d9a472 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Wed, 2 Mar 2022 16:39:13 +0100 Subject: [PATCH 047/192] Feature/update docker support (#319) * Updated docker image according to discussion on https://github.com/hapifhir/hapi-fhir-jpaserver-starter/pull/305 * Added doc * Added corrections according to comments * Update Dockerfile * Update build-images.yaml Updated to default to distroless --- .github/workflows/build-images.yaml | 24 ++++++++--------- Dockerfile | 40 ++++++++++++++++++----------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/.github/workflows/build-images.yaml b/.github/workflows/build-images.yaml index dae02057a17..2a413b5e7dc 100644 --- a/.github/workflows/build-images.yaml +++ b/.github/workflows/build-images.yaml @@ -19,25 +19,24 @@ jobs: name: Build runs-on: ubuntu-20.04 steps: - - name: Docker meta + - name: Container meta for default (distroless) image id: docker_meta uses: docker/metadata-action@v3 with: images: ${{ env.IMAGES }} tags: | type=match,pattern=image-(.*),group=1,enable=${{github.event_name != 'pull_request'}} - type=sha + - - name: Docker distroless meta - id: docker_distroless_meta + - name: Container meta for tomcat image + id: docker_tomcat_meta uses: docker/metadata-action@v3 with: images: ${{ env.IMAGES }} tags: | type=match,pattern=image-(.*),group=1,enable=${{github.event_name != 'pull_request'}} - type=sha flavor: | - suffix=-distroless,onlatest=true + suffix=-tomcat,onlatest=true - name: Set up QEMU uses: docker/setup-qemu-action@v1 @@ -60,7 +59,7 @@ jobs: restore-keys: | ${{ runner.os }}-buildx- - - name: Build and push + - name: Build and push default (distroless) image id: docker_build uses: docker/build-push-action@v2 with: @@ -70,15 +69,16 @@ jobs: tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} platforms: ${{ env.PLATFORMS }} + target: default - - name: Build and push distroless - id: docker_build_distroless + - name: Build and push tomcat image + id: docker_build_tomcat uses: docker/build-push-action@v2 with: cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.docker_distroless_meta.outputs.tags }} - labels: ${{ steps.docker_distroless_meta.outputs.labels }} + tags: ${{ steps.docker_tomcat_meta.outputs.tags }} + labels: ${{ steps.docker_tomcat_meta.outputs.labels }} platforms: ${{ env.PLATFORMS }} - target: release-distroless + target: tomcat diff --git a/Dockerfile b/Dockerfile index 5d3772e75e7..3a8ea7a44f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.8.2-jdk-11-slim as build-hapi +FROM maven:3.8-openjdk-17-slim as build-hapi WORKDIR /tmp/hapi-fhir-jpaserver-starter COPY pom.xml . @@ -6,14 +6,34 @@ COPY server.xml . RUN mvn -ntp dependency:go-offline COPY src/ /tmp/hapi-fhir-jpaserver-starter/src/ -RUN mvn clean install -DskipTests +RUN mvn clean install -DskipTests -Djdk.lang.Process.launchMechanism=vfork FROM build-hapi AS build-distroless RUN mvn package spring-boot:repackage -Pboot -RUN mkdir /app && \ - cp /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /app/main.war +RUN mkdir /app && cp /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /app/main.war -FROM gcr.io/distroless/java-debian11:11 AS release-distroless + +########### bitnami tomcat version is suitable for debugging and comes with a shell +########### it can be built using eg. `docker build --target tomcat .` +FROM bitnami/tomcat:9.0 as tomcat + +RUN rm -rf /opt/bitnami/tomcat/webapps/ROOT && \ + rm -rf /opt/bitnami/tomcat/webapps_default/ROOT && \ + mkdir -p /opt/bitnami/hapi/data/hapi/lucenefiles && \ + chmod 775 /opt/bitnami/hapi/data/hapi/lucenefiles + +USER root +RUN mkdir -p /target && chown -R 1001:1001 target +USER 1001 + +COPY --chown=1001:1001 catalina.properties /opt/bitnami/tomcat/conf/catalina.properties +COPY --chown=1001:1001 server.xml /opt/bitnami/tomcat/conf/server.xml +COPY --from=build-hapi --chown=1001:1001 /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /opt/bitnami/tomcat/webapps_default/ROOT.war + +ENV ALLOW_EMPTY_PASSWORD=yes + +########### distroless brings focus on security and runs on plain spring boot - this is the default image +FROM gcr.io/distroless/java17:nonroot as default COPY --chown=nonroot:nonroot --from=build-distroless /app /app # 65532 is the nonroot user's uid # used here instead of the name to allow Kubernetes to easily detect that the container @@ -21,13 +41,3 @@ COPY --chown=nonroot:nonroot --from=build-distroless /app /app USER 65532:65532 WORKDIR /app CMD ["/app/main.war"] - -FROM tomcat:9.0.53-jdk11-openjdk-slim-bullseye - -RUN mkdir -p /data/hapi/lucenefiles && chmod 775 /data/hapi/lucenefiles -COPY --from=build-hapi /tmp/hapi-fhir-jpaserver-starter/target/*.war /usr/local/tomcat/webapps/ - -COPY catalina.properties /usr/local/tomcat/conf/catalina.properties -COPY server.xml /usr/local/tomcat/conf/server.xml - -CMD ["catalina.sh", "run"] From 7db15103fe4790817588e74a099126e8008b620f Mon Sep 17 00:00:00 2001 From: "Joel Schneider (NMDP)" Date: Fri, 4 Mar 2022 04:38:16 -0600 Subject: [PATCH 048/192] add dao_scheduling_enabled configuration property (#324) --- src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java | 9 +++++++++ .../ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java | 2 ++ 2 files changed, 11 insertions(+) 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 1118df7fd55..2ef74cfe3df 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -28,6 +28,7 @@ public class AppProperties { private Boolean allow_multiple_delete = false; private Boolean allow_override_default_search_params = true; private Boolean auto_create_placeholder_reference_targets = false; + private Boolean dao_scheduling_enabled = true; private Boolean delete_expunge_enabled = false; private Boolean enable_index_missing_fields = false; private Boolean enable_index_contained_resource = false; @@ -286,6 +287,14 @@ public void setDefault_page_size(Integer default_page_size) { this.default_page_size = default_page_size; } + public Boolean getDao_scheduling_enabled() { + return dao_scheduling_enabled; + } + + public void setDao_scheduling_enabled(Boolean dao_scheduling_enabled) { + this.dao_scheduling_enabled = dao_scheduling_enabled; + } + public Boolean getDelete_expunge_enabled() { return delete_expunge_enabled; } 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 fb99b7f0dc8..d9617c75b21 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -39,6 +39,7 @@ public FhirServerConfigCommon(AppProperties appProperties) { ourLog.info("Server configured to " + (appProperties.getAllow_contains_searches() ? "allow" : "deny") + " contains searches"); ourLog.info("Server configured to " + (appProperties.getAllow_multiple_delete() ? "allow" : "deny") + " multiple deletes"); ourLog.info("Server configured to " + (appProperties.getAllow_external_references() ? "allow" : "deny") + " external references"); + ourLog.info("Server configured to " + (appProperties.getDao_scheduling_enabled() ? "enable" : "disable") + " DAO scheduling"); ourLog.info("Server configured to " + (appProperties.getDelete_expunge_enabled() ? "enable" : "disable") + " delete expunges"); ourLog.info("Server configured to " + (appProperties.getExpunge_enabled() ? "enable" : "disable") + " expunges"); ourLog.info("Server configured to " + (appProperties.getAllow_override_default_search_params() ? "allow" : "deny") + " overriding default search params"); @@ -85,6 +86,7 @@ public DaoConfig daoConfig(AppProperties appProperties) { retVal.setAllowContainsSearches(appProperties.getAllow_contains_searches()); retVal.setAllowMultipleDelete(appProperties.getAllow_multiple_delete()); retVal.setAllowExternalReferences(appProperties.getAllow_external_references()); + retVal.setSchedulingDisabled(!appProperties.getDao_scheduling_enabled()); retVal.setDeleteExpungeEnabled(appProperties.getDelete_expunge_enabled()); retVal.setExpungeEnabled(appProperties.getExpunge_enabled()); if(appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) From 40d7b9ce27355fedb3fb70fcd79a09d7bd8290bb Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Mon, 7 Mar 2022 13:20:06 +0100 Subject: [PATCH 049/192] added reindexProvider to Config (#326) --- .../java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 a41e399b874..3d94924ac21 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -42,6 +42,7 @@ import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor; import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor; +import ca.uhn.fhir.rest.server.provider.ReindexProvider; import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; @@ -95,6 +96,8 @@ public class BaseJpaRestfulServer extends RestfulServer { @Autowired ValueSetOperationProvider valueSetOperationProvider; @Autowired + ReindexProvider reindexProvider; + @Autowired BinaryStorageInterceptor binaryStorageInterceptor; @Autowired IPackageInstallerSvc packageInstallerSvc; @@ -373,6 +376,9 @@ protected void initialize() throws ServletException { // valueSet Operations i.e $expand registerProvider(valueSetOperationProvider); + //reindex Provider $reindex + registerProvider(reindexProvider); + // Partitioning if (appProperties.getPartitioning() != null) { registerInterceptor(new RequestTenantPartitionInterceptor()); From 0483db9195057326a574b29af654f8da0b1cfee1 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Tue, 8 Mar 2022 10:42:52 +0100 Subject: [PATCH 050/192] Update application.yaml --- src/main/resources/application.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7ea0ccc7c7f..3b7e97bf7f4 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,6 +1,7 @@ spring: main: allow-circular-references: true + allow-bean-definition-overriding: true flyway: enabled: false check-location: false From 929a3535fa93d33b24cef06ed4158ae2fcb9f6a2 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Tue, 8 Mar 2022 10:44:13 +0100 Subject: [PATCH 051/192] Update application.yaml Roll back - mistake from my side --- src/main/resources/application.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 3b7e97bf7f4..3131c7ed55a 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,7 +1,7 @@ spring: main: allow-circular-references: true - allow-bean-definition-overriding: true + #allow-bean-definition-overriding: true flyway: enabled: false check-location: false From 146b9f68ac92ae62da878de36450bd7619d016ff Mon Sep 17 00:00:00 2001 From: Jaison Baskaran Date: Wed, 9 Mar 2022 09:03:10 -0700 Subject: [PATCH 052/192] Bump hapi-fhir version to 'PRE5' (#329) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a08affeef25..83635dcaa45 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.0.0-PRE3-SNAPSHOT + 6.0.0-PRE5-SNAPSHOT hapi-fhir-jpaserver-starter From aeef4b176c0a48065c6190f6b56d27a45a62db33 Mon Sep 17 00:00:00 2001 From: jkv Date: Sun, 20 Mar 2022 21:22:36 +0100 Subject: [PATCH 053/192] Add actuator --- pom.xml | 19 +++++++++++++++++++ src/main/resources/application.yaml | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/pom.xml b/pom.xml index 69aef165fbf..3c511efb15a 100644 --- a/pom.xml +++ b/pom.xml @@ -85,6 +85,12 @@ ca.uhn.hapi.fhir hapi-fhir-jpaserver-subscription ${project.version} + + + com.zaxxer + HikariCP-java7 + + @@ -301,6 +307,19 @@ ${spring_boot_version} + + org.springframework.boot + spring-boot-starter-actuator + ${spring_boot_version} + + + + com.zaxxer + HikariCP + 5.0.1 + + + org.junit.jupiter junit-jupiter-api diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 3131c7ed55a..11da8d1cafd 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,3 +1,10 @@ +#Adds the option to go to eg. http://localhost:8080/actuator/env for seeing the running configuration +management: + endpoints: + web: + exposure: + include: "*" + exclude: "beans" spring: main: allow-circular-references: true From 403b87573d6381e85186f8d3c1f4226052fdae98 Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Wed, 23 Mar 2022 10:34:42 -0400 Subject: [PATCH 054/192] Bump to PRE8 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 83635dcaa45..056a508e32d 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.0.0-PRE5-SNAPSHOT + 6.0.0-PRE8-SNAPSHOT hapi-fhir-jpaserver-starter From da319e8761ed2ef017ed5e9dcbde489a99489123 Mon Sep 17 00:00:00 2001 From: craig mcclendon Date: Wed, 23 Mar 2022 14:12:48 -0500 Subject: [PATCH 055/192] disable springboot actuator endpoints other than 'health' for security reasons (#338) Co-authored-by: Craig McClendon --- src/main/resources/application.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 11da8d1cafd..b03dd76f559 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,10 +1,10 @@ -#Adds the option to go to eg. http://localhost:8080/actuator/env for seeing the running configuration +#Adds the option to go to eg. http://localhost:8080/actuator/health for seeing the running configuration +#see https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints management: endpoints: web: exposure: - include: "*" - exclude: "beans" + include: "health" spring: main: allow-circular-references: true From 49401c0d3dbd52c9a5b8ac3c9c4407fcb973a367 Mon Sep 17 00:00:00 2001 From: Jaison Baskaran Date: Tue, 29 Mar 2022 15:16:08 -0600 Subject: [PATCH 056/192] Bump to PRE9 --- pom.xml | 2 +- src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 2 +- .../java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 056a508e32d..0c0f6280ed3 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.0.0-PRE8-SNAPSHOT + 6.0.0-PRE9-SNAPSHOT hapi-fhir-jpaserver-starter 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 e147da6b6a8..48e159a3713 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -9,7 +9,7 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; -import ca.uhn.fhir.jpa.binstore.BinaryStorageInterceptor; +import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor; import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider; import ca.uhn.fhir.jpa.graphql.GraphQLProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; 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 eda9ae4c2dc..cc93f60d821 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -1,8 +1,8 @@ package ca.uhn.fhir.jpa.starter; import ca.uhn.fhir.jpa.api.config.DaoConfig; +import ca.uhn.fhir.jpa.binary.api.IBinaryStorageSvc; import ca.uhn.fhir.jpa.binstore.DatabaseBlobBinaryStorageSvcImpl; -import ca.uhn.fhir.jpa.binstore.IBinaryStorageSvc; import ca.uhn.fhir.jpa.config.HibernatePropertiesProvider; import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings.CrossPartitionReferenceMode; From 6b3f57cf12a1f264a9ef9ce9bcd885de0a67d269 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Thu, 7 Apr 2022 22:32:38 +0200 Subject: [PATCH 057/192] Update application.yaml (#345) --- src/main/resources/application.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 3131c7ed55a..df616721414 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -100,7 +100,6 @@ hapi: # mdm_enabled: true # local_base_urls: # - https://hapi.fhir.org/baseR4 - mdm_enabled: true # partitioning: # allow_references_across_partitions: false # partitioning_include_in_search_hashes: false From cdda71b25320afa83538c2c6d88e097bedbfaa70 Mon Sep 17 00:00:00 2001 From: craig mcclendon Date: Sat, 9 Apr 2022 12:19:44 -0500 Subject: [PATCH 058/192] add support for ms sql server (#347) --- README.md | 20 ++++++++++++++++++++ pom.xml | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/README.md b/README.md index a377bf16b7b..bb67d6ac821 100644 --- a/README.md +++ b/README.md @@ -215,6 +215,26 @@ spring: Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. +### Microsoft SQL Server configuration + +To configure the starter app to use MS SQL Server, instead of the default H2, update the application.yaml file to have the following: + +```yaml +spring: + datasource: + url: 'jdbc:sqlserver://:;databaseName=' + username: admin + password: admin + driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver +``` + + +Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. + + +NOTE: MS SQL Server by default uses a case-insensitive codepage. This will cause errors with some operations - such as when expanding case-sensitive valuesets (UCUM) as there are unique indexes defined on the terminology tables for codes. +It is recommended to deploy a case-sensitive database prior to running HAPI FHIR when using MS SQL Server to avoid these and potentially other issues. + ## Customizing The Web Testpage UI The UI that comes with this server is an exact clone of the server available at [http://hapi.fhir.org](http://hapi.fhir.org). You may skin this UI if you'd like. For example, you might change the introductory text or replace the logo with your own. diff --git a/pom.xml b/pom.xml index 69aef165fbf..591664c24c3 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,10 @@ org.postgresql postgresql + + com.microsoft.sqlserver + mssql-jdbc + From bb21ccfe90e5e40b86587bcf9b04cda08114b878 Mon Sep 17 00:00:00 2001 From: dotasek Date: Mon, 11 Apr 2022 11:47:09 -0400 Subject: [PATCH 059/192] Fix comments in Demo that lead to 404 (#348) Co-authored-by: dotasek --- src/test/java/ca/uhn/fhir/jpa/starter/Demo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/Demo.java b/src/test/java/ca/uhn/fhir/jpa/starter/Demo.java index 5dadf14f8da..d46094360ee 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/Demo.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/Demo.java @@ -15,6 +15,6 @@ public static void main(String[] args) { System.setProperty("spring.batch.job.enabled", "false"); SpringApplication.run(Demo.class, args); - //Server is now accessible at eg. http://localhost:8080/metadata + //Server is now accessible at eg. http://localhost:8080/fhir/metadata } } From 4bed69fedfd1f3021c1ecdae388dfee9067073e2 Mon Sep 17 00:00:00 2001 From: chgl Date: Mon, 11 Apr 2022 17:56:32 +0200 Subject: [PATCH 060/192] updated helm chart to use v5.7.0 and latest PostgreSQL sub-chart (#346) --- charts/hapi-fhir-jpaserver/Chart.lock | 6 +-- charts/hapi-fhir-jpaserver/Chart.yaml | 17 ++++---- charts/hapi-fhir-jpaserver/README.md | 13 +++---- .../ci/enabled-ingress-values.yaml | 6 +++ .../templates/_helpers.tpl | 24 +++--------- .../templates/deployment.yaml | 8 ++-- .../templates/externaldb-secret.yaml | 4 +- ...st-connection.yaml => test-endpoints.yaml} | 29 +++++++++++++- charts/hapi-fhir-jpaserver/values.yaml | 39 +++++++++---------- 9 files changed, 82 insertions(+), 64 deletions(-) create mode 100644 charts/hapi-fhir-jpaserver/ci/enabled-ingress-values.yaml rename charts/hapi-fhir-jpaserver/templates/tests/{test-connection.yaml => test-endpoints.yaml} (53%) diff --git a/charts/hapi-fhir-jpaserver/Chart.lock b/charts/hapi-fhir-jpaserver/Chart.lock index 0db0f3a7b87..bfb87acb260 100644 --- a/charts/hapi-fhir-jpaserver/Chart.lock +++ b/charts/hapi-fhir-jpaserver/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 10.12.2 -digest: sha256:38ee315eae1af3e3f6eb20e1dd8ffd60d4ab7ee0c51bf26941b56c8bcb376c11 -generated: "2021-10-07T00:19:18.9743522+02:00" + version: 11.1.19 +digest: sha256:5bb38230bfa62c63547851e6f46f66a61441a4a4f18e3689827546277e34d192 +generated: "2022-04-08T21:55:34.6868891+02:00" diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index dd2c479314a..3cb702b205b 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -7,20 +7,23 @@ sources: - https://github.com/hapifhir/hapi-fhir-jpaserver-starter dependencies: - name: postgresql - version: 10.12.2 + version: 11.1.19 repository: https://charts.bitnami.com/bitnami condition: postgresql.enabled annotations: artifacthub.io/license: Apache-2.0 - artifacthub.io/prerelease: "true" artifacthub.io/changes: | # When using the list of objects option the valid supported kinds are # added, changed, deprecated, removed, fixed, and security. - kind: changed description: | - updated HAPI FHIR starter image to 5.6.0 - - kind: added + updated HAPI FHIR starter image to 5.7.0 + - kind: changed + description: | + BREAKING CHANGE: updated included PostgreSQL-subchart to v11 + - kind: changed description: | - added support for configuring PodDisruptionBudget for the server pods -appVersion: v5.6.0 -version: 0.7.0 + BREAKING CHANGE: removed ability to override the image flavor. + The one based on distroless is now the new default. +appVersion: v5.7.0 +version: 0.8.0 diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index 9208bd6f967..288e2ce517c 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -1,6 +1,6 @@ # HAPI FHIR JPA Server Starter Helm Chart -![Version: 0.7.0](https://img.shields.io/badge/Version-0.7.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v5.6.0](https://img.shields.io/badge/AppVersion-v5.6.0-informational?style=flat-square) +![Version: 0.8.0](https://img.shields.io/badge/Version-0.8.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v5.7.0](https://img.shields.io/badge/AppVersion-v5.7.0-informational?style=flat-square) This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment. @@ -29,11 +29,10 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | externalDatabase.user | string | `"fhir"` | username for the external database | | extraEnv | list | `[]` | extra environment variables to set on the server container | | fullnameOverride | string | `""` | override the chart fullname | -| image.flavor | string | `"distroless"` | the flavor or variant of the image to use. appended to the image tag by `-`. | | image.pullPolicy | string | `"IfNotPresent"` | image pullPolicy to use | | image.registry | string | `"docker.io"` | registry where the HAPI FHIR server image is hosted | | image.repository | string | `"hapiproject/hapi"` | the path inside the repository | -| image.tag | string | `""` | defaults to `Chart.appVersion` | +| image.tag | string | `""` | defaults to `Chart.appVersion`. As of v5.7.0, this is the `distroless` flavor | | imagePullSecrets | list | `[]` | image pull secrets to use when pulling the image | | ingress.annotations | object | `{}` | provide any additional annotations which may be required. Evaluated as a template. | | ingress.enabled | bool | `false` | whether to create an Ingress to expose the FHIR server HTTP endpoint | @@ -51,11 +50,11 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | podDisruptionBudget.maxUnavailable | string | `""` | maximum unavailable instances | | podDisruptionBudget.minAvailable | int | `1` | minimum available instances | | podSecurityContext | object | `{}` | pod security context | -| postgresql.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | | -| postgresql.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | | +| postgresql.auth.database | string | `"fhir"` | name for a custom database to create | +| postgresql.auth.existingSecret | string | `""` | Name of existing secret to use for PostgreSQL credentials `auth.postgresPassword`, `auth.password`, and `auth.replicationPassword` will be ignored and picked up from this secret The secret must contain the keys `postgres-password` (which is the password for "postgres" admin user), `password` (which is the password for the custom user to create when `auth.username` is set), and `replication-password` (which is the password for replication user). The secret might also contains the key `ldap-password` if LDAP is enabled. `ldap.bind_password` will be ignored and picked from this secret in this case. The value is evaluated as a template. | | postgresql.enabled | bool | `true` | enable an included PostgreSQL DB. see for details if set to `false`, the values under `externalDatabase` are used | -| postgresql.existingSecret | string | `""` | Name of existing secret to use for PostgreSQL passwords. The secret has to contain the keys `postgresql-password` which is the password for `postgresqlUsername` when it is different of `postgres`, `postgresql-postgres-password` which will override `postgresqlPassword`, `postgresql-replication-password` which will override `replication.password` and `postgresql-ldap-password` which will be sed to authenticate on LDAP. The value is evaluated as a template. | -| postgresql.postgresqlDatabase | string | `"fhir"` | name of the database to create see: | +| postgresql.primary.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | | +| postgresql.primary.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | | | readinessProbe.failureThreshold | int | `5` | | | readinessProbe.initialDelaySeconds | int | `30` | | | readinessProbe.periodSeconds | int | `20` | | diff --git a/charts/hapi-fhir-jpaserver/ci/enabled-ingress-values.yaml b/charts/hapi-fhir-jpaserver/ci/enabled-ingress-values.yaml new file mode 100644 index 00000000000..f28063f19a0 --- /dev/null +++ b/charts/hapi-fhir-jpaserver/ci/enabled-ingress-values.yaml @@ -0,0 +1,6 @@ +ingress: + enabled: true + +postgresql: + auth: + postgresPassword: secretpassword diff --git a/charts/hapi-fhir-jpaserver/templates/_helpers.tpl b/charts/hapi-fhir-jpaserver/templates/_helpers.tpl index 178d84028bd..eee1ed59867 100644 --- a/charts/hapi-fhir-jpaserver/templates/_helpers.tpl +++ b/charts/hapi-fhir-jpaserver/templates/_helpers.tpl @@ -30,18 +30,6 @@ Create chart name and version as used by the chart label. {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} -{{/* -Create image tag -*/}} -{{- define "hapi-fhir-jpaserver.imageTag" -}} -{{- $version := default .Chart.AppVersion .Values.image.tag -}} -{{- if .Values.image.flavor }} -{{- printf "%s-%s" $version .Values.image.flavor }} -{{- else }} -{{- printf "%s" $version }} -{{- end }} -{{- end }} - {{/* Common labels */}} @@ -75,10 +63,10 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this Get the Postgresql credentials secret name. */}} {{- define "hapi-fhir-jpaserver.postgresql.secretName" -}} -{{- if and (.Values.postgresql.enabled) (not .Values.postgresql.existingSecret) -}} +{{- if and (.Values.postgresql.enabled) (not .Values.postgresql.auth.existingSecret) -}} {{- printf "%s" (include "hapi-fhir-jpaserver.postgresql.fullname" .) -}} -{{- else if and (.Values.postgresql.enabled) (.Values.postgresql.existingSecret) -}} - {{- printf "%s" .Values.postgresql.existingSecret -}} +{{- else if and (.Values.postgresql.enabled) (.Values.postgresql.auth.existingSecret) -}} + {{- printf "%s" .Values.postgresql.auth.existingSecret -}} {{- else }} {{- if .Values.externalDatabase.existingSecret -}} {{- printf "%s" .Values.externalDatabase.existingSecret -}} @@ -95,7 +83,7 @@ Get the Postgresql credentials secret key. {{- if (.Values.externalDatabase.existingSecret) -}} {{- printf "%s" .Values.externalDatabase.existingSecretKey -}} {{- else }} - {{- printf "postgresql-password" -}} + {{- printf "postgres-password" -}} {{- end -}} {{- end -}} @@ -110,14 +98,14 @@ Add environment variables to configure database values Add environment variables to configure database values */}} {{- define "hapi-fhir-jpaserver.database.user" -}} -{{- ternary .Values.postgresql.postgresqlUsername .Values.externalDatabase.user .Values.postgresql.enabled -}} +{{- ternary "postgres" .Values.externalDatabase.user .Values.postgresql.enabled -}} {{- end -}} {{/* Add environment variables to configure database values */}} {{- define "hapi-fhir-jpaserver.database.name" -}} -{{- ternary .Values.postgresql.postgresqlDatabase .Values.externalDatabase.database .Values.postgresql.enabled -}} +{{- ternary .Values.postgresql.auth.database .Values.externalDatabase.database .Values.postgresql.enabled -}} {{- end -}} {{/* diff --git a/charts/hapi-fhir-jpaserver/templates/deployment.yaml b/charts/hapi-fhir-jpaserver/templates/deployment.yaml index a58024c82e3..187ee9d2816 100644 --- a/charts/hapi-fhir-jpaserver/templates/deployment.yaml +++ b/charts/hapi-fhir-jpaserver/templates/deployment.yaml @@ -60,7 +60,7 @@ spec: - name: {{ .Chart.Name }} securityContext: {{- toYaml .Values.securityContext | nindent 12 }} - image: {{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ include "hapi-fhir-jpaserver.imageTag" . }} + image: {{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }} imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - name: http @@ -102,12 +102,10 @@ spec: key: {{ include "hapi-fhir-jpaserver.postgresql.secretKey" . }} - name: SPRING_DATASOURCE_DRIVERCLASSNAME value: org.postgresql.Driver - - name: SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT - value: org.hibernate.dialect.PostgreSQL10Dialect + - name: spring.jpa.properties.hibernate.dialect + value: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect - name: HAPI_FHIR_USE_APACHE_ADDRESS_STRATEGY value: "true" - - name: SPRING_JPA_DATABASE_PLATFORM - value: org.hibernate.dialect.PostgreSQLDialect {{- if .Values.extraEnv }} {{ toYaml .Values.extraEnv | nindent 12 }} {{- end }} diff --git a/charts/hapi-fhir-jpaserver/templates/externaldb-secret.yaml b/charts/hapi-fhir-jpaserver/templates/externaldb-secret.yaml index e3a35d80219..a487cb6b030 100644 --- a/charts/hapi-fhir-jpaserver/templates/externaldb-secret.yaml +++ b/charts/hapi-fhir-jpaserver/templates/externaldb-secret.yaml @@ -1,4 +1,4 @@ -{{- if and (not .Values.postgresql.enabled) (not .Values.externalDatabase.existingSecret) (not .Values.postgresql.existingSecret) }} +{{- if and (not .Values.postgresql.enabled) (not .Values.externalDatabase.existingSecret) (not .Values.postgresql.auth.existingSecret) }} apiVersion: v1 kind: Secret metadata: @@ -7,5 +7,5 @@ metadata: {{- include "hapi-fhir-jpaserver.labels" . | nindent 4 }} type: Opaque data: - postgresql-password: {{ .Values.externalDatabase.password | b64enc | quote }} + postgres-password: {{ .Values.externalDatabase.password | b64enc | quote }} {{- end }} diff --git a/charts/hapi-fhir-jpaserver/templates/tests/test-connection.yaml b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml similarity index 53% rename from charts/hapi-fhir-jpaserver/templates/tests/test-connection.yaml rename to charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml index eac503dfbf2..911f59d6ae3 100644 --- a/charts/hapi-fhir-jpaserver/templates/tests/test-connection.yaml +++ b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Pod metadata: - name: "{{ include "hapi-fhir-jpaserver.fullname" . }}-test-connection" + name: "{{ include "hapi-fhir-jpaserver.fullname" . }}-test-endpoints" labels: {{- include "hapi-fhir-jpaserver.labels" . | nindent 4 }} {{ include "hapi-fhir-jpaserver.fullname" . }}-client: "true" @@ -10,7 +10,32 @@ metadata: spec: restartPolicy: Never containers: - - name: wget + - name: test-metadata-endpoint + image: busybox:1 + command: ['wget', '-O', '-'] + args: ['http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/metadata'] + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsUser: 22222 + runAsNonRoot: true + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + livenessProbe: + exec: + command: ["true"] + readinessProbe: + exec: + command: ["true"] + - name: test-patient-endpoint image: busybox:1 command: ['wget', '-O', '-'] args: ['http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/Patient?_count=1'] diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index 5fb71ddb257..e89a5c4dd72 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -6,11 +6,8 @@ image: registry: docker.io # -- the path inside the repository repository: hapiproject/hapi - # -- defaults to `Chart.appVersion` + # -- defaults to `Chart.appVersion`. As of v5.7.0, this is the `distroless` flavor tag: "" - # -- the flavor or variant of the image to use. - # appended to the image tag by `-`. - flavor: "distroless" # -- image pullPolicy to use pullPolicy: IfNotPresent @@ -96,22 +93,24 @@ postgresql: # see for details # if set to `false`, the values under `externalDatabase` are used enabled: true - # -- name of the database to create - # see: - postgresqlDatabase: "fhir" - # -- Name of existing secret to use for PostgreSQL passwords. - # The secret has to contain the keys `postgresql-password` - # which is the password for `postgresqlUsername` when it is - # different of `postgres`, `postgresql-postgres-password` which - # will override `postgresqlPassword`, `postgresql-replication-password` - # which will override `replication.password` and `postgresql-ldap-password` - # which will be sed to authenticate on LDAP. The value is evaluated as a template. - existingSecret: "" - containerSecurityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL + auth: + # -- name for a custom database to create + database: "fhir" + # -- Name of existing secret to use for PostgreSQL credentials + # `auth.postgresPassword`, `auth.password`, and `auth.replicationPassword` will be ignored and picked up from this secret + # The secret must contain the keys `postgres-password` (which is the password for "postgres" admin user), + # `password` (which is the password for the custom user to create when `auth.username` is set), + # and `replication-password` (which is the password for replication user). + # The secret might also contains the key `ldap-password` if LDAP is enabled. `ldap.bind_password` will be ignored and + # picked from this secret in this case. + # The value is evaluated as a template. + existingSecret: "" + primary: + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL readinessProbe: failureThreshold: 5 From bf51c2263af48f1a5927363d45c136068c78bd21 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Mon, 11 Apr 2022 20:00:06 +0200 Subject: [PATCH 061/192] Update application.yaml Reverted to sane defaults --- src/main/resources/application.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index df616721414..891bf363894 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -86,8 +86,7 @@ hapi: # enable_index_missing_fields: false # enable_index_contained_resource: false # advanced_lucene_indexing: false - advanced_lucene_indexing: true -# enforce_referential_integrity_on_delete: false + # enforce_referential_integrity_on_delete: false # enforce_referential_integrity_on_write: false # etag_support_enabled: true # expunge_enabled: true From ae724f417224c41fb6ab6eb527b1e5f9d522a86e Mon Sep 17 00:00:00 2001 From: Jaison Baskaran Date: Wed, 13 Apr 2022 08:54:11 -0600 Subject: [PATCH 062/192] Bump to PRE10 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0c0f6280ed3..566ae629ef8 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.0.0-PRE9-SNAPSHOT + 6.0.0-PRE10-SNAPSHOT hapi-fhir-jpaserver-starter From c607a98728b2eb79bf73b266e3457bbab7f44e3c Mon Sep 17 00:00:00 2001 From: chgl Date: Fri, 15 Apr 2022 19:28:53 +0200 Subject: [PATCH 063/192] Updated to HAPI FHIR version 5.7.2 (#349) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 65d418fcee1..fc2346b7871 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.7.0 + 5.7.2 hapi-fhir-jpaserver-starter From f1e18d200a2656db37a81dd355909bf1fd9b587b Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Wed, 20 Apr 2022 12:23:10 -0400 Subject: [PATCH 064/192] Revert accidental default activation of experimental lucene indexing --- src/main/resources/application.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 7083b7d3ecb..deea04ff892 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -84,8 +84,8 @@ hapi: # enable_repository_validating_interceptor: false # enable_index_missing_fields: false # enable_index_contained_resource: false - # advanced_lucene_indexing: false - advanced_lucene_indexing: true + # This is an experimental feature, and does not fully support _total and other FHIR features. + advanced_lucene_indexing: false # enforce_referential_integrity_on_delete: false # enforce_referential_integrity_on_write: false # etag_support_enabled: true From c8da589636ca510445310efb36692806cb8b8a7b Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Wed, 20 Apr 2022 18:31:37 +0200 Subject: [PATCH 065/192] Add disclaimer for advanced_lucene_indexing added warning to advanced_lucene_indexing: false property --- src/main/resources/application.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 062008fa88d..95c7c5af06e 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -92,6 +92,8 @@ hapi: # enable_repository_validating_interceptor: false # enable_index_missing_fields: false # enable_index_contained_resource: false + ### !!Extended Lucene/Elasticsearch Indexing is still a experimental feature, expect some features (e.g. _total=accurate) to not work as expected!! + ### more information here: https://hapifhir.io/hapi-fhir/docs/server_jpa/elastic.html # advanced_lucene_indexing: false # enforce_referential_integrity_on_delete: false # enforce_referential_integrity_on_write: false From f736b6d8e63bd6bf802eeec57614fd768629a116 Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Fri, 29 Apr 2022 08:57:37 -0400 Subject: [PATCH 066/192] Bump to hapi PRE11 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 566ae629ef8..b8fb17f048c 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.0.0-PRE10-SNAPSHOT + 6.0.0-PRE11-SNAPSHOT hapi-fhir-jpaserver-starter From fdfa6fd711f411c58b9175223c05141cea0598fe Mon Sep 17 00:00:00 2001 From: chgl Date: Sun, 1 May 2022 21:48:18 +0200 Subject: [PATCH 067/192] Expose Prometheus metrics (#355) --- pom.xml | 7 +++++++ src/main/resources/application.yaml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fc2346b7871..6a69b1b8932 100644 --- a/pom.xml +++ b/pom.xml @@ -317,6 +317,13 @@ ${spring_boot_version} + + + io.micrometer + micrometer-registry-prometheus + 1.8.5 + + com.zaxxer HikariCP diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 95c7c5af06e..45c3e13a60d 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -4,7 +4,7 @@ management: endpoints: web: exposure: - include: "health" + include: "health,prometheus" spring: main: allow-circular-references: true From 91e4105fd8c0c900e552633fbe02d436564b8675 Mon Sep 17 00:00:00 2001 From: Alejandro Medina Date: Fri, 6 May 2022 12:25:51 -0400 Subject: [PATCH 068/192] Add: of-type modifier option in application.yaml (#363) Co-authored-by: Alejandro Medina --- src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java | 9 +++++++++ .../ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java | 1 + src/main/resources/application.yaml | 1 + 3 files changed, 11 insertions(+) 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 2ef74cfe3df..a4ab834f401 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -22,6 +22,7 @@ public class AppProperties { private Boolean openapi_enabled = false; private Boolean mdm_enabled = false; private boolean advanced_lucene_indexing = false; + private boolean enable_index_of_type = false; private Boolean allow_cascading_deletes = false; private Boolean allow_contains_searches = true; private Boolean allow_external_references = false; @@ -834,4 +835,12 @@ public void setQuitWait(Boolean quitWait) { private Boolean quitWait = false; } } + + public boolean getEnable_index_of_type() { + return enable_index_of_type; + } + + public void setEnable_index_of_type(boolean enable_index_of_type) { + this.enable_index_of_type = enable_index_of_type; + } } 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 d9617c75b21..3896167e556 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -178,6 +178,7 @@ public ModelConfig modelConfig(AppProperties appProperties, DaoConfig daoConfig) modelConfig.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); modelConfig.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); + modelConfig.setIndexIdentifierOfType(appProperties.getEnable_index_of_type()); return modelConfig; } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 45c3e13a60d..67c86f43c86 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -91,6 +91,7 @@ hapi: # delete_expunge_enabled: true # enable_repository_validating_interceptor: false # enable_index_missing_fields: false + # enable_index_of_type: true # enable_index_contained_resource: false ### !!Extended Lucene/Elasticsearch Indexing is still a experimental feature, expect some features (e.g. _total=accurate) to not work as expected!! ### more information here: https://hapifhir.io/hapi-fhir/docs/server_jpa/elastic.html From 244113ba67d99b414f2c1bba6379145c16b922dd Mon Sep 17 00:00:00 2001 From: Dennis Verspuij <6680484+dennisverspuij@users.noreply.github.com> Date: Mon, 9 May 2022 21:39:56 +0200 Subject: [PATCH 069/192] Fix applying supported_resource_types option with list that already includes SearchParameter (#365) --- .../java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 3d94924ac21..fb48ffda537 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -131,8 +131,10 @@ protected void initialize() throws ServletException { // Customize supported resource types List supportedResourceTypes = appProperties.getSupported_resource_types(); - if (!supportedResourceTypes.isEmpty() && !supportedResourceTypes.contains("SearchParameter")) { - supportedResourceTypes.add("SearchParameter"); + if (!supportedResourceTypes.isEmpty()) { + if (!supportedResourceTypes.contains("SearchParameter")) { + supportedResourceTypes.add("SearchParameter"); + } daoRegistry.setSupportedResourceTypes(supportedResourceTypes); } From cd0b8d7392ceaef13a68aa9f56fb038489f0152f Mon Sep 17 00:00:00 2001 From: Tadgh Date: Mon, 16 May 2022 09:57:30 -0700 Subject: [PATCH 070/192] Bump pom and minimum java version --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index b8fb17f048c..a21f708461c 100644 --- a/pom.xml +++ b/pom.xml @@ -14,13 +14,13 @@ ca.uhn.hapi.fhir hapi-fhir - 6.0.0-PRE11-SNAPSHOT + 6.0.0 hapi-fhir-jpaserver-starter - 8 + 11 @@ -375,7 +375,7 @@ maven-compiler-plugin 3.8.1 - 8 + 11 From ffd0cb1a4f8a662f01058ce5bf7a5101c5298241 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Mon, 16 May 2022 14:26:52 -0700 Subject: [PATCH 071/192] Bump ES version --- .../uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 1387354f75e..366ed48d456 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -43,6 +43,7 @@ "hapi.fhir.fhir_version=r4", "hapi.fhir.lastn_enabled=true", "hapi.fhir.store_resource_in_lucene_index_enabled=true", + "hapi.fhir.advanced_lucene_indexing=true", "elasticsearch.enabled=true", // Because the port is set randomly, we will set the rest_url using the Initializer. // "elasticsearch.rest_url='http://localhost:9200'", @@ -57,10 +58,9 @@ public class ElasticsearchLastNR4IT { private IGenericClient ourClient; private FhirContext ourCtx; - private static final String ELASTIC_VERSION = "7.10.2"; - private static final String ELASTIC_IMAGE = "docker.elastic.co/elasticsearch/elasticsearch:" + ELASTIC_VERSION; - - private static ElasticsearchContainer embeddedElastic; + private static final String ELASTIC_VERSION = "7.16.3"; + private static final String ELASTIC_IMAGE = "docker.elastic.co/elasticsearch/elasticsearch:" + ELASTIC_VERSION; + private static ElasticsearchContainer embeddedElastic; @Autowired private ElasticsearchSvcImpl myElasticsearchSvc; @@ -90,8 +90,10 @@ void testLastN() throws IOException { obs.getSubject().setReferenceElement(id); String observationCode = "testobservationcode"; String codeSystem = "http://testobservationcodesystem"; + obs.getCode().addCoding().setCode(observationCode).setSystem(codeSystem); obs.setValue(new StringType(observationCode)); + Date effectiveDtm = new GregorianCalendar().getTime(); obs.setEffective(new DateTimeType(effectiveDtm)); obs.getCategoryFirstRep().addCoding().setCode("testcategorycode").setSystem("http://testcategorycodesystem"); @@ -103,6 +105,7 @@ void testLastN() throws IOException { .withParameter(Parameters.class, "max", new IntegerType(1)) .andParameter("subject", new StringType("Patient/" + id.getIdPart())) .execute(); + Bundle b = (Bundle) output.getParameter().get(0).getResource(); assertEquals(1, b.getTotal()); assertEquals(obsId, b.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless()); From 87585ec7cc3d17c2bc4b51cc148f2537031244c2 Mon Sep 17 00:00:00 2001 From: Jaison Baskaran Date: Mon, 16 May 2022 16:18:30 -0600 Subject: [PATCH 072/192] hibernate search application properties updates. --- .../ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 366ed48d456..593faaea87e 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -50,7 +50,10 @@ "elasticsearch.username=SomeUsername", "elasticsearch.password=SomePassword", "elasticsearch.protocol=http", - "spring.main.allow-bean-definition-overriding=true" + "spring.main.allow-bean-definition-overriding=true", + "spring.jpa.properties.hibernate.search.enabled=true", + "spring.jpa.properties.hibernate.search.backend.type=elasticsearch", + "spring.jpa.properties.hibernate.search.backend.analysis.configurer=ca.uhn.fhir.jpa.search.elastic.HapiElasticsearchAnalysisConfigurer" }) @ContextConfiguration(initializers = ElasticsearchLastNR4IT.Initializer.class) public class ElasticsearchLastNR4IT { @@ -80,7 +83,8 @@ public void stop() { private int port; @Test - void testLastN() throws IOException { + void testLastN() throws IOException, InterruptedException { + Thread.sleep(2000); Patient pt = new Patient(); pt.addName().setFamily("Lastn").addGiven("Arthur"); @@ -105,7 +109,6 @@ void testLastN() throws IOException { .withParameter(Parameters.class, "max", new IntegerType(1)) .andParameter("subject", new StringType("Patient/" + id.getIdPart())) .execute(); - Bundle b = (Bundle) output.getParameter().get(0).getResource(); assertEquals(1, b.getTotal()); assertEquals(obsId, b.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless()); From 12ea07b460bdf71dbf92e4d198a1869e6dbc75e5 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Mon, 16 May 2022 15:45:49 -0700 Subject: [PATCH 073/192] make lastN test pass --- .../java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 593faaea87e..6ad49c61cf5 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -49,6 +49,7 @@ // "elasticsearch.rest_url='http://localhost:9200'", "elasticsearch.username=SomeUsername", "elasticsearch.password=SomePassword", + "elasticsearch.debug.refresh_after_write=true", "elasticsearch.protocol=http", "spring.main.allow-bean-definition-overriding=true", "spring.jpa.properties.hibernate.search.enabled=true", From 5942823f17f6cdf0e6c0888b16db0dcac9908db4 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 19 May 2022 11:56:14 -0700 Subject: [PATCH 074/192] Remove value set provider as it causes a boot failure without lucene --- .../ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) 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 0a714da84d8..616dbcaef40 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -78,8 +78,9 @@ public class BaseJpaRestfulServer extends RestfulServer { BulkDataExportProvider bulkDataExportProvider; @Autowired PartitionManagementProvider partitionManagementProvider; - @Autowired - ValueSetOperationProvider valueSetOperationProvider; + //TODO GGG RE-ADD ONCE FIXED IN HAPI-FHIR +// @Autowired +// ValueSetOperationProvider valueSetOperationProvider; @Autowired ReindexProvider reindexProvider; @Autowired @@ -134,7 +135,8 @@ protected void initialize() throws ServletException { registerProviders(resourceProviderFactory.createProviders()); registerProvider(jpaSystemProvider); - registerProvider(myValueSetOperationProvider); + //TODO GGG RE-ADD ONCE FIXED IN HAPI-FHIR +// registerProvider(myValueSetOperationProvider); /* * 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 @@ -361,7 +363,8 @@ protected void initialize() throws ServletException { } // valueSet Operations i.e $expand - registerProvider(valueSetOperationProvider); + //TODO GGG RE-ADD ONCE FIXED IN HAPI-FHIR +// registerProvider(myValueSetOperationProvider); //reindex Provider $reindex registerProvider(reindexProvider); From af842619b0f9de2684a633c49e9078416b231d5a Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 19 May 2022 12:59:22 -0700 Subject: [PATCH 075/192] Fix reindex provider --- .../java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 616dbcaef40..6d8a0f2c24d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.starter; +import ca.uhn.fhir.batch2.jobs.reindex.ReindexProvider; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.support.IValidationSupport; @@ -28,7 +29,6 @@ import ca.uhn.fhir.rest.server.*; import ca.uhn.fhir.rest.server.interceptor.*; import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor; -import ca.uhn.fhir.rest.server.provider.ReindexProvider; import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; @@ -81,8 +81,8 @@ public class BaseJpaRestfulServer extends RestfulServer { //TODO GGG RE-ADD ONCE FIXED IN HAPI-FHIR // @Autowired // ValueSetOperationProvider valueSetOperationProvider; - @Autowired - ReindexProvider reindexProvider; + @Autowired + ReindexProvider reindexProvider; @Autowired BinaryStorageInterceptor binaryStorageInterceptor; @Autowired From d4bc6febb39d5fdd240bb3dee9c381d5003507bf Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 19 May 2022 13:34:29 -0700 Subject: [PATCH 076/192] Bump java version for test --- .github/workflows/maven.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 435d58b3dfd..9919452b887 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -17,9 +17,9 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Build with Maven run: mvn -B package --file pom.xml From 6ad499cecb82c3bc1c76b50aa58d46ea6b95a91b Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 19 May 2022 14:45:42 -0700 Subject: [PATCH 077/192] Bump to pre-01 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6019652990c..b2da79cfc32 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.0.0 + 6.1.0-PRE1-SNAPSHOT hapi-fhir-jpaserver-starter From e5b0fc721621eaece1291bbdacc72a4caabf67a2 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Fri, 20 May 2022 15:24:17 -0400 Subject: [PATCH 078/192] fix build --- .../java/ca/uhn/fhir/jpa/starter/Application.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) 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 0ba207207d5..2a26b5cb3ef 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -1,5 +1,7 @@ package ca.uhn.fhir.jpa.starter; +import ca.uhn.fhir.batch2.jobs.config.Batch2JobsConfig; +import ca.uhn.fhir.jpa.batch2.JpaBatch2Config; import ca.uhn.fhir.jpa.starter.annotations.OnEitherVersion; import ca.uhn.fhir.jpa.starter.mdm.MdmConfig; import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig; @@ -24,7 +26,15 @@ @ServletComponentScan(basePackageClasses = { JpaRestfulServer.class}) @SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class}) -@Import({SubscriptionSubmitterConfig.class, SubscriptionProcessorConfig.class, SubscriptionChannelConfig.class, WebsocketDispatcherConfig.class, MdmConfig.class}) +@Import({ + SubscriptionSubmitterConfig.class, + SubscriptionProcessorConfig.class, + SubscriptionChannelConfig.class, + WebsocketDispatcherConfig.class, + MdmConfig.class, + JpaBatch2Config.class, + Batch2JobsConfig.class +}) public class Application extends SpringBootServletInitializer { public static void main(String[] args) { From 4dacf6ae904fa45a04c38a7bb9622cdff9115247 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Sat, 21 May 2022 09:54:50 -0700 Subject: [PATCH 079/192] Re-add valuesetoperation provider --- .../ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 6d8a0f2c24d..7da8638f8e7 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -78,11 +78,11 @@ public class BaseJpaRestfulServer extends RestfulServer { BulkDataExportProvider bulkDataExportProvider; @Autowired PartitionManagementProvider partitionManagementProvider; - //TODO GGG RE-ADD ONCE FIXED IN HAPI-FHIR -// @Autowired -// ValueSetOperationProvider valueSetOperationProvider; - @Autowired - ReindexProvider reindexProvider; + + @Autowired + ValueSetOperationProvider valueSetOperationProvider; + @Autowired + ReindexProvider reindexProvider; @Autowired BinaryStorageInterceptor binaryStorageInterceptor; @Autowired From f39393ca976db25e0dda588bb67451683af074e6 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Sat, 21 May 2022 10:10:20 -0700 Subject: [PATCH 080/192] Disable lucene by default --- src/main/resources/application.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 0174848fb7f..9492327dc52 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -40,7 +40,7 @@ spring: # hibernate.cache.use_structured_entries: false # hibernate.cache.use_minimal_puts: false ### These settings will enable fulltext search with lucene - # hibernate.search.enabled: true + hibernate.search.enabled: false # hibernate.search.backend.type: lucene # hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiLuceneAnalysisConfigurer # hibernate.search.backend.directory.type: local-filesystem From d660dc137004d8bbe2c635fe6b7ae31701f286c0 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Sat, 21 May 2022 10:31:49 -0700 Subject: [PATCH 081/192] Re-add valueset operation provider --- .../java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 7da8638f8e7..c7ec35b34a5 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -135,8 +135,6 @@ protected void initialize() throws ServletException { registerProviders(resourceProviderFactory.createProviders()); registerProvider(jpaSystemProvider); - //TODO GGG RE-ADD ONCE FIXED IN HAPI-FHIR -// registerProvider(myValueSetOperationProvider); /* * 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 @@ -363,8 +361,7 @@ protected void initialize() throws ServletException { } // valueSet Operations i.e $expand - //TODO GGG RE-ADD ONCE FIXED IN HAPI-FHIR -// registerProvider(myValueSetOperationProvider); + registerProvider(myValueSetOperationProvider); //reindex Provider $reindex registerProvider(reindexProvider); From 9882a1cd58065bf90f2d9ef011d99ffe7acbb779 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 24 May 2022 17:37:45 -0400 Subject: [PATCH 082/192] adding smoke test files --- .../smoketestfiles/patient_batch_create.json | 85 +++++++ .../smoketestfiles/patient_create.json | 162 +++++++++++++ .../smoketestfiles/patient_patch.json | 7 + .../patient_process_message.json | 63 +++++ .../smoketestfiles/patient_update.json | 20 ++ src/test/smoketest/SMOKE_TEST.md | 10 + src/test/smoketest/http-client.env.json | 7 + src/test/smoketest/plain_server.rest | 223 ++++++++++++++++++ 8 files changed, 577 insertions(+) create mode 100644 src/test/resources/smoketestfiles/patient_batch_create.json create mode 100644 src/test/resources/smoketestfiles/patient_create.json create mode 100644 src/test/resources/smoketestfiles/patient_patch.json create mode 100644 src/test/resources/smoketestfiles/patient_process_message.json create mode 100644 src/test/resources/smoketestfiles/patient_update.json create mode 100644 src/test/smoketest/SMOKE_TEST.md create mode 100644 src/test/smoketest/http-client.env.json create mode 100644 src/test/smoketest/plain_server.rest diff --git a/src/test/resources/smoketestfiles/patient_batch_create.json b/src/test/resources/smoketestfiles/patient_batch_create.json new file mode 100644 index 00000000000..c476f72f931 --- /dev/null +++ b/src/test/resources/smoketestfiles/patient_batch_create.json @@ -0,0 +1,85 @@ +{ + "resourceType": "Bundle", + "id": "bundle-transaction", + "meta": { + "lastUpdated": "2014-08-18T01:43:30Z" + }, + "type": "transaction", + "entry": [ + { + "resource": { + "resourceType": "Patient", + "text": { + "status": "generated", + "div": "
Some narrative
" + }, + "active": true, + "name": [ + { + "use": "official", + "family": "Iantorno", + "given": [ + "Mark" + ] + } + ], + "gender": "male", + "birthDate": "1983-06-23" + }, + "request": { + "method": "POST", + "url": "Patient" + } + }, + { + "resource": { + "resourceType": "Patient", + "text": { + "status": "generated", + "div": "
Some narrative
" + }, + "active": true, + "name": [ + { + "use": "official", + "family": "Iantorno", + "given": [ + "Alexander" + ] + } + ], + "gender": "male", + "birthDate": "1993-08-16" + }, + "request": { + "method": "POST", + "url": "Patient" + } + }, + { + "resource": { + "resourceType": "Patient", + "text": { + "status": "generated", + "div": "
Some narrative
" + }, + "active": true, + "name": [ + { + "use": "official", + "family": "Cash", + "given": [ + "Johnny" + ] + } + ], + "gender": "male", + "birthDate": "1932-02-26" + }, + "request": { + "method": "POST", + "url": "Patient" + } + } + ] +} \ No newline at end of file diff --git a/src/test/resources/smoketestfiles/patient_create.json b/src/test/resources/smoketestfiles/patient_create.json new file mode 100644 index 00000000000..73f58999de6 --- /dev/null +++ b/src/test/resources/smoketestfiles/patient_create.json @@ -0,0 +1,162 @@ +{ + "resourceType": "Patient", + "id": "example", + "text": { + "status": "generated", + "div": "
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
NamePeter James \n Chalmers ("Jim")\n
Address534 Erewhon, Pleasantville, Vic, 3999
ContactsHome: unknown. Work: (03) 5555 6473
IdMRN: 12345 (Acme Healthcare)
\n\t\t
" + }, + "identifier": [ + { + "use": "usual", + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "MR" + } + ] + }, + "system": "urn:oid:1.2.36.146.595.217.0.1", + "value": "12345", + "period": { + "start": "2001-05-06" + }, + "assigner": { + "display": "Acme Healthcare" + } + } + ], + "active": true, + "name": [ + { + "use": "official", + "family": "Chalmers", + "given": [ + "Peter", + "James" + ] + }, + { + "use": "usual", + "given": [ + "Jim" + ] + }, + { + "use": "maiden", + "family": "Windsor", + "given": [ + "Peter", + "James" + ], + "period": { + "end": "2002" + } + } + ], + "telecom": [ + { + "use": "home" + }, + { + "system": "phone", + "value": "(03) 5555 6473", + "use": "work", + "rank": 1 + }, + { + "system": "phone", + "value": "(03) 3410 5613", + "use": "mobile", + "rank": 2 + }, + { + "system": "phone", + "value": "(03) 5555 8834", + "use": "old", + "period": { + "end": "2014" + } + } + ], + "gender": "male", + "birthDate": "1974-12-25", + "_birthDate": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/patient-birthTime", + "valueDateTime": "1974-12-25T14:35:45-05:00" + } + ] + }, + "deceasedBoolean": false, + "address": [ + { + "use": "home", + "type": "both", + "text": "534 Erewhon St PeasantVille, Rainbow, Vic 3999", + "line": [ + "534 Erewhon St" + ], + "city": "PleasantVille", + "district": "Rainbow", + "state": "Vic", + "postalCode": "3999", + "period": { + "start": "1974-12-25" + } + } + ], + "contact": [ + { + "relationship": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0131", + "code": "N" + } + ] + } + ], + "name": { + "family": "du Marché", + "_family": { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/humanname-own-prefix", + "valueString": "VV" + } + ] + }, + "given": [ + "Bénédicte" + ] + }, + "telecom": [ + { + "system": "phone", + "value": "+33 (237) 998327" + } + ], + "address": { + "use": "home", + "type": "both", + "line": [ + "534 Erewhon St" + ], + "city": "PleasantVille", + "district": "Rainbow", + "state": "Vic", + "postalCode": "3999", + "period": { + "start": "1974-12-25" + } + }, + "gender": "female", + "period": { + "start": "2012" + } + } + ] +} \ No newline at end of file diff --git a/src/test/resources/smoketestfiles/patient_patch.json b/src/test/resources/smoketestfiles/patient_patch.json new file mode 100644 index 00000000000..b1cfaaa25d6 --- /dev/null +++ b/src/test/resources/smoketestfiles/patient_patch.json @@ -0,0 +1,7 @@ +[ + { + "op": "add", + "path": "/active", + "value": false + } +] \ No newline at end of file diff --git a/src/test/resources/smoketestfiles/patient_process_message.json b/src/test/resources/smoketestfiles/patient_process_message.json new file mode 100644 index 00000000000..033f3cf4a86 --- /dev/null +++ b/src/test/resources/smoketestfiles/patient_process_message.json @@ -0,0 +1,63 @@ +{ + "resourceType": "MessageHeader", + "id": "{{batch_patient_id}}", + "text": { + "status": "generated", + "div": "
\n\t\t\t

Update Person resource for Peter James CHALMERS (Jim), MRN: 12345 (Acme Healthcare)

\n\t\t
" + }, + "eventCoding": { + "system": "http://example.org/fhir/message-events", + "code": "admin-notify" + }, + "destination": [ + { + "name": "Acme Message Gateway", + "target": { + "reference": "Device/example" + }, + "endpoint": "llp:10.11.12.14:5432", + "receiver": { + "reference": "http://acme.com/ehr/fhir/Practitioner/2323-33-4" + } + } + ], + "sender": { + "reference": "Organization/1" + }, + "enterer": { + "reference": "Practitioner/example" + }, + "author": { + "reference": "Practitioner/example" + }, + "source": { + "name": "Acme Central Patient Registry", + "software": "FooBar Patient Manager", + "version": "3.1.45.AABB", + "contact": { + "system": "phone", + "value": "+1 (555) 123 4567" + }, + "endpoint": "llp:10.11.12.13:5432" + }, + "reason": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/message-reasons-encounter", + "code": "admit" + } + ] + }, + "response": { + "identifier": { + "value": "5015fe84-8e76-4526-89d8-44b322e8d4fb" + }, + "code": "ok" + }, + "focus": [ + { + "reference": "Patient/example" + } + ], + "definition": "http:////acme.com/ehr/fhir/messagedefinition/patientrequest" +} \ No newline at end of file diff --git a/src/test/resources/smoketestfiles/patient_update.json b/src/test/resources/smoketestfiles/patient_update.json new file mode 100644 index 00000000000..b182b2fbf52 --- /dev/null +++ b/src/test/resources/smoketestfiles/patient_update.json @@ -0,0 +1,20 @@ +{ + "resourceType": "Patient", + "id": "{{batch_patient_id}}", + "text": { + "status": "generated", + "div": "
Some narrative
" + }, + "active": true, + "name": [ + { + "use": "official", + "family": "Iantoryes", + "given": [ + "Mark" + ] + } + ], + "gender": "male", + "birthDate": "1983-06-23" +} diff --git a/src/test/smoketest/SMOKE_TEST.md b/src/test/smoketest/SMOKE_TEST.md new file mode 100644 index 00000000000..3370613fa85 --- /dev/null +++ b/src/test/smoketest/SMOKE_TEST.md @@ -0,0 +1,10 @@ +# JPA Server Starter Smoke Tests + +--- + +### What they do... +When updating the HAPI-FHIR version, or making changes to the JPA server starter code itself, + +### Requirements... + +### How to run the smoke test... diff --git a/src/test/smoketest/http-client.env.json b/src/test/smoketest/http-client.env.json new file mode 100644 index 00000000000..85b8ef4a45d --- /dev/null +++ b/src/test/smoketest/http-client.env.json @@ -0,0 +1,7 @@ +{ + "default": { + "host": "localhost:8080", + "username": "username", + "password": "password" + } +} \ No newline at end of file diff --git a/src/test/smoketest/plain_server.rest b/src/test/smoketest/plain_server.rest new file mode 100644 index 00000000000..47e15154315 --- /dev/null +++ b/src/test/smoketest/plain_server.rest @@ -0,0 +1,223 @@ +### Create Single Patient +# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#create-type +POST http://{{host}}/fhir/Patient +Content-Type: application/json + +< ../resources/smoketestfiles/patient_create.json + +> {% + client.test("Patient created successfully", function() { + client.assert(response.status === 201, "Response status is not 201"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Patient", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Patient", "Expected 'Patient' but received '" + resourceType + "'"); + }); + client.global.set("single_patient_id", response.body.id); + client.global.set("single_patient_family_name", response.body.name[0].family); +%} + +### Search Single Patient +# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#search +GET http://{{host}}/fhir/Patient?name={{single_patient_family_name}}&_id={{single_patient_id}} + +> {% + client.test("Patient created successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Bundle", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Bundle", "Expected 'Bundle' but received '" + resourceType + "'"); + }); + client.test("Total patients found is 1", function() { + const totalFound = response.body.total; + client.assert(totalFound === 1, "Expected '1' match but found '" + totalFound + "'"); + }); + %} + +### Delete Patient +# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#delete-instance +DELETE http://{{host}}/fhir/Patient/{{single_patient_id}} + +> {% + client.test("Patient deleted successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is OperationOutcome", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "OperationOutcome", "Expected 'OperationOutcome' but received '" + resourceType + "'"); + }); +%} + +### Batch Patient Create +# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#transaction-server +POST http://{{host}}/fhir/ +Content-Type: application/json + +< ../resources/smoketestfiles/patient_batch_create.json + +> {% + client.test("Bundle transaction completed successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Bundle", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Bundle", "Expected 'Bundle' but received '" + resourceType + "'"); + }); + client.test("All patient additions successful", function() { + for (var index = 0; index < response.body.entry.length; index++) { + client.assert(response.body.entry[index].response.status === "201 Created", "Expected '201 Created' for patient index " + index + " but received '" + response.body.entry[index].response.status + "'"); + } + }); + const batch_patient_location = response.body.entry[0].response.location; + const indexOfHistory = batch_patient_location.lastIndexOf("/_history"); + trimmed_location = batch_patient_location.substring(0, indexOfHistory); + trimmed_location = trimmed_location.replace("Patient/", "") + client.global.set("batch_patient_id", trimmed_location); +%} + +### Update - Instance +# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#update-instance +PUT http://{{host}}/fhir/Patient/{{batch_patient_id}} +Content-Type: application/json + +< ../resources/smoketestfiles/patient_update.json + +> {% + client.test("Bundle transaction completed successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Patient", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Patient", "Expected 'Patient' but received '" + resourceType + "'"); + }); + client.test("Test last name updated", function() { + const familyName = response.body.name[0].family; + client.assert(familyName === "Iantoryes", "Expected updated family name 'Iantoryes' but received '" + familyName + "'"); + }); + client.test("Test version number updated", function() { + const versionId = response.body.meta.versionId; + client.assert(versionId === "2", "Expected updated versionId name '2' but received '" + versionId + "'"); + }); +%} + +### Patch - Instance +# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#patch-instance +PATCH http://{{host}}/fhir/Patient/{{batch_patient_id}} +Content-Type: application/json-patch+json + +< ../resources/smoketestfiles/patient_patch.json + +> {% + client.test("Patch operation completed successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Patient", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Patient", "Expected 'Patient' but received '" + resourceType + "'"); + }); + client.test("Test active field patched", function() { + const active = response.body.active; + client.assert(active === false, "Expected updated active 'false' but received '" + active + "'"); + }); +%} + +### History - Server/Type/Instance +# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#history-servertypeinstance +GET http://{{host}}/fhir/Patient/{{batch_patient_id}}/_history + +> {% + client.test("History completed successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Bundle", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Bundle", "Expected 'Bundle' but received '" + resourceType + "'"); + }); + client.test("Test receive history type", function() { + const type = response.body.type; + client.assert(type === "history", "Expected type 'history' but received '" + type + "'"); + }); +%} + +### Capability Statement +# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#capability-statement-metadata-server +GET http://{{host}}/fhir/metadata + +> {% + client.test("CapabilityStatement fetched successfully", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is CapabilityStatement", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "CapabilityStatement", "Expected 'CapabilityStatement' but received '" + resourceType + "'"); + }); +%} + +### Extended Operations - everything +# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#extended-operations +GET http://{{host}}/fhir/Patient/{{batch_patient_id}}/$everything + +> {% + client.test("$everything operation successful", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is Bundle", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "Bundle", "Expected 'Bundle' but received '" + resourceType + "'"); + }); +%} + +### Extended Operations - validate +# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#extended-operations +POST http://{{host}}/fhir/Patient/{{batch_patient_id}}/$validate + +> {% + client.test("$validate operation successful", function() { + client.assert(response.status === 200, "Response status is not 200"); + }); + client.test("Response content-type is json", function() { + const type = response.contentType.mimeType; + client.assert(type === "application/fhir+json", "Expected 'application/fhir+json' but received '" + type + "'"); + }); + client.test("Response resourceType is OperationOutcome", function() { + const resourceType = response.body.resourceType; + client.assert(resourceType === "OperationOutcome", "Expected 'OperationOutcome' but received '" + resourceType + "'"); + }); +%} \ No newline at end of file From 067c7f16c4f450599e088b7a30f4cb50475495ad Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 24 May 2022 19:18:07 -0400 Subject: [PATCH 083/192] adding base documentation --- src/test/smoketest/SMOKE_TEST.md | 52 +++++++++++++++++-- src/test/smoketest/plain_server.rest | 30 +++++------ .../smoketestfiles/patient_batch_create.json | 0 .../smoketestfiles/patient_create.json | 0 .../smoketestfiles/patient_patch.json | 0 .../patient_process_message.json | 0 .../smoketestfiles/patient_update.json | 0 7 files changed, 63 insertions(+), 19 deletions(-) rename src/test/{resources => smoketest}/smoketestfiles/patient_batch_create.json (100%) rename src/test/{resources => smoketest}/smoketestfiles/patient_create.json (100%) rename src/test/{resources => smoketest}/smoketestfiles/patient_patch.json (100%) rename src/test/{resources => smoketest}/smoketestfiles/patient_process_message.json (100%) rename src/test/{resources => smoketest}/smoketestfiles/patient_update.json (100%) diff --git a/src/test/smoketest/SMOKE_TEST.md b/src/test/smoketest/SMOKE_TEST.md index 3370613fa85..577e685cef1 100644 --- a/src/test/smoketest/SMOKE_TEST.md +++ b/src/test/smoketest/SMOKE_TEST.md @@ -2,9 +2,53 @@ --- -### What they do... -When updating the HAPI-FHIR version, or making changes to the JPA server starter code itself, +When updating the supporting HAPI-FHIR version, or making changes to the JPA server starter code itself, it is sometimes +useful to run basic smoke tests to ensure the basic functionality of the server is maintained. The goal of these tests is +to provide users a quick way to run groups of tests that correspond to various sections within the +[HAPI-FHIR documentation][Link-HAPI-FHIR-docs]. -### Requirements... +### Requirements +Tests are written in IntelliJ [HTTP Client Request files][Link-HTTP-Client-Req-Intro]. Ultimate edition of IntelliJ +is required to run these tests. -### How to run the smoke test... +For more details on integrated tooling and request syntax, there is [documentation available][Link-HTTP-Client-Req-Exploring] +on the jetbrains website, in addition to the [API reference][Link-HTTP-Client-Req-API]. + +### Formatting +As mentioned, each test file corresponds to a given section within the hapifhir documentation as close as possible. For +example, there is a `plain_server.rest` file, which attemps to smoke test all basic functionality outlined in the section +[within the docs][Link-HAPI-FHIR-docs-plain-server]. + +Individual tests are formatted as follows: +```javascript +### Test Title Here +# +REST-OPERATION ENDPOINT-URL +// Verification Steps +``` + +Users can setup custom environment variables for running tests locally against their own servers. This can be done by +adding environment information within the `http-client.env.json` file. By default, we provide the following: +```json +{ + "default": { + "host": "localhost:8080", + "username": "username", + "password": "password" + } +} +``` + +### Running the Tests +Within IntelliJ, right click the file you wish to run tests in and select the `Run All` option from the menu. + +**Important:** Tests may not work individually when run. Often times, tests need to be run sequentially, as they depend +on resources/references from previous tests to complete. _(An example of this would be adding a Patient, saving the id, +then using that idea to test if we can successfully PATCH that Patient resource.)_ + + +[Link-HAPI-FHIR-docs]: https://hapifhir.io/hapi-fhir/docs/ +[Link-HAPI-FHIR-docs-plain-server]: https://hapifhir.io/hapi-fhir/docs/server_plain/server_types.html +[Link-HTTP-Client-Req-Intro]: https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html +[Link-HTTP-Client-Req-Exploring]: https://www.jetbrains.com/help/idea/exploring-http-syntax.html +[Link-HTTP-Client-Req-API]: https://www.jetbrains.com/help/idea/http-response-handling-api-reference.html \ No newline at end of file diff --git a/src/test/smoketest/plain_server.rest b/src/test/smoketest/plain_server.rest index 47e15154315..c5856ffa8f9 100644 --- a/src/test/smoketest/plain_server.rest +++ b/src/test/smoketest/plain_server.rest @@ -1,9 +1,9 @@ ### Create Single Patient -# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#create-type +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#type_create POST http://{{host}}/fhir/Patient Content-Type: application/json -< ../resources/smoketestfiles/patient_create.json +< smoketestfiles/patient_create.json > {% client.test("Patient created successfully", function() { @@ -22,11 +22,11 @@ Content-Type: application/json %} ### Search Single Patient -# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#search +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#type_search GET http://{{host}}/fhir/Patient?name={{single_patient_family_name}}&_id={{single_patient_id}} > {% - client.test("Patient created successfully", function() { + client.test("Patient search successful", function() { client.assert(response.status === 200, "Response status is not 200"); }); client.test("Response content-type is json", function() { @@ -44,7 +44,7 @@ GET http://{{host}}/fhir/Patient?name={{single_patient_family_name}}&_id={{singl %} ### Delete Patient -# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#delete-instance +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#instance_delete DELETE http://{{host}}/fhir/Patient/{{single_patient_id}} > {% @@ -62,11 +62,11 @@ DELETE http://{{host}}/fhir/Patient/{{single_patient_id}} %} ### Batch Patient Create -# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#transaction-server +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#system_transaction POST http://{{host}}/fhir/ Content-Type: application/json -< ../resources/smoketestfiles/patient_batch_create.json +< smoketestfiles/patient_batch_create.json > {% client.test("Bundle transaction completed successfully", function() { @@ -93,11 +93,11 @@ Content-Type: application/json %} ### Update - Instance -# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#update-instance +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#instance_update PUT http://{{host}}/fhir/Patient/{{batch_patient_id}} Content-Type: application/json -< ../resources/smoketestfiles/patient_update.json +< smoketestfiles/patient_update.json > {% client.test("Bundle transaction completed successfully", function() { @@ -122,11 +122,11 @@ Content-Type: application/json %} ### Patch - Instance -# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#patch-instance +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#instance-level-patch PATCH http://{{host}}/fhir/Patient/{{batch_patient_id}} Content-Type: application/json-patch+json -< ../resources/smoketestfiles/patient_patch.json +< smoketestfiles/patient_patch.json > {% client.test("Patch operation completed successfully", function() { @@ -147,7 +147,7 @@ Content-Type: application/json-patch+json %} ### History - Server/Type/Instance -# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#history-servertypeinstance +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#history GET http://{{host}}/fhir/Patient/{{batch_patient_id}}/_history > {% @@ -169,7 +169,7 @@ GET http://{{host}}/fhir/Patient/{{batch_patient_id}}/_history %} ### Capability Statement -# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#capability-statement-metadata-server +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html#system_capabilities GET http://{{host}}/fhir/metadata > {% @@ -187,7 +187,7 @@ GET http://{{host}}/fhir/metadata %} ### Extended Operations - everything -# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#extended-operations +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations_operations.html GET http://{{host}}/fhir/Patient/{{batch_patient_id}}/$everything > {% @@ -205,7 +205,7 @@ GET http://{{host}}/fhir/Patient/{{batch_patient_id}}/$everything %} ### Extended Operations - validate -# https://hapifhir.io/hapi-fhir/docs/client/generic_client.html#extended-operations +# https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations_operations.html POST http://{{host}}/fhir/Patient/{{batch_patient_id}}/$validate > {% diff --git a/src/test/resources/smoketestfiles/patient_batch_create.json b/src/test/smoketest/smoketestfiles/patient_batch_create.json similarity index 100% rename from src/test/resources/smoketestfiles/patient_batch_create.json rename to src/test/smoketest/smoketestfiles/patient_batch_create.json diff --git a/src/test/resources/smoketestfiles/patient_create.json b/src/test/smoketest/smoketestfiles/patient_create.json similarity index 100% rename from src/test/resources/smoketestfiles/patient_create.json rename to src/test/smoketest/smoketestfiles/patient_create.json diff --git a/src/test/resources/smoketestfiles/patient_patch.json b/src/test/smoketest/smoketestfiles/patient_patch.json similarity index 100% rename from src/test/resources/smoketestfiles/patient_patch.json rename to src/test/smoketest/smoketestfiles/patient_patch.json diff --git a/src/test/resources/smoketestfiles/patient_process_message.json b/src/test/smoketest/smoketestfiles/patient_process_message.json similarity index 100% rename from src/test/resources/smoketestfiles/patient_process_message.json rename to src/test/smoketest/smoketestfiles/patient_process_message.json diff --git a/src/test/resources/smoketestfiles/patient_update.json b/src/test/smoketest/smoketestfiles/patient_update.json similarity index 100% rename from src/test/resources/smoketestfiles/patient_update.json rename to src/test/smoketest/smoketestfiles/patient_update.json From 8d6247bfe8357f0769ff7478e3533ed765006bae Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 24 May 2022 19:20:13 -0400 Subject: [PATCH 084/192] wip --- src/test/smoketest/SMOKE_TEST.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/smoketest/SMOKE_TEST.md b/src/test/smoketest/SMOKE_TEST.md index 577e685cef1..3610e6f15d8 100644 --- a/src/test/smoketest/SMOKE_TEST.md +++ b/src/test/smoketest/SMOKE_TEST.md @@ -44,7 +44,8 @@ Within IntelliJ, right click the file you wish to run tests in and select the `R **Important:** Tests may not work individually when run. Often times, tests need to be run sequentially, as they depend on resources/references from previous tests to complete. _(An example of this would be adding a Patient, saving the id, -then using that idea to test if we can successfully PATCH that Patient resource.)_ +then using that saved id to test if we can successfully PATCH that Patient resource. Without that saved id from the +previous test creating that patient, the PATCH test will fail.)_ [Link-HAPI-FHIR-docs]: https://hapifhir.io/hapi-fhir/docs/ From b71880e39ea06392a0a9aefdf40bc2621831dbef Mon Sep 17 00:00:00 2001 From: Mark Iantorno Date: Wed, 25 May 2022 12:55:16 -0400 Subject: [PATCH 085/192] Update src/test/smoketest/SMOKE_TEST.md Co-authored-by: Ken Stevens --- src/test/smoketest/SMOKE_TEST.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/smoketest/SMOKE_TEST.md b/src/test/smoketest/SMOKE_TEST.md index 3610e6f15d8..5f798250bb4 100644 --- a/src/test/smoketest/SMOKE_TEST.md +++ b/src/test/smoketest/SMOKE_TEST.md @@ -15,7 +15,7 @@ For more details on integrated tooling and request syntax, there is [documentati on the jetbrains website, in addition to the [API reference][Link-HTTP-Client-Req-API]. ### Formatting -As mentioned, each test file corresponds to a given section within the hapifhir documentation as close as possible. For +Each test file corresponds to a given section within the hapifhir documentation as close as possible. For example, there is a `plain_server.rest` file, which attemps to smoke test all basic functionality outlined in the section [within the docs][Link-HAPI-FHIR-docs-plain-server]. From 788015f467b91c9fb5dfaf043a7a4edd21553f94 Mon Sep 17 00:00:00 2001 From: Mark Iantorno Date: Wed, 25 May 2022 12:55:22 -0400 Subject: [PATCH 086/192] Update src/test/smoketest/SMOKE_TEST.md Co-authored-by: Ken Stevens --- src/test/smoketest/SMOKE_TEST.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/smoketest/SMOKE_TEST.md b/src/test/smoketest/SMOKE_TEST.md index 5f798250bb4..7ced8ca084f 100644 --- a/src/test/smoketest/SMOKE_TEST.md +++ b/src/test/smoketest/SMOKE_TEST.md @@ -2,8 +2,7 @@ --- -When updating the supporting HAPI-FHIR version, or making changes to the JPA server starter code itself, it is sometimes -useful to run basic smoke tests to ensure the basic functionality of the server is maintained. The goal of these tests is +When updating the supporting HAPI-FHIR version, or making changes to the JPA server starter code itself, it is recommended to run basic smoke tests to ensure the basic functionality of the server is maintained. The goal of these tests is to provide users a quick way to run groups of tests that correspond to various sections within the [HAPI-FHIR documentation][Link-HAPI-FHIR-docs]. From e9ff226750d5ac335d46bbddad1bdaa6a3baa935 Mon Sep 17 00:00:00 2001 From: Mark Iantorno Date: Wed, 25 May 2022 12:55:41 -0400 Subject: [PATCH 087/192] Update src/test/smoketest/SMOKE_TEST.md Co-authored-by: Ken Stevens --- src/test/smoketest/SMOKE_TEST.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/smoketest/SMOKE_TEST.md b/src/test/smoketest/SMOKE_TEST.md index 7ced8ca084f..968d7fb2fd8 100644 --- a/src/test/smoketest/SMOKE_TEST.md +++ b/src/test/smoketest/SMOKE_TEST.md @@ -26,8 +26,7 @@ REST-OPERATION ENDPOINT-URL // Verification Steps ``` -Users can setup custom environment variables for running tests locally against their own servers. This can be done by -adding environment information within the `http-client.env.json` file. By default, we provide the following: +To run these tests against a specific server, configure the server details within the `http-client.env.json` file. By default, we provide the following: ```json { "default": { From 73d7ee185771a10e9156d7b2d97fe7e5af6ae20f Mon Sep 17 00:00:00 2001 From: Mark Iantorno Date: Thu, 26 May 2022 15:00:07 -0400 Subject: [PATCH 088/192] bumping to non-snapshot version (#377) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b2da79cfc32..9cbbfab03e8 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.1.0-PRE1-SNAPSHOT + 6.0.1 hapi-fhir-jpaserver-starter From 67caa88e06cf79df9f52db95ea9b2da03b00af6c Mon Sep 17 00:00:00 2001 From: chgl Date: Sat, 4 Jun 2022 14:24:28 +0200 Subject: [PATCH 089/192] updated helm chart to use latest v6.0.1 version of the image (#382) * updated helm chart to use latest v6.0.1 version of the image * updated workflow to run against multiple k8s versions --- .github/workflows/chart-test.yaml | 13 +++-- charts/hapi-fhir-jpaserver/Chart.lock | 6 +-- charts/hapi-fhir-jpaserver/Chart.yaml | 30 ++++++++--- charts/hapi-fhir-jpaserver/README.md | 16 ++++-- .../templates/deployment.yaml | 32 ++++++++++-- .../templates/networkpolicy.yaml | 27 ---------- .../templates/service.yaml | 4 ++ .../templates/servicemonitor.yaml | 30 +++++++++++ charts/hapi-fhir-jpaserver/values.yaml | 51 +++++++++++-------- 9 files changed, 139 insertions(+), 70 deletions(-) delete mode 100644 charts/hapi-fhir-jpaserver/templates/networkpolicy.yaml create mode 100644 charts/hapi-fhir-jpaserver/templates/servicemonitor.yaml diff --git a/.github/workflows/chart-test.yaml b/.github/workflows/chart-test.yaml index b3eb576bf83..1d32194682f 100644 --- a/.github/workflows/chart-test.yaml +++ b/.github/workflows/chart-test.yaml @@ -15,7 +15,7 @@ jobs: - name: Install helm-docs working-directory: /tmp env: - HELM_DOCS_URL: https://github.com/norwoodj/helm-docs/releases/download/v1.5.0/helm-docs_1.5.0_Linux_x86_64.tar.gz + HELM_DOCS_URL: https://github.com/norwoodj/helm-docs/releases/download/v1.9.1/helm-docs_1.9.1_Linux_x86_64.tar.gz run: | curl -LSs $HELM_DOCS_URL | tar xz && \ mv ./helm-docs /usr/local/bin/helm-docs && \ @@ -35,16 +35,19 @@ jobs: test: runs-on: ubuntu-20.04 + strategy: + matrix: + k8s-version: [1.22.9, 1.23.6, 1.24.1] needs: - lint steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up chart-testing - uses: helm/chart-testing-action@v2.1.0 + uses: helm/chart-testing-action@v2.2.1 - name: Run chart-testing (list-changed) id: list-changed @@ -57,6 +60,10 @@ jobs: - name: Create k8s Kind Cluster uses: helm/kind-action@v1.2.0 if: steps.list-changed.outputs.changed == 'true' + with: + version: v0.14.0 + cluster_name: kind-cluster-k8s-${{ matrix.k8s-version }} + node_image: kindest/node:v${{ matrix.k8s-version }} - name: Run chart-testing (install) run: ct install --config .github/ct/config.yaml diff --git a/charts/hapi-fhir-jpaserver/Chart.lock b/charts/hapi-fhir-jpaserver/Chart.lock index bfb87acb260..e8c97e8edcc 100644 --- a/charts/hapi-fhir-jpaserver/Chart.lock +++ b/charts/hapi-fhir-jpaserver/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 11.1.19 -digest: sha256:5bb38230bfa62c63547851e6f46f66a61441a4a4f18e3689827546277e34d192 -generated: "2022-04-08T21:55:34.6868891+02:00" + version: 11.6.2 +digest: sha256:1b96efc47b5dbe28bf34bcb694697325f3d2755a39ce2f1c371b2c9de9fac9d3 +generated: "2022-06-03T11:48:19.1684784+02:00" diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index 3cb702b205b..9cebc38656e 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -7,9 +7,11 @@ sources: - https://github.com/hapifhir/hapi-fhir-jpaserver-starter dependencies: - name: postgresql - version: 11.1.19 + version: 11.6.2 repository: https://charts.bitnami.com/bitnami condition: postgresql.enabled +appVersion: v6.0.1 +version: 0.9.0 annotations: artifacthub.io/license: Apache-2.0 artifacthub.io/changes: | @@ -17,13 +19,27 @@ annotations: # added, changed, deprecated, removed, fixed, and security. - kind: changed description: | - updated HAPI FHIR starter image to 5.7.0 + BREAKING CHANGE: updated HAPI FHIR starter image to v6.0.1. + See for all application changes. - kind: changed description: | - BREAKING CHANGE: updated included PostgreSQL-subchart to v11 + updated included PostgreSQL-subchart to v11.6.2 + - kind: fixed + description: | + use a fixed image for the wait-for-database container (docker.io/bitnami/postgresql:14.3.0-debian-10-r20) + instead of relying on the PostgreSQL sub-chart values + - kind: changed + description: | + expose actuator/metrics endpoint on a separate port (8081) + - kind: added + description: | + support for monitoring metrics using ServiceMonitor CRDs - kind: changed description: | - BREAKING CHANGE: removed ability to override the image flavor. - The one based on distroless is now the new default. -appVersion: v5.7.0 -version: 0.8.0 + switched liveness and readiness probes to Spring Boot actuator endpoints + - kind: changed + description: | + BREAKING CHANGE: removed included `NetworkPolicy`, which is subject to more thorough rework + - kind: added + description: | + allow configuring `topologySpreadConstraints` for the deployment diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index 288e2ce517c..20d0d6f9410 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -1,6 +1,6 @@ # HAPI FHIR JPA Server Starter Helm Chart -![Version: 0.8.0](https://img.shields.io/badge/Version-0.8.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v5.7.0](https://img.shields.io/badge/AppVersion-v5.7.0-informational?style=flat-square) +![Version: 0.9.0](https://img.shields.io/badge/Version-0.9.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v6.0.1](https://img.shields.io/badge/AppVersion-v6.0.1-informational?style=flat-square) This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment. @@ -40,10 +40,15 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | ingress.hosts[0].pathType | string | `"ImplementationSpecific"` | | | ingress.hosts[0].paths[0] | string | `"/"` | | | ingress.tls | list | `[]` | ingress TLS config | +| livenessProbe.failureThreshold | int | `5` | | +| livenessProbe.initialDelaySeconds | int | `30` | | +| livenessProbe.periodSeconds | int | `20` | | +| livenessProbe.successThreshold | int | `1` | | +| livenessProbe.timeoutSeconds | int | `30` | | +| metrics.service.port | int | `8081` | | +| metrics.serviceMonitor.additionalLabels | object | `{}` | additional labels to apply to the ServiceMonitor object, e.g. `release: prometheus` | +| metrics.serviceMonitor.enabled | bool | `false` | if enabled, creates a ServiceMonitor instance for Prometheus Operator-based monitoring | | nameOverride | string | `""` | override the chart name | -| networkPolicy.allowedFrom | list | `[]` | Additional allowed NetworkPolicyPeer specs Evaluated as a template so you could do: Example: allowedFrom: - podSelector: matchLabels: app.kubernetes.io/name: {{ $.Release.Name }} | -| networkPolicy.enabled | bool | `false` | enable NetworkPolicy | -| networkPolicy.explicitNamespacesSelector | object | `{}` | a Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed | | nodeSelector | object | `{}` | node selector for the pod | | podAnnotations | object | `{}` | annotations applied to the server pod | | podDisruptionBudget.enabled | bool | `false` | Enable PodDisruptionBudget for the server pods. uses policy/v1/PodDisruptionBudget thus requiring k8s 1.21+ | @@ -75,6 +80,7 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | startupProbe.successThreshold | int | `1` | | | startupProbe.timeoutSeconds | int | `30` | | | tolerations | list | `[]` | pod tolerations | +| topologySpreadConstraints | list | `[]` | pod topology spread configuration see: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#api | ## Development @@ -89,4 +95,4 @@ INFO[2021-11-20T12:38:04Z] Generating README Documentation for chart /usr/src/ap ``` ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.5.0](https://github.com/norwoodj/helm-docs/releases/v1.5.0) +Autogenerated from chart metadata using [helm-docs v1.9.1](https://github.com/norwoodj/helm-docs/releases/v1.9.1) diff --git a/charts/hapi-fhir-jpaserver/templates/deployment.yaml b/charts/hapi-fhir-jpaserver/templates/deployment.yaml index 187ee9d2816..741eb71add2 100644 --- a/charts/hapi-fhir-jpaserver/templates/deployment.yaml +++ b/charts/hapi-fhir-jpaserver/templates/deployment.yaml @@ -30,7 +30,7 @@ spec: {{- toYaml .Values.podSecurityContext | nindent 8 }} initContainers: - name: wait-for-db-to-be-ready - image: "{{ .Values.postgresql.image.registry }}/{{ .Values.postgresql.image.repository }}:{{ .Values.postgresql.image.tag }}" + image: docker.io/bitnami/postgresql:14.3.0-debian-10-r20 imagePullPolicy: IfNotPresent securityContext: allowPrivilegeEscalation: false @@ -66,9 +66,23 @@ spec: - name: http containerPort: 8080 protocol: TCP + - name: metrics + containerPort: 8081 + protocol: TCP + startupProbe: + httpGet: + path: /readyz + port: http + {{- with .Values.startupProbe }} + initialDelaySeconds: {{ .initialDelaySeconds }} + periodSeconds: {{ .periodSeconds }} + timeoutSeconds: {{ .timeoutSeconds }} + successThreshold: {{ .successThreshold }} + failureThreshold: {{ .failureThreshold }} + {{- end }} readinessProbe: httpGet: - path: / + path: /readyz port: http {{- with .Values.readinessProbe }} initialDelaySeconds: {{ .initialDelaySeconds }} @@ -77,11 +91,11 @@ spec: successThreshold: {{ .successThreshold }} failureThreshold: {{ .failureThreshold }} {{- end }} - startupProbe: + livenessProbe: httpGet: - path: /fhir/metadata + path: /livez port: http - {{- with .Values.startupProbe }} + {{- with .Values.livenessProbe }} initialDelaySeconds: {{ .initialDelaySeconds }} periodSeconds: {{ .periodSeconds }} timeoutSeconds: {{ .timeoutSeconds }} @@ -106,6 +120,10 @@ spec: value: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect - name: HAPI_FHIR_USE_APACHE_ADDRESS_STRATEGY value: "true" + - name: MANAGEMENT_ENDPOINT_HEALTH_PROBES_ADD_ADDITIONAL_PATHS + value: "true" + - name: MANAGEMENT_SERVER_PORT + value: "8081" {{- if .Values.extraEnv }} {{ toYaml .Values.extraEnv | nindent 12 }} {{- end }} @@ -126,6 +144,10 @@ spec: tolerations: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} volumes: - name: tmp-volume emptyDir: {} diff --git a/charts/hapi-fhir-jpaserver/templates/networkpolicy.yaml b/charts/hapi-fhir-jpaserver/templates/networkpolicy.yaml deleted file mode 100644 index d051950e0e1..00000000000 --- a/charts/hapi-fhir-jpaserver/templates/networkpolicy.yaml +++ /dev/null @@ -1,27 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -kind: NetworkPolicy -apiVersion: networking.k8s.io/v1 -metadata: - name: {{ include "hapi-fhir-jpaserver.fullname" . }} - labels: - {{- include "hapi-fhir-jpaserver.labels" . | nindent 4 }} -spec: - podSelector: - matchLabels: - {{- include "hapi-fhir-jpaserver.selectorLabels" . | nindent 6 }} - ingress: - # Allow inbound connections from pods with the "hapi-fhir-jpaserver-client: true" label - - ports: - - port: http - from: - - podSelector: - matchLabels: - {{ include "hapi-fhir-jpaserver.fullname" . }}-client: "true" - {{- with .Values.networkPolicy.explicitNamespacesSelector }} - namespaceSelector: - {{ toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.networkPolicy.allowedFrom }} - {{ tpl (toYaml .) $ | nindent 8 }} - {{- end }} -{{- end }} diff --git a/charts/hapi-fhir-jpaserver/templates/service.yaml b/charts/hapi-fhir-jpaserver/templates/service.yaml index 90a05a291e8..d7ecaa5d25e 100644 --- a/charts/hapi-fhir-jpaserver/templates/service.yaml +++ b/charts/hapi-fhir-jpaserver/templates/service.yaml @@ -11,5 +11,9 @@ spec: targetPort: http protocol: TCP name: http + - port: {{ .Values.metrics.service.port }} + targetPort: metrics + protocol: TCP + name: metrics selector: {{- include "hapi-fhir-jpaserver.selectorLabels" . | nindent 4 }} diff --git a/charts/hapi-fhir-jpaserver/templates/servicemonitor.yaml b/charts/hapi-fhir-jpaserver/templates/servicemonitor.yaml new file mode 100644 index 00000000000..e161feeb5c9 --- /dev/null +++ b/charts/hapi-fhir-jpaserver/templates/servicemonitor.yaml @@ -0,0 +1,30 @@ +{{- if .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "hapi-fhir-jpaserver.fullname" . }} + {{- if .Values.metrics.serviceMonitor.namespace }} + namespace: {{ .Values.metrics.serviceMonitor.namespace }} + {{- end }} + labels: + {{- include "hapi-fhir-jpaserver.labels" . | nindent 4 }} + {{- if .Values.metrics.serviceMonitor.additionalLabels }} + {{- toYaml .Values.metrics.serviceMonitor.additionalLabels | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: metrics + path: /actuator/prometheus + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + {{- include "hapi-fhir-jpaserver.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index e89a5c4dd72..55863c89d23 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -88,6 +88,18 @@ tolerations: [] # -- pod affinity affinity: {} +# -- pod topology spread configuration +# see: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#api +topologySpreadConstraints: + [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: ScheduleAnyway + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: hapi-fhir-jpaserver + # app.kubernetes.io/name: hapi-fhir-jpaserver + postgresql: # -- enable an included PostgreSQL DB. # see for details @@ -126,6 +138,13 @@ startupProbe: successThreshold: 1 timeoutSeconds: 30 +livenessProbe: + failureThreshold: 5 + initialDelaySeconds: 30 + periodSeconds: 20 + successThreshold: 1 + timeoutSeconds: 30 + externalDatabase: # -- external database host used with `postgresql.enabled=false` host: localhost @@ -142,26 +161,6 @@ externalDatabase: # -- database name database: fhir -networkPolicy: - # -- enable NetworkPolicy - enabled: false - # -- a Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed - explicitNamespacesSelector: - {} - # matchLabels: - # team: one - # test: foo - - # -- Additional allowed NetworkPolicyPeer specs - # Evaluated as a template so you could do: - # - # Example: - # allowedFrom: - # - podSelector: - # matchLabels: - # app.kubernetes.io/name: {{ $.Release.Name }} - allowedFrom: [] - # -- extra environment variables to set on the server container extraEnv: [] @@ -176,3 +175,15 @@ podDisruptionBudget: minAvailable: 1 # -- maximum unavailable instances maxUnavailable: "" + +metrics: + serviceMonitor: + # -- if enabled, creates a ServiceMonitor instance for Prometheus Operator-based monitoring + enabled: false + # -- additional labels to apply to the ServiceMonitor object, e.g. `release: prometheus` + additionalLabels: {} + # namespace: monitoring + # interval: 30s + # scrapeTimeout: 10s + service: + port: 8081 From 41ba07a5e5fcdbcee05b23f4d58c3c1d115b2052 Mon Sep 17 00:00:00 2001 From: Ibrohim Kholilul Islam Date: Fri, 17 Jun 2022 18:15:58 +0000 Subject: [PATCH 090/192] add BinaryAccessProvider to BaseJpaRestfulServer --- .../java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 4 ++++ 1 file changed, 4 insertions(+) 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 c7ec35b34a5..0043609ae68 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -11,6 +11,7 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor; +import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider; import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider; import ca.uhn.fhir.jpa.graphql.GraphQLProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; @@ -86,6 +87,8 @@ public class BaseJpaRestfulServer extends RestfulServer { @Autowired BinaryStorageInterceptor binaryStorageInterceptor; @Autowired + Optional binaryAccessProvider; + @Autowired IPackageInstallerSvc packageInstallerSvc; @Autowired AppProperties appProperties; @@ -318,6 +321,7 @@ protected void initialize() throws ServletException { // Binary Storage if (appProperties.getBinary_storage_enabled()) { + registerProvider(binaryAccessProvider.get()); getInterceptorService().registerInterceptor(binaryStorageInterceptor); } From a026b1f390ab5c4cefc00ccd22cd5928206924ff Mon Sep 17 00:00:00 2001 From: Ibrohim Kholilul Islam Date: Thu, 23 Jun 2022 12:00:55 +0700 Subject: [PATCH 091/192] Update src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java Co-authored-by: Kevin Dougan SmileCDR <72025369+KevinDougan-SmileCDR@users.noreply.github.com> --- src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0043609ae68..6ec6bc1e5fd 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -320,7 +320,7 @@ protected void initialize() throws ServletException { } // Binary Storage - if (appProperties.getBinary_storage_enabled()) { + if (appProperties.getBinary_storage_enabled() && binaryAccessProvider.isPresent()) { registerProvider(binaryAccessProvider.get()); getInterceptorService().registerInterceptor(binaryStorageInterceptor); } From d6b5bc3cd22c018f283a2699ab77ec643cd1ccba Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Mon, 4 Jul 2022 14:46:15 +0200 Subject: [PATCH 092/192] Applying fix from upstream for h2 Binaries This issue is already fixed upstream. Can be removed with next hapi version upgrade. https://github.com/hapifhir/hapi-fhir/pull/3676 --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 9cbbfab03e8..1f33108199b 100644 --- a/pom.xml +++ b/pom.xml @@ -197,6 +197,8 @@ com.h2database h2 + + 2.1.212 From bea4d471aaa1d4370ed79bb3615054c2be5b18c3 Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Mon, 4 Jul 2022 14:54:49 +0200 Subject: [PATCH 093/192] removed wrong and duplicated config entry `daoconfig_client_id_strategy`does not resolve and is a duplicate of `client_id_strategy` --- src/main/resources/application.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 9492327dc52..8a18d87bb98 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -102,7 +102,6 @@ hapi: # enforce_referential_integrity_on_write: false # etag_support_enabled: true # expunge_enabled: true - # daoconfig_client_id_strategy: null # client_id_strategy: ALPHANUMERIC # fhirpath_interceptor_enabled: false # filter_search_enabled: true From cd8b06b263a9d18ca820fb09860e51a6029e16eb Mon Sep 17 00:00:00 2001 From: chgl Date: Mon, 4 Jul 2022 19:44:20 +0200 Subject: [PATCH 094/192] Added OpenTelemetry Java Agent JAR to container image (#391) Closes #387 --- Dockerfile | 9 ++++++++- README.md | 25 +++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3a8ea7a44f1..4eba966f8e3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,9 @@ FROM maven:3.8-openjdk-17-slim as build-hapi WORKDIR /tmp/hapi-fhir-jpaserver-starter +ARG OPENTELEMETRY_JAVA_AGENT_VERSION=1.15.0 +RUN curl -LSsO https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${OPENTELEMETRY_JAVA_AGENT_VERSION}/opentelemetry-javaagent.jar + COPY pom.xml . COPY server.xml . RUN mvn -ntp dependency:go-offline @@ -29,15 +32,19 @@ USER 1001 COPY --chown=1001:1001 catalina.properties /opt/bitnami/tomcat/conf/catalina.properties COPY --chown=1001:1001 server.xml /opt/bitnami/tomcat/conf/server.xml COPY --from=build-hapi --chown=1001:1001 /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /opt/bitnami/tomcat/webapps_default/ROOT.war +COPY --from=build-hapi --chown=1001:1001 /tmp/hapi-fhir-jpaserver-starter/opentelemetry-javaagent.jar /app ENV ALLOW_EMPTY_PASSWORD=yes ########### distroless brings focus on security and runs on plain spring boot - this is the default image FROM gcr.io/distroless/java17:nonroot as default -COPY --chown=nonroot:nonroot --from=build-distroless /app /app # 65532 is the nonroot user's uid # used here instead of the name to allow Kubernetes to easily detect that the container # is running as a non-root (uid != 0) user. USER 65532:65532 WORKDIR /app + +COPY --chown=nonroot:nonroot --from=build-distroless /app /app +COPY --chown=nonroot:nonroot --from=build-hapi /tmp/hapi-fhir-jpaserver-starter/opentelemetry-javaagent.jar /app + CMD ["/app/main.war"] diff --git a/README.md b/README.md index 781429da4a1..da7d46efb34 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ Also, make sure you are not setting the Hibernate dialect explicitly, in other w hibernate.dialect: {some none MySQL dialect} ``` -On some systems, it might be necessary to override hibernate's default naming strategy. The naming strategy must be set using spring.jpa.hibernate.physical_naming_strategy. +On some systems, it might be necessary to override hibernate's default naming strategy. The naming strategy must be set using spring.jpa.hibernate.physical_naming_strategy. ```yaml spring: @@ -239,8 +239,8 @@ spring: Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. -NOTE: MS SQL Server by default uses a case-insensitive codepage. This will cause errors with some operations - such as when expanding case-sensitive valuesets (UCUM) as there are unique indexes defined on the terminology tables for codes. -It is recommended to deploy a case-sensitive database prior to running HAPI FHIR when using MS SQL Server to avoid these and potentially other issues. +NOTE: MS SQL Server by default uses a case-insensitive codepage. This will cause errors with some operations - such as when expanding case-sensitive valuesets (UCUM) as there are unique indexes defined on the terminology tables for codes. +It is recommended to deploy a case-sensitive database prior to running HAPI FHIR when using MS SQL Server to avoid these and potentially other issues. ## Customizing The Web Testpage UI @@ -390,7 +390,7 @@ Set `hapi.fhir.store_resource_in_lucene_index_enabled` in the [application.yaml] ## Changing cached search results time It is possible to change the cached search results time. The option `reuse_cached_search_results_millis` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) is 6000 miliseconds by default. -Set `reuse_cached_search_results_millis: -1` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file to ignore the cache time every search. +Set `reuse_cached_search_results_millis: -1` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file to ignore the cache time every search. ## Build the distroless variant of the image (for lower footprint and improved security) @@ -409,3 +409,20 @@ see the `-distroless` suffix in the image tags. To add a custom operation, refer to the documentation in the core hapi-fhir libraries [here](https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations_operations.html). Within `hapi-fhir-jpaserver-starter`, create a generic class (that does not extend or implement any classes or interfaces), add the `@Operation` as a method within the generic class, and then register the class as a provider using `RestfulServer.registerProvider()`. + +## Enable OpenTelemetry auto-instrumentation + +The container image includes the [OpenTelemetry Java auto-instrumentation](https://github.com/open-telemetry/opentelemetry-java-instrumentation) +Java agent JAR which can be used to export telemetry data for the HAPI FHIR JPA Server. You can enable it by specifying the `-javaagent` flag, +for example by overriding the `JAVA_TOOL_OPTIONS` environment variable: + +```sh +docker run --rm -it -p 8080:8080 \ + -e JAVA_TOOL_OPTIONS="-javaagent:/app/opentelemetry-javaagent.jar" \ + -e OTEL_TRACES_EXPORTER="jaeger" \ + -e OTEL_SERVICE_NAME="hapi-fhir-server" \ + -e OTEL_EXPORTER_JAEGER_ENDPOINT="http://jaeger:14250" \ + docker.io/hapiproject/hapi:latest +``` + +You can configure the agent using environment variables or Java system properties, see for details. From 6ad29890f0e85e240e207a6c7183c8109fd4fe87 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Tue, 5 Jul 2022 14:27:05 -0400 Subject: [PATCH 095/192] changes to pom.xml to enable publishing --- pom.xml | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 1f33108199b..6bf149e74e7 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,7 @@ hapi-fhir-jpaserver-starter + war 11 @@ -27,8 +28,6 @@ 3.8.3
- war - HAPI FHIR JPA Server - Starter Project @@ -353,7 +352,6 @@ test
- @@ -588,5 +586,61 @@
+ + ossrh-repo + + false + + deployToSonatype + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.13 + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + ${gpg.keyname} + ${gpg.keyname} + + --pinentry-mode + loopback + + + + + + + + From c9dd6054fa253d3769859942e3f3ac4e71463f20 Mon Sep 17 00:00:00 2001 From: chgl Date: Fri, 8 Jul 2022 00:18:49 +0200 Subject: [PATCH 096/192] fixed directory of the .war in tomcat-based image --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4eba966f8e3..464281e8673 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,6 @@ RUN mkdir /app && cp /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /app/main. FROM bitnami/tomcat:9.0 as tomcat RUN rm -rf /opt/bitnami/tomcat/webapps/ROOT && \ - rm -rf /opt/bitnami/tomcat/webapps_default/ROOT && \ mkdir -p /opt/bitnami/hapi/data/hapi/lucenefiles && \ chmod 775 /opt/bitnami/hapi/data/hapi/lucenefiles @@ -31,7 +30,7 @@ USER 1001 COPY --chown=1001:1001 catalina.properties /opt/bitnami/tomcat/conf/catalina.properties COPY --chown=1001:1001 server.xml /opt/bitnami/tomcat/conf/server.xml -COPY --from=build-hapi --chown=1001:1001 /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /opt/bitnami/tomcat/webapps_default/ROOT.war +COPY --from=build-hapi --chown=1001:1001 /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /opt/bitnami/tomcat/webapps/ROOT.war COPY --from=build-hapi --chown=1001:1001 /tmp/hapi-fhir-jpaserver-starter/opentelemetry-javaagent.jar /app ENV ALLOW_EMPTY_PASSWORD=yes From d148f458e0e07dad1ee2ce55c79b07bc3f612aad Mon Sep 17 00:00:00 2001 From: Arbaaz Muslim Date: Tue, 9 Aug 2022 16:31:49 -0700 Subject: [PATCH 097/192] bulk data instrumentation included --- src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java | 9 +++++++++ .../ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 8 ++++++++ src/main/resources/application.yaml | 2 ++ 3 files changed, 19 insertions(+) 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 af8be7c44c3..27bb715c116 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -46,6 +46,7 @@ public class AppProperties { private Boolean graphql_enabled = false; private Boolean binary_storage_enabled = false; private Boolean bulk_export_enabled = false; + private Boolean bulk_import_enabled = false; private Boolean default_pretty_print = true; private Integer default_page_size = 20; private Integer max_binary_size = null; @@ -402,6 +403,14 @@ public void setBulk_export_enabled(Boolean bulk_export_enabled) { this.bulk_export_enabled = bulk_export_enabled; } + public Boolean getBulk_import_enabled() { + return bulk_import_enabled; + } + + public void setBulk_import_enabled(Boolean bulk_import_enabled) { + this.bulk_import_enabled = bulk_import_enabled; + } + public EncodingEnum getDefault_encoding() { return default_encoding; } 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 6ec6bc1e5fd..5a457026936 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.starter; +import ca.uhn.fhir.batch2.jobs.imprt.BulkDataImportProvider; import ca.uhn.fhir.batch2.jobs.reindex.ReindexProvider; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; @@ -78,6 +79,8 @@ public class BaseJpaRestfulServer extends RestfulServer { @Autowired BulkDataExportProvider bulkDataExportProvider; @Autowired + BulkDataImportProvider bulkDataImportProvider; + @Autowired PartitionManagementProvider partitionManagementProvider; @Autowired @@ -364,6 +367,11 @@ protected void initialize() throws ServletException { registerProvider(bulkDataExportProvider); } + //Bulk Import + if (appProperties.getBulk_import_enabled()) { + registerProvider(bulkDataImportProvider); + } + // valueSet Operations i.e $expand registerProvider(myValueSetOperationProvider); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 8a18d87bb98..c8222637643 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -96,6 +96,8 @@ hapi: ### !!Extended Lucene/Elasticsearch Indexing is still a experimental feature, expect some features (e.g. _total=accurate) to not work as expected!! ### more information here: https://hapifhir.io/hapi-fhir/docs/server_jpa/elastic.html advanced_lucene_indexing: false + bulk_export_enabled: true + bulk_import_enabled: true # enforce_referential_integrity_on_delete: false # This is an experimental feature, and does not fully support _total and other FHIR features. # enforce_referential_integrity_on_delete: false From c617f4e395957b72c4eba9cbfe58843436705307 Mon Sep 17 00:00:00 2001 From: Arbaaz Muslim Date: Tue, 9 Aug 2022 16:48:22 -0700 Subject: [PATCH 098/192] bulk data instrumentation turned off by default --- src/main/resources/application.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index c8222637643..cb9c9a3bd8b 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -96,8 +96,8 @@ hapi: ### !!Extended Lucene/Elasticsearch Indexing is still a experimental feature, expect some features (e.g. _total=accurate) to not work as expected!! ### more information here: https://hapifhir.io/hapi-fhir/docs/server_jpa/elastic.html advanced_lucene_indexing: false - bulk_export_enabled: true - bulk_import_enabled: true + bulk_export_enabled: false + bulk_import_enabled: false # enforce_referential_integrity_on_delete: false # This is an experimental feature, and does not fully support _total and other FHIR features. # enforce_referential_integrity_on_delete: false From 1753272122665df6b2b25dc99944be44f275abdb Mon Sep 17 00:00:00 2001 From: chgl Date: Mon, 15 Aug 2022 01:20:49 +0200 Subject: [PATCH 099/192] updated opentelemetry-java-instrumentation JAR to 1.16.0 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 464281e8673..1eb0a2b3e0f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM maven:3.8-openjdk-17-slim as build-hapi WORKDIR /tmp/hapi-fhir-jpaserver-starter -ARG OPENTELEMETRY_JAVA_AGENT_VERSION=1.15.0 +ARG OPENTELEMETRY_JAVA_AGENT_VERSION=1.16.0 RUN curl -LSsO https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${OPENTELEMETRY_JAVA_AGENT_VERSION}/opentelemetry-javaagent.jar COPY pom.xml . From ee74116e6b4b73b84da374eca01892d30fb410ef Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Thu, 18 Aug 2022 21:05:36 +0200 Subject: [PATCH 100/192] Better support for ARM java17 regular doesn't have ARM, java17-debian11 does --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1eb0a2b3e0f..82af8df9a31 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,7 +36,7 @@ COPY --from=build-hapi --chown=1001:1001 /tmp/hapi-fhir-jpaserver-starter/opente ENV ALLOW_EMPTY_PASSWORD=yes ########### distroless brings focus on security and runs on plain spring boot - this is the default image -FROM gcr.io/distroless/java17:nonroot as default +FROM gcr.io/distroless/java17-debian11:nonroot as default # 65532 is the nonroot user's uid # used here instead of the name to allow Kubernetes to easily detect that the container # is running as a non-root (uid != 0) user. From 956cfb171dd8562d60ac49623e05338420d32264 Mon Sep 17 00:00:00 2001 From: chgl Date: Mon, 22 Aug 2022 18:15:34 +0200 Subject: [PATCH 101/192] Updated Otel Java agent to 1.17.0 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1eb0a2b3e0f..af067ebd1be 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM maven:3.8-openjdk-17-slim as build-hapi WORKDIR /tmp/hapi-fhir-jpaserver-starter -ARG OPENTELEMETRY_JAVA_AGENT_VERSION=1.16.0 +ARG OPENTELEMETRY_JAVA_AGENT_VERSION=1.17.0 RUN curl -LSsO https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${OPENTELEMETRY_JAVA_AGENT_VERSION}/opentelemetry-javaagent.jar COPY pom.xml . From d059954c5f40d59bc0553539e678fdc892526ddb Mon Sep 17 00:00:00 2001 From: chgl Date: Mon, 22 Aug 2022 18:16:24 +0200 Subject: [PATCH 102/192] Updated hapi-fhir to 6.1.0 --- README.md | 4 ++-- pom.xml | 4 +--- .../jpa/starter/BaseJpaRestfulServer.java | 2 +- .../fhir/jpa/starter/EnvironmentHelper.java | 7 ++++--- .../jpa/starter/FhirServerConfigCommon.java | 2 +- .../fhir/jpa/starter/StarterJpaConfig.java | 19 +++++++++++++++++++ src/main/resources/application.yaml | 2 +- 7 files changed, 29 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index da7d46efb34..c104d2398ff 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,9 @@ In order to use this sample, you should have: - Apache Maven build tool (newest version) ### or - - Docker, as the entire project can be built using multistage docker (with both JDK and maven wrapped in docker) or used directly from [Docker Hub](https://hub.docker.com/repository/docker/hapiproject/hapi) + - Docker, as the entire project can be built using multistage docker (with both JDK and maven wrapped in docker) or used directly from [Docker Hub](https://hub.docker.com/r/hapiproject/hapi) -## Running via [Docker Hub](https://hub.docker.com/repository/docker/hapiproject/hapi) +## Running via [Docker Hub](https://hub.docker.com/r/hapiproject/hapi) Each tagged/released version of `hapi-fhir-jpaserver` is built as a Docker image and published to Docker hub. To run the published Docker image from DockerHub: diff --git a/pom.xml b/pom.xml index 6bf149e74e7..3b2596f6f54 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.0.1 + 6.1.0 hapi-fhir-jpaserver-starter @@ -196,8 +196,6 @@ com.h2database h2 - - 2.1.212 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 5a457026936..4cad6bfd726 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -418,7 +418,7 @@ protected void initialize() throws ServletException { daoConfig.setLastNEnabled(true); } - daoConfig.setStoreResourceInLuceneIndex(appProperties.getStore_resource_in_lucene_index_enabled()); + daoConfig.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled()); daoConfig.getModelConfig().setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); daoConfig.getModelConfig().setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java index 11b612811c1..732705ac521 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java @@ -1,7 +1,7 @@ package ca.uhn.fhir.jpa.starter; import ca.uhn.fhir.jpa.config.HapiFhirLocalContainerEntityManagerFactoryBean; -import ca.uhn.fhir.jpa.search.HapiLuceneAnalysisConfigurer; +import ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers; import ca.uhn.fhir.jpa.search.elastic.ElasticsearchHibernatePropertiesBuilder; import org.apache.lucene.util.Version; import org.hibernate.cfg.AvailableSettings; @@ -71,7 +71,8 @@ public static Properties getHibernateProperties(ConfigurableEnvironment environm if (properties.get(BackendSettings.backendKey(BackendSettings.TYPE)).equals(LuceneBackendSettings.TYPE_NAME)) { properties.putIfAbsent(BackendSettings.backendKey(LuceneIndexSettings.DIRECTORY_TYPE), LocalFileSystemDirectoryProvider.NAME); properties.putIfAbsent(BackendSettings.backendKey(LuceneIndexSettings.DIRECTORY_ROOT), "target/lucenefiles"); - properties.putIfAbsent(BackendSettings.backendKey(LuceneBackendSettings.ANALYSIS_CONFIGURER), HapiLuceneAnalysisConfigurer.class.getName()); + properties.putIfAbsent(BackendSettings.backendKey(LuceneBackendSettings.ANALYSIS_CONFIGURER), + HapiHSearchAnalysisConfigurers.HapiLuceneAnalysisConfigurer.class.getName()); properties.putIfAbsent(BackendSettings.backendKey(LuceneBackendSettings.LUCENE_VERSION), Version.LATEST); } else if (properties.get(BackendSettings.backendKey(BackendSettings.TYPE)).equals(ElasticsearchBackendSettings.TYPE_NAME)) { @@ -188,4 +189,4 @@ private static void addAll(Map aBase, Map aToBeA aBase.put(entry.getKey(), entry.getValue()); } } -} \ No newline at end of file +} 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 15638f5336b..ac80f093b0e 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -122,7 +122,7 @@ public DaoConfig daoConfig(AppProperties appProperties) { } retVal.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); - retVal.setAdvancedLuceneIndexing(appProperties.getAdvanced_lucene_indexing()); + retVal.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing()); retVal.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls())); return retVal; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java index 07fd0282cb5..2acfabd898f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java @@ -10,13 +10,19 @@ import ca.uhn.fhir.jpa.config.util.ValidationSupportConfigUtil; import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl; import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc; +import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDaoJpaImpl; +import ca.uhn.fhir.jpa.dao.search.HSearchSortHelperImpl; +import ca.uhn.fhir.jpa.dao.search.IHSearchSortHelper; import ca.uhn.fhir.jpa.provider.DaoRegistryResourceSupportedSvc; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc; import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl; import ca.uhn.fhir.jpa.util.ResourceCountCache; import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain; +import ca.uhn.fhir.mdm.dao.IMdmLinkDao; import ca.uhn.fhir.rest.api.IResourceSupportedSvc; +import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; + import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport; import org.springframework.batch.core.configuration.annotation.BatchConfigurer; import org.springframework.beans.factory.annotation.Autowired; @@ -106,4 +112,17 @@ public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityM retVal.setEntityManagerFactory(entityManagerFactory); return retVal; } + + @Autowired + private ISearchParamRegistry mySearchParamRegistry; + + @Bean + public IHSearchSortHelper hSearchSortHelper() { + return new HSearchSortHelperImpl(mySearchParamRegistry); + } + + @Bean + public IMdmLinkDao mdmLinkDao(){ + return new MdmLinkDaoJpaImpl(); + } } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index cb9c9a3bd8b..3c0be6675d4 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -42,7 +42,7 @@ spring: ### These settings will enable fulltext search with lucene hibernate.search.enabled: false # hibernate.search.backend.type: lucene - # hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiLuceneAnalysisConfigurer + # hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer # hibernate.search.backend.directory.type: local-filesystem # hibernate.search.backend.directory.root: target/lucenefiles # hibernate.search.backend.lucene_version: lucene_current From 68e64f2f33757a33cb0183be35730f303b90e1ad Mon Sep 17 00:00:00 2001 From: chgl Date: Thu, 25 Aug 2022 02:34:02 +0200 Subject: [PATCH 103/192] Minor Helm chart dependency updates and security improvements --- .github/workflows/chart-test.yaml | 2 +- charts/hapi-fhir-jpaserver/Chart.lock | 6 +-- charts/hapi-fhir-jpaserver/Chart.yaml | 30 +++++------ charts/hapi-fhir-jpaserver/README.md | 11 ++-- .../templates/deployment.yaml | 18 +++---- .../templates/service.yaml | 4 +- .../templates/servicemonitor.yaml | 2 +- .../templates/tests/test-endpoints.yaml | 53 ++++++++++++------- charts/hapi-fhir-jpaserver/values.yaml | 25 ++++++++- 9 files changed, 89 insertions(+), 62 deletions(-) diff --git a/.github/workflows/chart-test.yaml b/.github/workflows/chart-test.yaml index 1d32194682f..f4357fb35cc 100644 --- a/.github/workflows/chart-test.yaml +++ b/.github/workflows/chart-test.yaml @@ -15,7 +15,7 @@ jobs: - name: Install helm-docs working-directory: /tmp env: - HELM_DOCS_URL: https://github.com/norwoodj/helm-docs/releases/download/v1.9.1/helm-docs_1.9.1_Linux_x86_64.tar.gz + HELM_DOCS_URL: https://github.com/norwoodj/helm-docs/releases/download/v1.11.0/helm-docs_1.11.0_Linux_x86_64.tar.gz run: | curl -LSs $HELM_DOCS_URL | tar xz && \ mv ./helm-docs /usr/local/bin/helm-docs && \ diff --git a/charts/hapi-fhir-jpaserver/Chart.lock b/charts/hapi-fhir-jpaserver/Chart.lock index e8c97e8edcc..411bc270ef5 100644 --- a/charts/hapi-fhir-jpaserver/Chart.lock +++ b/charts/hapi-fhir-jpaserver/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 11.6.2 -digest: sha256:1b96efc47b5dbe28bf34bcb694697325f3d2755a39ce2f1c371b2c9de9fac9d3 -generated: "2022-06-03T11:48:19.1684784+02:00" + version: 11.8.1 +digest: sha256:671325f8b3d0b85183fa241190e72705fb124a41254a5db6445bcc105e1ca7ec +generated: "2022-08-25T02:14:58.3432514+02:00" diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index 9cebc38656e..e172526f43d 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -7,11 +7,11 @@ sources: - https://github.com/hapifhir/hapi-fhir-jpaserver-starter dependencies: - name: postgresql - version: 11.6.2 + version: 11.8.1 repository: https://charts.bitnami.com/bitnami condition: postgresql.enabled -appVersion: v6.0.1 -version: 0.9.0 +appVersion: v6.x +version: 0.10.0 annotations: artifacthub.io/license: Apache-2.0 artifacthub.io/changes: | @@ -19,27 +19,21 @@ annotations: # added, changed, deprecated, removed, fixed, and security. - kind: changed description: | - BREAKING CHANGE: updated HAPI FHIR starter image to v6.0.1. - See for all application changes. + updated included PostgreSQL-subchart to v11.8.1. + Fixes `coalesce.go:220: warning: cannot overwrite table with non table for fhirserver.postgresql.primary.topologySpreadConstraints (map[])` warning - kind: changed description: | - updated included PostgreSQL-subchart to v11.6.2 - - kind: fixed + set `securityContext.seccompProfile.type=RuntimeDefault` for included PostgreSQL as well as all `initContainer` and Helm + test pods to comply with the "restricted" Pod Security Standard: + - kind: changed description: | - use a fixed image for the wait-for-database container (docker.io/bitnami/postgresql:14.3.0-debian-10-r20) - instead of relying on the PostgreSQL sub-chart values + use curl as the image for running Helm test pods - kind: changed description: | - expose actuator/metrics endpoint on a separate port (8081) + renamed `metrics` port to `http-metrics` for istio compliant naming - kind: added description: | - support for monitoring metrics using ServiceMonitor CRDs - - kind: changed - description: | - switched liveness and readiness probes to Spring Boot actuator endpoints + Helm test job to test metrics endpoint - kind: changed description: | - BREAKING CHANGE: removed included `NetworkPolicy`, which is subject to more thorough rework - - kind: added - description: | - allow configuring `topologySpreadConstraints` for the deployment + use full digest instead of just a tag for the server image reference diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index 20d0d6f9410..9b72dc5c7f5 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -1,6 +1,6 @@ # HAPI FHIR JPA Server Starter Helm Chart -![Version: 0.9.0](https://img.shields.io/badge/Version-0.9.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v6.0.1](https://img.shields.io/badge/AppVersion-v6.0.1-informational?style=flat-square) +![Version: 0.10.0](https://img.shields.io/badge/Version-0.10.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v6.x](https://img.shields.io/badge/AppVersion-v6.x-informational?style=flat-square) This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment. @@ -32,7 +32,7 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | image.pullPolicy | string | `"IfNotPresent"` | image pullPolicy to use | | image.registry | string | `"docker.io"` | registry where the HAPI FHIR server image is hosted | | image.repository | string | `"hapiproject/hapi"` | the path inside the repository | -| image.tag | string | `""` | defaults to `Chart.appVersion`. As of v5.7.0, this is the `distroless` flavor | +| image.tag | string | `"v6.0.1@sha256:63c98d8be3dadc77b47dca3115490f22bf99512f363f779f7bbcb42f569aeac3"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. | | imagePullSecrets | list | `[]` | image pull secrets to use when pulling the image | | ingress.annotations | object | `{}` | provide any additional annotations which may be required. Evaluated as a template. | | ingress.enabled | bool | `false` | whether to create an Ingress to expose the FHIR server HTTP endpoint | @@ -60,6 +60,8 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | postgresql.enabled | bool | `true` | enable an included PostgreSQL DB. see for details if set to `false`, the values under `externalDatabase` are used | | postgresql.primary.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | | | postgresql.primary.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | | +| postgresql.primary.containerSecurityContext.runAsNonRoot | bool | `true` | | +| postgresql.primary.containerSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | | | readinessProbe.failureThreshold | int | `5` | | | readinessProbe.initialDelaySeconds | int | `30` | | | readinessProbe.periodSeconds | int | `20` | | @@ -69,9 +71,12 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | resources | object | `{}` | configure the FHIR server's resource requests and limits | | securityContext.allowPrivilegeEscalation | bool | `false` | | | securityContext.capabilities.drop[0] | string | `"ALL"` | | +| securityContext.privileged | bool | `false` | | | securityContext.readOnlyRootFilesystem | bool | `true` | | +| securityContext.runAsGroup | int | `65532` | | | securityContext.runAsNonRoot | bool | `true` | | | securityContext.runAsUser | int | `65532` | | +| securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | | service.port | int | `8080` | port where the server will be exposed at | | service.type | string | `"ClusterIP"` | service type | | startupProbe.failureThreshold | int | `10` | | @@ -95,4 +100,4 @@ INFO[2021-11-20T12:38:04Z] Generating README Documentation for chart /usr/src/ap ``` ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.9.1](https://github.com/norwoodj/helm-docs/releases/v1.9.1) +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/charts/hapi-fhir-jpaserver/templates/deployment.yaml b/charts/hapi-fhir-jpaserver/templates/deployment.yaml index 741eb71add2..fa88745b016 100644 --- a/charts/hapi-fhir-jpaserver/templates/deployment.yaml +++ b/charts/hapi-fhir-jpaserver/templates/deployment.yaml @@ -30,18 +30,12 @@ spec: {{- toYaml .Values.podSecurityContext | nindent 8 }} initContainers: - name: wait-for-db-to-be-ready - image: docker.io/bitnami/postgresql:14.3.0-debian-10-r20 + image: docker.io/bitnami/postgresql:14.5.0@sha256:4355265e33e9c2a786aa145884d4b36ffd4c41c516b35d60df0b7495141ec738 imagePullPolicy: IfNotPresent + {{- with .Values.restrictedContainerSecurityContext }} securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - privileged: false - capabilities: - drop: - - ALL - runAsNonRoot: true - runAsUser: 1001 - runAsGroup: 1001 + {{- toYaml . | nindent 12 }} + {{- end }} env: - name: PGHOST value: "{{ include "hapi-fhir-jpaserver.database.host" . }}" @@ -60,13 +54,13 @@ spec: - name: {{ .Chart.Name }} securityContext: {{- toYaml .Values.securityContext | nindent 12 }} - image: {{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }} + image: {{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }} imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - name: http containerPort: 8080 protocol: TCP - - name: metrics + - name: http-metrics containerPort: 8081 protocol: TCP startupProbe: diff --git a/charts/hapi-fhir-jpaserver/templates/service.yaml b/charts/hapi-fhir-jpaserver/templates/service.yaml index d7ecaa5d25e..b18b1e7f382 100644 --- a/charts/hapi-fhir-jpaserver/templates/service.yaml +++ b/charts/hapi-fhir-jpaserver/templates/service.yaml @@ -12,8 +12,8 @@ spec: protocol: TCP name: http - port: {{ .Values.metrics.service.port }} - targetPort: metrics + targetPort: http-metrics protocol: TCP - name: metrics + name: http-metrics selector: {{- include "hapi-fhir-jpaserver.selectorLabels" . | nindent 4 }} diff --git a/charts/hapi-fhir-jpaserver/templates/servicemonitor.yaml b/charts/hapi-fhir-jpaserver/templates/servicemonitor.yaml index e161feeb5c9..8bfad8b61e5 100644 --- a/charts/hapi-fhir-jpaserver/templates/servicemonitor.yaml +++ b/charts/hapi-fhir-jpaserver/templates/servicemonitor.yaml @@ -13,7 +13,7 @@ metadata: {{- end }} spec: endpoints: - - port: metrics + - port: http-metrics path: /actuator/prometheus {{- if .Values.metrics.serviceMonitor.interval }} interval: {{ .Values.metrics.serviceMonitor.interval }} diff --git a/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml index 911f59d6ae3..30aab5aba93 100644 --- a/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml +++ b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml @@ -11,17 +11,13 @@ spec: restartPolicy: Never containers: - name: test-metadata-endpoint - image: busybox:1 - command: ['wget', '-O', '-'] - args: ['http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/metadata'] + image: docker.io/curlimages/curl:7.84.0@sha256:5a2a25d96aa941ea2fc47acc50122f7c3d007399a075df61a82d6d2c3a567a2b + command: ["curl", "--fail-with-body"] + args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/metadata?_summary=true"] + {{- with .Values.restrictedContainerSecurityContext }} securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsUser: 22222 - runAsNonRoot: true + {{- toYaml . | nindent 8 }} + {{- end }} resources: limits: cpu: 100m @@ -36,17 +32,34 @@ spec: exec: command: ["true"] - name: test-patient-endpoint - image: busybox:1 - command: ['wget', '-O', '-'] - args: ['http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/Patient?_count=1'] + image: docker.io/curlimages/curl:7.84.0@sha256:5a2a25d96aa941ea2fc47acc50122f7c3d007399a075df61a82d6d2c3a567a2b + command: ["curl", "--fail-with-body"] + args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/Patient?_count=1&_summary=true"] + {{- with .Values.restrictedContainerSecurityContext }} securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsUser: 22222 - runAsNonRoot: true + {{- toYaml . | nindent 8 }} + {{- end }} + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + livenessProbe: + exec: + command: ["true"] + readinessProbe: + exec: + command: ["true"] + - name: test-metrics-endpoint + image: docker.io/curlimages/curl:7.84.0@sha256:5a2a25d96aa941ea2fc47acc50122f7c3d007399a075df61a82d6d2c3a567a2b + command: ["curl", "--fail-with-body"] + args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.metrics.service.port }}/actuator/prometheus"] + {{- with .Values.restrictedContainerSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} resources: limits: cpu: 100m diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index 55863c89d23..231b781821e 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -6,8 +6,8 @@ image: registry: docker.io # -- the path inside the repository repository: hapiproject/hapi - # -- defaults to `Chart.appVersion`. As of v5.7.0, this is the `distroless` flavor - tag: "" + # -- the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. + tag: "v6.0.1@sha256:63c98d8be3dadc77b47dca3115490f22bf99512f363f779f7bbcb42f569aeac3" # -- image pullPolicy to use pullPolicy: IfNotPresent @@ -39,6 +39,10 @@ securityContext: readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 65532 + runAsGroup: 65532 + privileged: false + seccompProfile: + type: RuntimeDefault # service to expose the server service: @@ -123,6 +127,9 @@ postgresql: capabilities: drop: - ALL + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault readinessProbe: failureThreshold: 5 @@ -187,3 +194,17 @@ metrics: # scrapeTimeout: 10s service: port: 8081 + +# @ignore +restrictedContainerSecurityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + privileged: false + capabilities: + drop: + - ALL + runAsNonRoot: true + runAsUser: 65534 + runAsGroup: 65534 + seccompProfile: + type: RuntimeDefault From 4790c4372f28a21cd76e29169a1827095aa555ef Mon Sep 17 00:00:00 2001 From: chgl Date: Thu, 25 Aug 2022 02:46:13 +0200 Subject: [PATCH 104/192] Don't run maven CI on changes to the helm chart --- .github/workflows/maven.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9919452b887..7fc93b8be73 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -5,10 +5,14 @@ name: Java CI with Maven on: push: - branches: - - '**' + branches: + - '**' + paths-ignore: + - "charts/**" pull_request: branches: [ master ] + paths-ignore: + - "charts/**" jobs: build: From bdc621e535a15eacca3891abd94f1bfc6a8fa333 Mon Sep 17 00:00:00 2001 From: chgl Date: Thu, 25 Aug 2022 23:21:19 +0200 Subject: [PATCH 105/192] updated helm chart to use version 6.1.0 of the image --- charts/hapi-fhir-jpaserver/Chart.yaml | 22 ++------ charts/hapi-fhir-jpaserver/README.md | 57 +++++++++++++++++++-- charts/hapi-fhir-jpaserver/README.md.gotmpl | 53 ++++++++++++++++++- charts/hapi-fhir-jpaserver/values.yaml | 2 +- 4 files changed, 108 insertions(+), 26 deletions(-) diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index e172526f43d..4632de77230 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -11,29 +11,13 @@ dependencies: repository: https://charts.bitnami.com/bitnami condition: postgresql.enabled appVersion: v6.x -version: 0.10.0 +version: 0.10.1 annotations: artifacthub.io/license: Apache-2.0 artifacthub.io/changes: | # When using the list of objects option the valid supported kinds are # added, changed, deprecated, removed, fixed, and security. - kind: changed - description: | - updated included PostgreSQL-subchart to v11.8.1. - Fixes `coalesce.go:220: warning: cannot overwrite table with non table for fhirserver.postgresql.primary.topologySpreadConstraints (map[])` warning + description: updated image version to v6.1.0 - kind: changed - description: | - set `securityContext.seccompProfile.type=RuntimeDefault` for included PostgreSQL as well as all `initContainer` and Helm - test pods to comply with the "restricted" Pod Security Standard: - - kind: changed - description: | - use curl as the image for running Helm test pods - - kind: changed - description: | - renamed `metrics` port to `http-metrics` for istio compliant naming - - kind: added - description: | - Helm test job to test metrics endpoint - - kind: changed - description: | - use full digest instead of just a tag for the server image reference + description: added section on configuring the chart for distributed tracing to the README.md diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index 9b72dc5c7f5..798e001bb0f 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -1,6 +1,6 @@ # HAPI FHIR JPA Server Starter Helm Chart -![Version: 0.10.0](https://img.shields.io/badge/Version-0.10.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v6.x](https://img.shields.io/badge/AppVersion-v6.x-informational?style=flat-square) +![Version: 0.10.1](https://img.shields.io/badge/Version-0.10.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v6.x](https://img.shields.io/badge/AppVersion-v6.x-informational?style=flat-square) This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment. @@ -32,7 +32,7 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | image.pullPolicy | string | `"IfNotPresent"` | image pullPolicy to use | | image.registry | string | `"docker.io"` | registry where the HAPI FHIR server image is hosted | | image.repository | string | `"hapiproject/hapi"` | the path inside the repository | -| image.tag | string | `"v6.0.1@sha256:63c98d8be3dadc77b47dca3115490f22bf99512f363f779f7bbcb42f569aeac3"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. | +| image.tag | string | `"v6.1.0@sha256:253f87bb1f5b7627f8e25f76a4b0aa7a83f31968c6e111ad74d3cc4ad9ae812e"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. | | imagePullSecrets | list | `[]` | image pull secrets to use when pulling the image | | ingress.annotations | object | `{}` | provide any additional annotations which may be required. Evaluated as a template. | | ingress.enabled | bool | `false` | whether to create an Ingress to expose the FHIR server HTTP endpoint | @@ -89,8 +89,8 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas ## Development -To update the Helm chart when a new version of the `hapiproject/hapi` image is released, the [Chart.yaml](Chart.yaml)'s -`appVersion` and `version` fields need to be updated accordingly. Afterwards, re-generate the [README.md](README.md) +To update the Helm chart when a new version of the `hapiproject/hapi` image is released, [values.yaml](values.yaml) `image.tag` and the [Chart.yaml](Chart.yaml)'s +`version` and optionally the `appVersion` field on major releases need to be updated. Afterwards, re-generate the [README.md](README.md) by running: ```sh @@ -99,5 +99,54 @@ INFO[2021-11-20T12:38:04Z] Found Chart directories [charts/hapi-fhir-jpaserver] INFO[2021-11-20T12:38:04Z] Generating README Documentation for chart /usr/src/app/charts/hapi-fhir-jpaserver ``` +## Enable Distributed Tracing based on the OpenTelemtry Java Agent + +The container image includes the [OpenTelemetry Java agent JAR](https://github.com/open-telemetry/opentelemetry-java-instrumentation) +which can be used to enable distributed tracing. It can be configured entirely using environment variables, +see for details. + +Here's an example setup deploying [Jaeger](https://www.jaegertracing.io/) as a tracing backend: + +```sh +# required by the Jaeger Operator +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml +kubectl create namespace observability +kubectl create -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.37.0/jaeger-operator.yaml -n observability + +cat < in your browser. + ---------------------------------------------- Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/charts/hapi-fhir-jpaserver/README.md.gotmpl b/charts/hapi-fhir-jpaserver/README.md.gotmpl index e345f8be8cb..bfea0325fe1 100644 --- a/charts/hapi-fhir-jpaserver/README.md.gotmpl +++ b/charts/hapi-fhir-jpaserver/README.md.gotmpl @@ -18,8 +18,8 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas ## Development -To update the Helm chart when a new version of the `hapiproject/hapi` image is released, the [Chart.yaml](Chart.yaml)'s -`appVersion` and `version` fields need to be updated accordingly. Afterwards, re-generate the [README.md](README.md) +To update the Helm chart when a new version of the `hapiproject/hapi` image is released, [values.yaml](values.yaml) `image.tag` and the [Chart.yaml](Chart.yaml)'s +`version` and optionally the `appVersion` field on major releases need to be updated. Afterwards, re-generate the [README.md](README.md) by running: ```sh @@ -28,4 +28,53 @@ INFO[2021-11-20T12:38:04Z] Found Chart directories [charts/hapi-fhir-jpaserver] INFO[2021-11-20T12:38:04Z] Generating README Documentation for chart /usr/src/app/charts/hapi-fhir-jpaserver ``` +## Enable Distributed Tracing based on the OpenTelemtry Java Agent + +The container image includes the [OpenTelemetry Java agent JAR](https://github.com/open-telemetry/opentelemetry-java-instrumentation) +which can be used to enable distributed tracing. It can be configured entirely using environment variables, +see for details. + +Here's an example setup deploying [Jaeger](https://www.jaegertracing.io/) as a tracing backend: + +```sh +# required by the Jaeger Operator +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml +kubectl create namespace observability +kubectl create -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.37.0/jaeger-operator.yaml -n observability + +cat < in your browser. + {{ template "helm-docs.versionFooter" . }} diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index 231b781821e..8b05fbe1146 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -7,7 +7,7 @@ image: # -- the path inside the repository repository: hapiproject/hapi # -- the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. - tag: "v6.0.1@sha256:63c98d8be3dadc77b47dca3115490f22bf99512f363f779f7bbcb42f569aeac3" + tag: "v6.1.0@sha256:253f87bb1f5b7627f8e25f76a4b0aa7a83f31968c6e111ad74d3cc4ad9ae812e" # -- image pullPolicy to use pullPolicy: IfNotPresent From c5e460dab02c32714fbe05f44b514ef8bdf273b8 Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Sat, 3 Sep 2022 20:04:59 +0200 Subject: [PATCH 106/192] added appProperties.getInline_resource_storage_below_size() (#420) * added appProperties.getInline_resource_storage_below_size() * indentations --- .../uhn/fhir/jpa/starter/AppProperties.java | 11 ++++++++- .../jpa/starter/BaseJpaRestfulServer.java | 4 ++++ src/main/resources/application.yaml | 23 ++++++++++--------- 3 files changed, 26 insertions(+), 12 deletions(-) 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 27bb715c116..431431747f9 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -45,6 +45,7 @@ public class AppProperties { private Boolean filter_search_enabled = true; private Boolean graphql_enabled = false; private Boolean binary_storage_enabled = false; + private Integer inline_resource_storage_below_size = 0; private Boolean bulk_export_enabled = false; private Boolean bulk_import_enabled = false; private Boolean default_pretty_print = true; @@ -395,7 +396,15 @@ public void setBinary_storage_enabled(Boolean binary_storage_enabled) { this.binary_storage_enabled = binary_storage_enabled; } - public Boolean getBulk_export_enabled() { + public Integer getInline_resource_storage_below_size() { + return inline_resource_storage_below_size; + } + + public void setInline_resource_storage_below_size(Integer inline_resource_storage_below_size) { + this.inline_resource_storage_below_size = inline_resource_storage_below_size; + } + + public Boolean getBulk_export_enabled() { return bulk_export_enabled; } 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 4cad6bfd726..81c0e0fb13b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -418,6 +418,10 @@ protected void initialize() throws ServletException { daoConfig.setLastNEnabled(true); } + if(appProperties.getInline_resource_storage_below_size() != 0){ + daoConfig.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size()); + } + daoConfig.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled()); daoConfig.getModelConfig().setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); daoConfig.getModelConfig().setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 3c0be6675d4..b8c322ca8f6 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -100,7 +100,7 @@ hapi: bulk_import_enabled: false # enforce_referential_integrity_on_delete: false # This is an experimental feature, and does not fully support _total and other FHIR features. -# enforce_referential_integrity_on_delete: false + # enforce_referential_integrity_on_delete: false # enforce_referential_integrity_on_write: false # etag_support_enabled: true # expunge_enabled: true @@ -110,8 +110,8 @@ hapi: # graphql_enabled: true # narrative_enabled: true # mdm_enabled: true -# local_base_urls: -# - https://hapi.fhir.org/baseR4 + # local_base_urls: + # - https://hapi.fhir.org/baseR4 mdm_enabled: false # partitioning: # allow_references_across_partitions: false @@ -128,10 +128,10 @@ hapi: search-coord-queue-capacity: 200 # Threadpool size for BATCH'ed GETs in a bundle. -# bundle_batch_pool_size: 10 -# bundle_batch_pool_max_size: 50 + # bundle_batch_pool_size: 10 + # bundle_batch_pool_max_size: 50 -# logger: + # logger: # error_format: 'ERROR - ${requestVerb} ${requestUrl}' # format: >- # Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] @@ -155,10 +155,11 @@ hapi: 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 + # validation: + # requests_enabled: true + # responses_enabled: true + # binary_storage_enabled: true + inline_resource_storage_below_size: 4000 # bulk_export_enabled: true # subscription: # resthook_enabled: true @@ -190,4 +191,4 @@ hapi: # rest_url: 'localhost:9200' # protocol: 'http' # schema_management_strategy: CREATE -# username: SomeUsername +# username: SomeUsername \ No newline at end of file From d660d5f76d63ad4697148f9d612aedd29640efe9 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Sat, 10 Sep 2022 21:14:01 +0200 Subject: [PATCH 107/192] Feat/restructuring (#422) * Did restructuring and made repo validation interceptor an optional bean instead as it makes it more clean * Moved construction of FHIR servlet into a bean for better reuse of others that would like to depend directly on this library * Disabled default validation enabled --- .../uhn/fhir/jpa/starter/AppProperties.java | 6 +- .../ca/uhn/fhir/jpa/starter/Application.java | 12 +- .../jpa/starter/BaseJpaRestfulServer.java | 429 ----------------- .../fhir/jpa/starter/JpaRestfulServer.java | 28 -- .../fhir/jpa/starter/StarterJpaConfig.java | 128 ------ .../{ => common}/ElasticsearchConfig.java | 10 +- .../{ => common}/FhirServerConfigCommon.java | 101 ++-- .../{ => common}/FhirServerConfigDstu2.java | 2 +- .../{ => common}/FhirServerConfigDstu3.java | 3 +- .../{ => common}/FhirServerConfigR4.java | 3 +- .../{ => common}/FhirServerConfigR5.java | 2 +- .../{ => common}/FhirTesterConfig.java | 23 +- .../jpa/starter/common/StarterJpaConfig.java | 433 ++++++++++++++++++ ...epositoryValidationInterceptorFactory.java | 4 +- ...toryValidationInterceptorFactoryDstu3.java | 13 +- ...ositoryValidationInterceptorFactoryR4.java | 13 +- ...ositoryValidationInterceptorFactoryR5.java | 13 +- .../jpa/starter/cql/CqlConfigCondition.java | 3 +- .../starter/{ => util}/EnvironmentHelper.java | 19 +- .../JpaHibernatePropertiesProvider.java | 2 +- src/main/resources/application.yaml | 2 +- .../java/ca/uhn/fhir/jpa/starter/Demo.java | 20 - .../jpa/starter/ExampleServerDstu3IT.java | 4 +- .../fhir/jpa/starter/ExampleServerR4IT.java | 4 - .../jpa/starter/SocketImplementation.java | 4 +- 25 files changed, 554 insertions(+), 727 deletions(-) delete mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java delete mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java delete mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common}/ElasticsearchConfig.java (85%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common}/FhirServerConfigCommon.java (71%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common}/FhirServerConfigDstu2.java (91%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common}/FhirServerConfigDstu3.java (87%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common}/FhirServerConfigR4.java (87%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common}/FhirServerConfigR5.java (91%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common}/FhirTesterConfig.java (78%) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common/validation}/IRepositoryValidationInterceptorFactory.java (63%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common/validation}/RepositoryValidationInterceptorFactoryDstu3.java (84%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common/validation}/RepositoryValidationInterceptorFactoryR4.java (84%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => common/validation}/RepositoryValidationInterceptorFactoryR5.java (84%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => util}/EnvironmentHelper.java (95%) rename src/main/java/ca/uhn/fhir/jpa/starter/{ => util}/JpaHibernatePropertiesProvider.java (96%) delete mode 100644 src/test/java/ca/uhn/fhir/jpa/starter/Demo.java 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 431431747f9..e7599a8b284 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -81,7 +81,7 @@ public class AppProperties { private Integer bundle_batch_pool_size = 20; private Integer bundle_batch_pool_max_size = 100; - private List local_base_urls = new ArrayList<>(); + private final List local_base_urls = new ArrayList<>(); public Boolean getOpenapi_enabled() { return openapi_enabled; @@ -203,10 +203,6 @@ public void setSupported_resource_types(List supported_resource_types) { this.supported_resource_types = supported_resource_types; } - public List getSupported_resource_types(List supported_resource_types) { - return this.supported_resource_types; - } - public Logger getLogger() { return logger; } 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 2a26b5cb3ef..8031c598f7e 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -3,11 +3,13 @@ import ca.uhn.fhir.batch2.jobs.config.Batch2JobsConfig; import ca.uhn.fhir.jpa.batch2.JpaBatch2Config; import ca.uhn.fhir.jpa.starter.annotations.OnEitherVersion; +import ca.uhn.fhir.jpa.starter.common.FhirTesterConfig; import ca.uhn.fhir.jpa.starter.mdm.MdmConfig; 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 ca.uhn.fhir.rest.server.RestfulServer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.boot.SpringApplication; @@ -23,8 +25,7 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; -@ServletComponentScan(basePackageClasses = { - JpaRestfulServer.class}) +@ServletComponentScan(basePackageClasses = {RestfulServer.class}) @SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class}) @Import({ SubscriptionSubmitterConfig.class, @@ -56,11 +57,10 @@ protected SpringApplicationBuilder configure( @Bean @Conditional(OnEitherVersion.class) - public ServletRegistrationBean hapiServletRegistration() { + public ServletRegistrationBean hapiServletRegistration(RestfulServer restfulServer) { ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(); - JpaRestfulServer jpaRestfulServer = new JpaRestfulServer(); - beanFactory.autowireBean(jpaRestfulServer); - servletRegistrationBean.setServlet(jpaRestfulServer); + beanFactory.autowireBean(restfulServer); + servletRegistrationBean.setServlet(restfulServer); servletRegistrationBean.addUrlMappings("/fhir/*"); servletRegistrationBean.setLoadOnStartup(1); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java deleted file mode 100644 index 81c0e0fb13b..00000000000 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ /dev/null @@ -1,429 +0,0 @@ -package ca.uhn.fhir.jpa.starter; - -import ca.uhn.fhir.batch2.jobs.imprt.BulkDataImportProvider; -import ca.uhn.fhir.batch2.jobs.reindex.ReindexProvider; -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.context.FhirVersionEnum; -import ca.uhn.fhir.context.support.IValidationSupport; -import ca.uhn.fhir.cql.common.provider.CqlProviderLoader; -import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; -import ca.uhn.fhir.interceptor.api.IInterceptorService; -import ca.uhn.fhir.jpa.api.config.DaoConfig; -import ca.uhn.fhir.jpa.api.dao.DaoRegistry; -import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; -import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor; -import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider; -import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider; -import ca.uhn.fhir.jpa.graphql.GraphQLProvider; -import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; -import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc; -import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; -import ca.uhn.fhir.jpa.partition.PartitionManagementProvider; -import ca.uhn.fhir.jpa.provider.*; -import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; -import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; -import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor; -import ca.uhn.fhir.mdm.provider.MdmProviderLoader; -import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; -import ca.uhn.fhir.narrative.INarrativeGenerator; -import ca.uhn.fhir.narrative2.NullNarrativeGenerator; -import ca.uhn.fhir.rest.openapi.OpenApiInterceptor; -import ca.uhn.fhir.rest.server.*; -import ca.uhn.fhir.rest.server.interceptor.*; -import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor; -import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; -import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy; -import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; -import ca.uhn.fhir.validation.IValidatorModule; -import ca.uhn.fhir.validation.ResultSeverityEnum; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; -import org.hl7.fhir.r4.model.Bundle.BundleType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpHeaders; -import org.springframework.web.cors.CorsConfiguration; - -import javax.servlet.ServletException; -import java.util.*; -import java.util.stream.Collectors; - -public class BaseJpaRestfulServer extends RestfulServer { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseJpaRestfulServer.class); - - private static final long serialVersionUID = 1L; - @Autowired - DaoRegistry daoRegistry; - @Autowired - DaoConfig daoConfig; - @Autowired - ISearchParamRegistry searchParamRegistry; - @Autowired - IFhirSystemDao fhirSystemDao; - @Autowired - ResourceProviderFactory resourceProviderFactory; - @Autowired - IJpaSystemProvider jpaSystemProvider; - @Autowired - ValueSetOperationProvider myValueSetOperationProvider; - @Autowired - IInterceptorBroadcaster interceptorBroadcaster; - @Autowired - DatabaseBackedPagingProvider databaseBackedPagingProvider; - @Autowired - IInterceptorService interceptorService; - @Autowired - IValidatorModule validatorModule; - @Autowired - Optional graphQLProvider; - @Autowired - BulkDataExportProvider bulkDataExportProvider; - @Autowired - BulkDataImportProvider bulkDataImportProvider; - @Autowired - PartitionManagementProvider partitionManagementProvider; - - @Autowired - ValueSetOperationProvider valueSetOperationProvider; - @Autowired - ReindexProvider reindexProvider; - @Autowired - BinaryStorageInterceptor binaryStorageInterceptor; - @Autowired - Optional binaryAccessProvider; - @Autowired - IPackageInstallerSvc packageInstallerSvc; - @Autowired - AppProperties appProperties; - @Autowired - ApplicationContext myApplicationContext; - @Autowired(required = false) - IRepositoryValidationInterceptorFactory factory; - // These are set only if the features are enabled - @Autowired - Optional cqlProviderLoader; - @Autowired - Optional mdmProviderProvider; - - @Autowired - private IValidationSupport myValidationSupport; - - public BaseJpaRestfulServer() { - } - - @SuppressWarnings("unchecked") - @Override - protected void initialize() throws ServletException { - super.initialize(); - - /* - * Create a FhirContext object that uses the version of FHIR - * specified in the properties file. - */ - // Customize supported resource types - List supportedResourceTypes = appProperties.getSupported_resource_types(); - - if (!supportedResourceTypes.isEmpty()) { - if (!supportedResourceTypes.contains("SearchParameter")) { - supportedResourceTypes.add("SearchParameter"); - } - daoRegistry.setSupportedResourceTypes(supportedResourceTypes); - } - - setFhirContext(fhirSystemDao.getContext()); - - /* - * Order matters - the MDM provider registers itself on the resourceProviderFactory - hence the loading must be done - * ahead of provider registration - */ - if(appProperties.getMdm_enabled()) - mdmProviderProvider.get().loadProvider(); - - registerProviders(resourceProviderFactory.createProviders()); - registerProvider(jpaSystemProvider); - /* - * 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 - * is a nice addition. - * - * You can also create your own subclass of the conformance provider if you need to - * provide further customization of your server's CapabilityStatement - */ - - FhirVersionEnum fhirVersion = fhirSystemDao.getContext().getVersion().getVersion(); - if (fhirVersion == FhirVersionEnum.DSTU2) { - - JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, fhirSystemDao, - daoConfig); - confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server"); - setServerConformanceProvider(confProvider); - } else { - if (fhirVersion == FhirVersionEnum.DSTU3) { - - JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, fhirSystemDao, - daoConfig, searchParamRegistry); - confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server"); - setServerConformanceProvider(confProvider); - } else if (fhirVersion == FhirVersionEnum.R4) { - - JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(this, fhirSystemDao, - daoConfig, searchParamRegistry, myValidationSupport); - confProvider.setImplementationDescription("HAPI FHIR R4 Server"); - setServerConformanceProvider(confProvider); - } else if (fhirVersion == FhirVersionEnum.R5) { - - JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(this, fhirSystemDao, - daoConfig, searchParamRegistry, myValidationSupport); - confProvider.setImplementationDescription("HAPI FHIR R5 Server"); - setServerConformanceProvider(confProvider); - } else { - throw new IllegalStateException(); - } - } - - /* - * ETag Support - */ - - if (appProperties.getEtag_support_enabled() == false) - setETagSupport(ETagSupportEnum.DISABLED); - - - /* - * This server tries to dynamically generate narratives - */ - FhirContext ctx = getFhirContext(); - INarrativeGenerator theNarrativeGenerator = - appProperties.getNarrative_enabled() ? - new DefaultThymeleafNarrativeGenerator() : - new NullNarrativeGenerator(); - ctx.setNarrativeGenerator(theNarrativeGenerator); - - /* - * Default to JSON and pretty printing - */ - setDefaultPrettyPrint(appProperties.getDefault_pretty_print()); - - /* - * Default encoding - */ - setDefaultResponseEncoding(appProperties.getDefault_encoding()); - - /* - * This configures the server to page search results to and from - * the database, instead of only paging them to memory. This may mean - * a performance hit when performing searches that return lots of results, - * but makes the server much more scalable. - */ - - setPagingProvider(databaseBackedPagingProvider); - - /* - * This interceptor formats the output using nice colourful - * HTML output when the request is detected to come from a - * browser. - */ - ResponseHighlighterInterceptor responseHighlighterInterceptor = new ResponseHighlighterInterceptor(); - this.registerInterceptor(responseHighlighterInterceptor); - - if (appProperties.getFhirpath_interceptor_enabled()) { - registerInterceptor(new FhirPathFilterInterceptor()); - } - - /* - * Add some logging for each request - */ - LoggingInterceptor loggingInterceptor = new LoggingInterceptor(); - loggingInterceptor.setLoggerName(appProperties.getLogger().getName()); - loggingInterceptor.setMessageFormat(appProperties.getLogger().getFormat()); - loggingInterceptor.setErrorMessageFormat(appProperties.getLogger().getError_format()); - loggingInterceptor.setLogExceptions(appProperties.getLogger().getLog_exceptions()); - this.registerInterceptor(loggingInterceptor); - - /* - * If you are hosting this server at a specific DNS name, the server will try to - * figure out the FHIR base URL based on what the web container tells it, but - * this doesn't always work. If you are setting links in your search bundles that - * just refer to "localhost", you might want to use a server address strategy: - */ - String serverAddress = appProperties.getServer_address(); - if (!Strings.isNullOrEmpty(serverAddress)) { - setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress)); - } else if (appProperties.getUse_apache_address_strategy()) { - boolean useHttps = appProperties.getUse_apache_address_strategy_https(); - setServerAddressStrategy(useHttps ? ApacheProxyAddressStrategy.forHttps() : - ApacheProxyAddressStrategy.forHttp()); - } else { - setServerAddressStrategy(new IncomingRequestAddressStrategy()); - } - - /* - * If you are using DSTU3+, you may want to add a terminology uploader, which allows - * uploading of external terminologies such as Snomed CT. Note that this uploader - * does not have any security attached (any anonymous user may use it by default) - * so it is a potential security vulnerability. Consider using an AuthorizationInterceptor - * with this feature. - */ - if (ctx.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { // <-- ENABLED RIGHT NOW - registerProvider(myApplicationContext.getBean(TerminologyUploaderProvider.class)); - } - - // If you want to enable the $trigger-subscription operation to allow - // manual triggering of a subscription delivery, enable this provider - if (true) { // <-- ENABLED RIGHT NOW - registerProvider(myApplicationContext.getBean(SubscriptionTriggeringProvider.class)); - } - - // Define your CORS configuration. This is an example - // showing a typical setup. You should customize this - // to your specific needs - if (appProperties.getCors() != null) { - ourLog.info("CORS is enabled on this server"); - CorsConfiguration config = new CorsConfiguration(); - config.addAllowedHeader(HttpHeaders.ORIGIN); - config.addAllowedHeader(HttpHeaders.ACCEPT); - config.addAllowedHeader(HttpHeaders.CONTENT_TYPE); - config.addAllowedHeader(HttpHeaders.AUTHORIZATION); - config.addAllowedHeader(HttpHeaders.CACHE_CONTROL); - config.addAllowedHeader("x-fhir-starter"); - config.addAllowedHeader("X-Requested-With"); - config.addAllowedHeader("Prefer"); - - List allAllowedCORSOrigins = appProperties.getCors().getAllowed_origin(); - allAllowedCORSOrigins.forEach(config::addAllowedOriginPattern); - ourLog.info("CORS allows the following origins: " + String.join(", ", allAllowedCORSOrigins)); - - config.addExposedHeader("Location"); - config.addExposedHeader("Content-Location"); - config.setAllowedMethods( - Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD")); - config.setAllowCredentials(appProperties.getCors().getAllow_Credentials()); - - // Create the interceptor and register it - CorsInterceptor interceptor = new CorsInterceptor(config); - registerInterceptor(interceptor); - } else { - ourLog.info("CORS is disabled on this server"); - } - - // If subscriptions are enabled, we want to register the interceptor that - // will activate them and match results against them - if (appProperties.getSubscription() != null) { - // Subscription debug logging - interceptorService.registerInterceptor(new SubscriptionDebugLogInterceptor()); - } - - // Cascading deletes - - - if (appProperties.getAllow_cascading_deletes()) { - CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(ctx, - daoRegistry, interceptorBroadcaster); - getInterceptorService().registerInterceptor(cascadingDeleteInterceptor); - } - - // Binary Storage - if (appProperties.getBinary_storage_enabled() && binaryAccessProvider.isPresent()) { - registerProvider(binaryAccessProvider.get()); - getInterceptorService().registerInterceptor(binaryStorageInterceptor); - } - - // Validation - - if (validatorModule != null) { - if (appProperties.getValidation().getRequests_enabled()) { - RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor(); - interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR); - interceptor.setValidatorModules(Collections.singletonList(validatorModule)); - registerInterceptor(interceptor); - } - if (appProperties.getValidation().getResponses_enabled()) { - ResponseValidatingInterceptor interceptor = new ResponseValidatingInterceptor(); - interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR); - interceptor.setValidatorModules(Collections.singletonList(validatorModule)); - registerInterceptor(interceptor); - } - } - - // GraphQL - if (appProperties.getGraphql_enabled()) { - if (fhirVersion.isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { - registerProvider(graphQLProvider.get()); - } - } - - if (appProperties.getAllowed_bundle_types() != null) { - daoConfig.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream().map(BundleType::toCode).collect(Collectors.toSet())); - } - - daoConfig.setDeferIndexingForCodesystemsOfSize(appProperties.getDefer_indexing_for_codesystems_of_size()); - - if (appProperties.getOpenapi_enabled()) { - registerInterceptor(new OpenApiInterceptor()); - } - - // Bulk Export - if (appProperties.getBulk_export_enabled()) { - registerProvider(bulkDataExportProvider); - } - - //Bulk Import - if (appProperties.getBulk_import_enabled()) { - registerProvider(bulkDataImportProvider); - } - - // valueSet Operations i.e $expand - registerProvider(myValueSetOperationProvider); - - //reindex Provider $reindex - registerProvider(reindexProvider); - - // Partitioning - if (appProperties.getPartitioning() != null) { - registerInterceptor(new RequestTenantPartitionInterceptor()); - setTenantIdentificationStrategy(new UrlBaseTenantIdentificationStrategy()); - registerProviders(partitionManagementProvider); - } - - if (appProperties.getClient_id_strategy() == DaoConfig.ClientIdStrategyEnum.ANY) { - daoConfig.setResourceServerIdStrategy(DaoConfig.IdStrategyEnum.UUID); - daoConfig.setResourceClientIdStrategy(appProperties.getClient_id_strategy()); - } - //Parallel Batch GET execution settings - daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_size()); - daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_max_size()); - - if (appProperties.getImplementationGuides() != null) { - Map guides = appProperties.getImplementationGuides(); - for (Map.Entry guide : guides.entrySet()) { - PackageInstallationSpec packageInstallationSpec = new PackageInstallationSpec() - .setPackageUrl(guide.getValue().getUrl()) - .setName(guide.getValue().getName()) - .setVersion(guide.getValue().getVersion()) - .setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL); - if(appProperties.getInstall_transitive_ig_dependencies()) { - packageInstallationSpec.setFetchDependencies(true); - packageInstallationSpec.setDependencyExcludes(ImmutableList.of("hl7.fhir.r2.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core", "hl7.fhir.r5.core")); - } - packageInstallerSvc.install(packageInstallationSpec); - } - } - - if(factory != null) { - interceptorService.registerInterceptor(factory.buildUsingStoredStructureDefinitions()); - } - - - if (appProperties.getLastn_enabled()) { - daoConfig.setLastNEnabled(true); - } - - if(appProperties.getInline_resource_storage_below_size() != 0){ - daoConfig.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size()); - } - - daoConfig.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled()); - daoConfig.getModelConfig().setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); - daoConfig.getModelConfig().setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); - } -} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java deleted file mode 100644 index c895c2240cd..00000000000 --- a/src/main/java/ca/uhn/fhir/jpa/starter/JpaRestfulServer.java +++ /dev/null @@ -1,28 +0,0 @@ -package ca.uhn.fhir.jpa.starter; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; - -import javax.servlet.ServletException; - -@Import(AppProperties.class) -public class JpaRestfulServer extends BaseJpaRestfulServer { - - @Autowired - AppProperties appProperties; - - private static final long serialVersionUID = 1L; - - public JpaRestfulServer() { - super(); - } - - @Override - protected void initialize() throws ServletException { - super.initialize(); - - // Add your own customization here - - } - -} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java deleted file mode 100644 index 2acfabd898f..00000000000 --- a/src/main/java/ca/uhn/fhir/jpa/starter/StarterJpaConfig.java +++ /dev/null @@ -1,128 +0,0 @@ -package ca.uhn.fhir.jpa.starter; - -import ca.uhn.fhir.context.ConfigurationException; -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.jpa.api.IDaoRegistry; -import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; -import ca.uhn.fhir.jpa.batch.config.NonPersistedBatchConfigurer; -import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil; -import ca.uhn.fhir.jpa.config.util.ResourceCountCacheUtil; -import ca.uhn.fhir.jpa.config.util.ValidationSupportConfigUtil; -import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl; -import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc; -import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDaoJpaImpl; -import ca.uhn.fhir.jpa.dao.search.HSearchSortHelperImpl; -import ca.uhn.fhir.jpa.dao.search.IHSearchSortHelper; -import ca.uhn.fhir.jpa.provider.DaoRegistryResourceSupportedSvc; -import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; -import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc; -import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl; -import ca.uhn.fhir.jpa.util.ResourceCountCache; -import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain; -import ca.uhn.fhir.mdm.dao.IMdmLinkDao; -import ca.uhn.fhir.rest.api.IResourceSupportedSvc; -import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; - -import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport; -import org.springframework.batch.core.configuration.annotation.BatchConfigurer; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; - -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; - -@Configuration -public class StarterJpaConfig { - @Bean - public IFulltextSearchSvc fullTextSearchSvc() { - return new FulltextSearchSvcImpl(); - } - - @Bean - public IStaleSearchDeletingSvc staleSearchDeletingSvc() { - return new StaleSearchDeletingSvcImpl(); - } - - @Primary - @Bean - public CachingValidationSupport validationSupportChain(JpaValidationSupportChain theJpaValidationSupportChain) { - return ValidationSupportConfigUtil.newCachingValidationSupport(theJpaValidationSupportChain); - } - - @Bean - public BatchConfigurer batchConfigurer() { - return new NonPersistedBatchConfigurer(); - } - - @Autowired - AppProperties appProperties; - @Autowired - private DataSource myDataSource; - @Autowired - private ConfigurableEnvironment configurableEnvironment; - - /** - * Customize the default/max page sizes for search results. You can set these however - * you want, although very large page sizes will require a lot of RAM. - */ - @Bean - public DatabaseBackedPagingProvider databaseBackedPagingProvider() { - DatabaseBackedPagingProvider pagingProvider = new DatabaseBackedPagingProvider(); - pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); - pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); - return pagingProvider; - } - - @Bean - public IResourceSupportedSvc resourceSupportedSvc(IDaoRegistry theDaoRegistry) { - return new DaoRegistryResourceSupportedSvc(theDaoRegistry); - } - - @Bean(name = "myResourceCountsCache") - public ResourceCountCache resourceCountsCache(IFhirSystemDao theSystemDao) { - return ResourceCountCacheUtil.newResourceCountCache(theSystemDao); - } - - @Primary - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory( - ConfigurableListableBeanFactory myConfigurableListableBeanFactory, FhirContext theFhirContext) { - LocalContainerEntityManagerFactoryBean retVal = HapiEntityManagerFactoryUtil.newEntityManagerFactory(myConfigurableListableBeanFactory, theFhirContext); - retVal.setPersistenceUnitName("HAPI_PU"); - - try { - retVal.setDataSource(myDataSource); - } catch (Exception e) { - throw new ConfigurationException("Could not set the data source due to a configuration issue", e); - } - retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, myConfigurableListableBeanFactory)); - return retVal; - } - - @Bean - @Primary - public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { - JpaTransactionManager retVal = new JpaTransactionManager(); - retVal.setEntityManagerFactory(entityManagerFactory); - return retVal; - } - - @Autowired - private ISearchParamRegistry mySearchParamRegistry; - - @Bean - public IHSearchSortHelper hSearchSortHelper() { - return new HSearchSortHelperImpl(mySearchParamRegistry); - } - - @Bean - public IMdmLinkDao mdmLinkDao(){ - return new MdmLinkDaoJpaImpl(); - } -} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/ElasticsearchConfig.java similarity index 85% rename from src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/ElasticsearchConfig.java index 21216e6dd59..78de8907af4 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/ElasticsearchConfig.java @@ -1,7 +1,7 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common; import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; -import org.springframework.beans.factory.annotation.Autowired; +import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.ConfigurableEnvironment; @@ -10,12 +10,8 @@ @Configuration public class ElasticsearchConfig { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ElasticsearchConfig.class); - - @Autowired - private ConfigurableEnvironment configurableEnvironment; - @Bean - public ElasticsearchSvcImpl elasticsearchSvc() { + public ElasticsearchSvcImpl elasticsearchSvc(ConfigurableEnvironment configurableEnvironment) { if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) { String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); if (elasticsearchUrl.startsWith("http")) { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java similarity index 71% rename from src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java index ac80f093b0e..4dd4412c77a 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common; import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.binary.api.IBinaryStorageSvc; @@ -7,6 +7,8 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings.CrossPartitionReferenceMode; import ca.uhn.fhir.jpa.model.entity.ModelConfig; +import ca.uhn.fhir.jpa.starter.AppProperties; +import ca.uhn.fhir.jpa.starter.util.JpaHibernatePropertiesProvider; import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory; import ca.uhn.fhir.jpa.subscription.match.deliver.email.EmailSenderImpl; import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender; @@ -14,6 +16,7 @@ import ca.uhn.fhir.rest.server.mail.MailConfig; import ca.uhn.fhir.rest.server.mail.MailSvc; import com.google.common.base.Strings; +import org.hl7.fhir.r4.model.Bundle.BundleType; import org.hl7.fhir.dstu2.model.Subscription; import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.context.annotation.Bean; @@ -25,6 +28,7 @@ import java.util.HashSet; import java.util.Optional; +import java.util.stream.Collectors; /** * This is the primary configuration file for the example server @@ -78,54 +82,85 @@ public FhirServerConfigCommon(AppProperties appProperties) { */ @Bean public DaoConfig daoConfig(AppProperties appProperties) { - DaoConfig retVal = new DaoConfig(); - - retVal.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? DaoConfig.IndexEnabledEnum.ENABLED : DaoConfig.IndexEnabledEnum.DISABLED); - retVal.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets()); - retVal.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write()); - retVal.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete()); - retVal.setAllowContainsSearches(appProperties.getAllow_contains_searches()); - retVal.setAllowMultipleDelete(appProperties.getAllow_multiple_delete()); - retVal.setAllowExternalReferences(appProperties.getAllow_external_references()); - retVal.setSchedulingDisabled(!appProperties.getDao_scheduling_enabled()); - retVal.setDeleteExpungeEnabled(appProperties.getDelete_expunge_enabled()); - retVal.setExpungeEnabled(appProperties.getExpunge_enabled()); + DaoConfig daoConfig = new DaoConfig(); + + daoConfig.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? DaoConfig.IndexEnabledEnum.ENABLED : DaoConfig.IndexEnabledEnum.DISABLED); + daoConfig.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets()); + daoConfig.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write()); + daoConfig.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete()); + daoConfig.setAllowContainsSearches(appProperties.getAllow_contains_searches()); + daoConfig.setAllowMultipleDelete(appProperties.getAllow_multiple_delete()); + daoConfig.setAllowExternalReferences(appProperties.getAllow_external_references()); + daoConfig.setSchedulingDisabled(!appProperties.getDao_scheduling_enabled()); + daoConfig.setDeleteExpungeEnabled(appProperties.getDelete_expunge_enabled()); + daoConfig.setExpungeEnabled(appProperties.getExpunge_enabled()); if(appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) - retVal.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom()); + daoConfig.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom()); Integer maxFetchSize = appProperties.getMax_page_size(); - retVal.setFetchSizeDefaultMaximum(maxFetchSize); + daoConfig.setFetchSizeDefaultMaximum(maxFetchSize); ourLog.info("Server configured to have a maximum fetch size of " + (maxFetchSize == Integer.MAX_VALUE ? "'unlimited'" : maxFetchSize)); Long reuseCachedSearchResultsMillis = appProperties.getReuse_cached_search_results_millis(); - retVal.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis); + daoConfig.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis); ourLog.info("Server configured to cache search results for {} milliseconds", reuseCachedSearchResultsMillis); Long retainCachedSearchesMinutes = appProperties.getRetain_cached_searches_mins(); - retVal.setExpireSearchResultsAfterMillis(retainCachedSearchesMinutes * 60 * 1000); + daoConfig.setExpireSearchResultsAfterMillis(retainCachedSearchesMinutes * 60 * 1000); if(appProperties.getSubscription() != null) { // Subscriptions are enabled by channel type if (appProperties.getSubscription().getResthook_enabled()) { ourLog.info("Enabling REST-hook subscriptions"); - retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK); + daoConfig.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK); } if (appProperties.getSubscription().getEmail() != null) { ourLog.info("Enabling email subscriptions"); - retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL); + daoConfig.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL); } if (appProperties.getSubscription().getWebsocket_enabled()) { ourLog.info("Enabling websocket subscriptions"); - retVal.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET); + daoConfig.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET); } } - retVal.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); - retVal.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing()); - retVal.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls())); + daoConfig.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); + daoConfig.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing()); + daoConfig.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls())); - return retVal; + if (appProperties.getLastn_enabled()) { + daoConfig.setLastNEnabled(true); + } + + if(appProperties.getInline_resource_storage_below_size() != 0){ + daoConfig.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size()); + } + + + daoConfig.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled()); + daoConfig.getModelConfig().setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); + daoConfig.getModelConfig().setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); + + + + if (appProperties.getAllowed_bundle_types() != null) { + daoConfig.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream().map(BundleType::toCode).collect(Collectors.toSet())); + } + + daoConfig.setDeferIndexingForCodesystemsOfSize(appProperties.getDefer_indexing_for_codesystems_of_size()); + + + if (appProperties.getClient_id_strategy() == DaoConfig.ClientIdStrategyEnum.ANY) { + daoConfig.setResourceServerIdStrategy(DaoConfig.IdStrategyEnum.UUID); + daoConfig.setResourceClientIdStrategy(appProperties.getClient_id_strategy()); + } + //Parallel Batch GET execution settings + daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_size()); + daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_max_size()); + + + return daoConfig; } @Bean @@ -183,24 +218,6 @@ public ModelConfig modelConfig(AppProperties appProperties, DaoConfig daoConfig) return modelConfig; } - /** - * The following bean configures the database connection. The 'url' property value of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates that the server should save resources in a - * directory called "jpaserver_derby_files". - *

- * A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource. - */ - /*@Bean(destroyMethod = "close") - public BasicDataSource dataSource() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { - BasicDataSource retVal = new BasicDataSource(); - Driver driver = (Driver) Class.forName(HapiProperties.getDataSourceDriver()).getConstructor().newInstance(); - retVal.setDriver(driver); - retVal.setUrl(HapiProperties.getDataSourceUrl()); - retVal.setUsername(HapiProperties.getDataSourceUsername()); - retVal.setPassword(HapiProperties.getDataSourcePassword()); - retVal.setMaxTotal(HapiProperties.getDataSourceMaxPoolSize()); - return retVal; - }*/ - @Lazy @Bean public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java similarity index 91% rename from src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java index b8011389d20..151df82898f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common; import ca.uhn.fhir.jpa.config.JpaDstu2Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU2Condition; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java similarity index 87% rename from src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java index 35d1dabb49c..e0056bc1912 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java @@ -1,9 +1,8 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common; import ca.uhn.fhir.jpa.config.dstu3.JpaDstu3Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU3Condition; import ca.uhn.fhir.jpa.starter.cql.StarterCqlDstu3Config; -import ca.uhn.fhir.jpa.starter.mdm.MdmConfig; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java similarity index 87% rename from src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java index c31cf529edd..4c212ef2bce 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java @@ -1,9 +1,8 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common; import ca.uhn.fhir.jpa.config.r4.JpaR4Config; import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; import ca.uhn.fhir.jpa.starter.cql.StarterCqlR4Config; -import ca.uhn.fhir.jpa.starter.mdm.MdmConfig; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java similarity index 91% rename from src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java index 8ee03df272d..1552aef7aee 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common; import ca.uhn.fhir.jpa.config.r5.JpaR5Config; import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java similarity index 78% rename from src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java index 7adf8bf4727..cb28659d52c 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirTesterConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java @@ -1,5 +1,6 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common; +import ca.uhn.fhir.jpa.starter.AppProperties; import ca.uhn.fhir.to.FhirTesterMvcConfig; import ca.uhn.fhir.to.TesterConfig; import org.springframework.context.annotation.Bean; @@ -36,17 +37,17 @@ public class FhirTesterConfig { @Bean public TesterConfig testerConfig(AppProperties appProperties) { TesterConfig retVal = new TesterConfig(); - appProperties.getTester().entrySet().stream().forEach(t -> { - retVal - .addServer() - .withId(t.getKey()) - .withFhirVersion(t.getValue().getFhir_version()) - .withBaseUrl(t.getValue().getServer_address()) - .withName(t.getValue().getName()); - retVal.setRefuseToFetchThirdPartyUrls( - t.getValue().getRefuse_to_fetch_third_party_urls()); + appProperties.getTester().forEach((key, value) -> { + retVal + .addServer() + .withId(key) + .withFhirVersion(value.getFhir_version()) + .withBaseUrl(value.getServer_address()) + .withName(value.getName()); + retVal.setRefuseToFetchThirdPartyUrls( + value.getRefuse_to_fetch_third_party_urls()); - }); + }); return retVal; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java new file mode 100644 index 00000000000..b2f108a084e --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -0,0 +1,433 @@ +package ca.uhn.fhir.jpa.starter.common; + +import ca.uhn.fhir.batch2.jobs.imprt.BulkDataImportProvider; +import ca.uhn.fhir.batch2.jobs.reindex.ReindexProvider; +import ca.uhn.fhir.context.ConfigurationException; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; +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; +import ca.uhn.fhir.jpa.batch.config.NonPersistedBatchConfigurer; +import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor; +import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider; +import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider; +import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil; +import ca.uhn.fhir.jpa.config.util.ResourceCountCacheUtil; +import ca.uhn.fhir.jpa.config.util.ValidationSupportConfigUtil; +import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl; +import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc; +import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDaoJpaImpl; +import ca.uhn.fhir.jpa.dao.search.HSearchSortHelperImpl; +import ca.uhn.fhir.jpa.dao.search.IHSearchSortHelper; +import ca.uhn.fhir.jpa.graphql.GraphQLProvider; +import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; +import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; +import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc; +import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; +import ca.uhn.fhir.jpa.partition.PartitionManagementProvider; +import ca.uhn.fhir.jpa.provider.*; +import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; +import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; +import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc; +import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl; +import ca.uhn.fhir.jpa.starter.AppProperties; +import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory; +import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper; +import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor; +import ca.uhn.fhir.jpa.util.ResourceCountCache; +import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain; +import ca.uhn.fhir.mdm.dao.IMdmLinkDao; +import ca.uhn.fhir.mdm.provider.MdmProviderLoader; +import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; +import ca.uhn.fhir.narrative2.NullNarrativeGenerator; +import ca.uhn.fhir.rest.api.IResourceSupportedSvc; +import ca.uhn.fhir.rest.openapi.OpenApiInterceptor; +import ca.uhn.fhir.rest.server.*; +import ca.uhn.fhir.rest.server.interceptor.*; +import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor; +import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; +import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy; +import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; +import ca.uhn.fhir.validation.IValidatorModule; +import ca.uhn.fhir.validation.ResultSeverityEnum; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport; +import org.springframework.batch.core.configuration.annotation.BatchConfigurer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.http.HttpHeaders; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.web.cors.CorsConfiguration; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; +import java.util.*; + +import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR; + +@Configuration +public class StarterJpaConfig { + + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StarterJpaConfig.class); + + @Bean + public IFulltextSearchSvc fullTextSearchSvc() { + return new FulltextSearchSvcImpl(); + } + + @Bean + public IStaleSearchDeletingSvc staleSearchDeletingSvc() { + return new StaleSearchDeletingSvcImpl(); + } + + @Primary + @Bean + public CachingValidationSupport validationSupportChain(JpaValidationSupportChain theJpaValidationSupportChain) { + return ValidationSupportConfigUtil.newCachingValidationSupport(theJpaValidationSupportChain); + } + + @Bean + public BatchConfigurer batchConfigurer() { + return new NonPersistedBatchConfigurer(); + } + + @Autowired + private ConfigurableEnvironment configurableEnvironment; + + /** + * Customize the default/max page sizes for search results. You can set these however + * you want, although very large page sizes will require a lot of RAM. + */ + @Bean + public DatabaseBackedPagingProvider databaseBackedPagingProvider(AppProperties appProperties) { + DatabaseBackedPagingProvider pagingProvider = new DatabaseBackedPagingProvider(); + pagingProvider.setDefaultPageSize(appProperties.getDefault_page_size()); + pagingProvider.setMaximumPageSize(appProperties.getMax_page_size()); + return pagingProvider; + } + + @Bean + public IResourceSupportedSvc resourceSupportedSvc(IDaoRegistry theDaoRegistry) { + return new DaoRegistryResourceSupportedSvc(theDaoRegistry); + } + + @Bean(name = "myResourceCountsCache") + public ResourceCountCache resourceCountsCache(IFhirSystemDao theSystemDao) { + return ResourceCountCacheUtil.newResourceCountCache(theSystemDao); + } + + @Primary + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource myDataSource, ConfigurableListableBeanFactory myConfigurableListableBeanFactory, FhirContext theFhirContext) { + LocalContainerEntityManagerFactoryBean retVal = HapiEntityManagerFactoryUtil.newEntityManagerFactory(myConfigurableListableBeanFactory, theFhirContext); + retVal.setPersistenceUnitName("HAPI_PU"); + + try { + retVal.setDataSource(myDataSource); + } catch (Exception e) { + throw new ConfigurationException("Could not set the data source due to a configuration issue", e); + } + retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, myConfigurableListableBeanFactory)); + return retVal; + } + + @Bean + @Primary + public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { + JpaTransactionManager retVal = new JpaTransactionManager(); + retVal.setEntityManagerFactory(entityManagerFactory); + return retVal; + } + + @Bean + public IHSearchSortHelper hSearchSortHelper(ISearchParamRegistry mySearchParamRegistry) { + return new HSearchSortHelperImpl(mySearchParamRegistry); + } + + + @Bean + @ConditionalOnProperty(prefix = "hapi.fhir", name = ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR, havingValue = "true") + public RepositoryValidatingInterceptor repositoryValidatingInterceptor(IRepositoryValidationInterceptorFactory factory) { + return factory.buildUsingStoredStructureDefinitions(); + } + + @Bean + public LoggingInterceptor loggingInterceptor(AppProperties appProperties) { + + /* + * Add some logging for each request + */ + + LoggingInterceptor loggingInterceptor = new LoggingInterceptor(); + loggingInterceptor.setLoggerName(appProperties.getLogger().getName()); + loggingInterceptor.setMessageFormat(appProperties.getLogger().getFormat()); + loggingInterceptor.setErrorMessageFormat(appProperties.getLogger().getError_format()); + loggingInterceptor.setLogExceptions(appProperties.getLogger().getLog_exceptions()); + return loggingInterceptor; + } + + @Bean + @Primary + /* + This bean is currently necessary to override from MDM settings + */ + IMdmLinkDao mdmLinkDao() { + return new MdmLinkDaoJpaImpl(); + } + + + @Bean + @ConditionalOnProperty(prefix = "hapi.fhir", name = "cors") + public CorsInterceptor corsInterceptor(AppProperties appProperties) { + // Define your CORS configuration. This is an example + // showing a typical setup. You should customize this + // to your specific needs + ourLog.info("CORS is enabled on this server"); + CorsConfiguration config = new CorsConfiguration(); + config.addAllowedHeader(HttpHeaders.ORIGIN); + config.addAllowedHeader(HttpHeaders.ACCEPT); + config.addAllowedHeader(HttpHeaders.CONTENT_TYPE); + config.addAllowedHeader(HttpHeaders.AUTHORIZATION); + config.addAllowedHeader(HttpHeaders.CACHE_CONTROL); + config.addAllowedHeader("x-fhir-starter"); + config.addAllowedHeader("X-Requested-With"); + config.addAllowedHeader("Prefer"); + + List allAllowedCORSOrigins = appProperties.getCors().getAllowed_origin(); + allAllowedCORSOrigins.forEach(config::addAllowedOriginPattern); + ourLog.info("CORS allows the following origins: " + String.join(", ", allAllowedCORSOrigins)); + + config.addExposedHeader("Location"); + config.addExposedHeader("Content-Location"); + config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD")); + config.setAllowCredentials(appProperties.getCors().getAllow_Credentials()); + + // Create the interceptor and register it + return new CorsInterceptor(config); + + } + + @Bean + public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc) { + RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext()); + + List supportedResourceTypes = appProperties.getSupported_resource_types(); + + if (!supportedResourceTypes.isEmpty()) { + if (!supportedResourceTypes.contains("SearchParameter")) { + supportedResourceTypes.add("SearchParameter"); + } + daoRegistry.setSupportedResourceTypes(supportedResourceTypes); + } + + if (appProperties.getNarrative_enabled()) { + fhirSystemDao.getContext().setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator()); + } else { + fhirSystemDao.getContext().setNarrativeGenerator(new NullNarrativeGenerator()); + } + + if (appProperties.getMdm_enabled()) mdmProviderProvider.get().loadProvider(); + + fhirServer.registerProviders(resourceProviderFactory.createProviders()); + fhirServer.registerProvider(jpaSystemProvider); + fhirServer.setServerConformanceProvider(calculateConformanceProvider(fhirSystemDao, fhirServer, daoConfig, searchParamRegistry, theValidationSupport)); + + /* + * ETag Support + */ + + if (!appProperties.getEtag_support_enabled()) fhirServer.setETagSupport(ETagSupportEnum.DISABLED); + + + /* + * Default to JSON and pretty printing + */ + fhirServer.setDefaultPrettyPrint(appProperties.getDefault_pretty_print()); + + /* + * Default encoding + */ + fhirServer.setDefaultResponseEncoding(appProperties.getDefault_encoding()); + + /* + * This configures the server to page search results to and from + * the database, instead of only paging them to memory. This may mean + * a performance hit when performing searches that return lots of results, + * but makes the server much more scalable. + */ + + fhirServer.setPagingProvider(databaseBackedPagingProvider); + + /* + * This interceptor formats the output using nice colourful + * HTML output when the request is detected to come from a + * browser. + */ + fhirServer.registerInterceptor(new ResponseHighlighterInterceptor()); + + if (appProperties.getFhirpath_interceptor_enabled()) { + fhirServer.registerInterceptor(new FhirPathFilterInterceptor()); + } + + fhirServer.registerInterceptor(loggingInterceptor); + + /* + * If you are hosting this server at a specific DNS name, the server will try to + * figure out the FHIR base URL based on what the web container tells it, but + * this doesn't always work. If you are setting links in your search bundles that + * just refer to "localhost", you might want to use a server address strategy: + */ + String serverAddress = appProperties.getServer_address(); + if (!Strings.isNullOrEmpty(serverAddress)) { + fhirServer.setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress)); + } else if (appProperties.getUse_apache_address_strategy()) { + boolean useHttps = appProperties.getUse_apache_address_strategy_https(); + fhirServer.setServerAddressStrategy(useHttps ? ApacheProxyAddressStrategy.forHttps() : ApacheProxyAddressStrategy.forHttp()); + } else { + fhirServer.setServerAddressStrategy(new IncomingRequestAddressStrategy()); + } + + /* + * If you are using DSTU3+, you may want to add a terminology uploader, which allows + * uploading of external terminologies such as Snomed CT. Note that this uploader + * does not have any security attached (any anonymous user may use it by default) + * so it is a potential security vulnerability. Consider using an AuthorizationInterceptor + * with this feature. + */ + if (fhirSystemDao.getContext().getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { // <-- ENABLED RIGHT NOW + fhirServer.registerProvider(terminologyUploaderProvider.get()); + } + + // If you want to enable the $trigger-subscription operation to allow + // manual triggering of a subscription delivery, enable this provider + if (true) { // <-- ENABLED RIGHT NOW + fhirServer.registerProvider(subscriptionTriggeringProvider.get()); + } + + corsInterceptor.ifPresent(fhirServer::registerInterceptor); + + if (appProperties.getSubscription() != null) { + // Subscription debug logging + fhirServer.registerInterceptor(new SubscriptionDebugLogInterceptor()); + } + + if (appProperties.getAllow_cascading_deletes()) { + CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(fhirSystemDao.getContext(), daoRegistry, interceptorBroadcaster); + fhirServer.registerInterceptor(cascadingDeleteInterceptor); + } + + // Binary Storage + if (appProperties.getBinary_storage_enabled() && binaryAccessProvider.isPresent()) { + fhirServer.registerProvider(binaryAccessProvider.get()); + fhirServer.registerInterceptor(binaryStorageInterceptor); + } + + // Validation + + if (validatorModule != null) { + if (appProperties.getValidation().getRequests_enabled()) { + RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor(); + interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR); + interceptor.setValidatorModules(Collections.singletonList(validatorModule)); + fhirServer.registerInterceptor(interceptor); + } + if (appProperties.getValidation().getResponses_enabled()) { + ResponseValidatingInterceptor interceptor = new ResponseValidatingInterceptor(); + interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR); + interceptor.setValidatorModules(Collections.singletonList(validatorModule)); + fhirServer.registerInterceptor(interceptor); + } + } + + // GraphQL + if (appProperties.getGraphql_enabled()) { + if (fhirSystemDao.getContext().getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { + fhirServer.registerProvider(graphQLProvider.get()); + } + } + + if (appProperties.getOpenapi_enabled()) { + fhirServer.registerInterceptor(new OpenApiInterceptor()); + } + + // Bulk Export + if (appProperties.getBulk_export_enabled()) { + fhirServer.registerProvider(bulkDataExportProvider); + } + + //Bulk Import + if (appProperties.getBulk_import_enabled()) { + fhirServer.registerProvider(bulkDataImportProvider); + } + + + // valueSet Operations i.e $expand + fhirServer.registerProvider(theValueSetOperationProvider); + + //reindex Provider $reindex + fhirServer.registerProvider(reindexProvider); + + // Partitioning + if (appProperties.getPartitioning() != null) { + fhirServer.registerInterceptor(new RequestTenantPartitionInterceptor()); + fhirServer.setTenantIdentificationStrategy(new UrlBaseTenantIdentificationStrategy()); + fhirServer.registerProviders(partitionManagementProvider); + } + + + repositoryValidatingInterceptor.ifPresent(fhirServer::registerInterceptor); + + if (appProperties.getImplementationGuides() != null) { + Map guides = appProperties.getImplementationGuides(); + for (Map.Entry guide : guides.entrySet()) { + PackageInstallationSpec packageInstallationSpec = new PackageInstallationSpec().setPackageUrl(guide.getValue().getUrl()).setName(guide.getValue().getName()).setVersion(guide.getValue().getVersion()).setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL); + if (appProperties.getInstall_transitive_ig_dependencies()) { + packageInstallationSpec.setFetchDependencies(true); + packageInstallationSpec.setDependencyExcludes(ImmutableList.of("hl7.fhir.r2.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core", "hl7.fhir.r5.core")); + } + packageInstallerSvc.install(packageInstallationSpec); + } + } + + return fhirServer; + } + + public static IServerConformanceProvider calculateConformanceProvider(IFhirSystemDao fhirSystemDao, RestfulServer fhirServer, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport) { + FhirVersionEnum fhirVersion = fhirSystemDao.getContext().getVersion().getVersion(); + if (fhirVersion == FhirVersionEnum.DSTU2) { + + JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(fhirServer, fhirSystemDao, daoConfig); + confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server"); + return confProvider; + } else if (fhirVersion == FhirVersionEnum.DSTU3) { + + JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(fhirServer, fhirSystemDao, daoConfig, searchParamRegistry); + confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server"); + return confProvider; + } else if (fhirVersion == FhirVersionEnum.R4) { + + JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, daoConfig, searchParamRegistry, theValidationSupport); + confProvider.setImplementationDescription("HAPI FHIR R4 Server"); + return confProvider; + } else if (fhirVersion == FhirVersionEnum.R5) { + + JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, daoConfig, searchParamRegistry, theValidationSupport); + confProvider.setImplementationDescription("HAPI FHIR R5 Server"); + return confProvider; + } else { + throw new IllegalStateException(); + } + } +} + diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/IRepositoryValidationInterceptorFactory.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/IRepositoryValidationInterceptorFactory.java similarity index 63% rename from src/main/java/ca/uhn/fhir/jpa/starter/IRepositoryValidationInterceptorFactory.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/validation/IRepositoryValidationInterceptorFactory.java index 13262a1cf1c..67a40c7761c 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/IRepositoryValidationInterceptorFactory.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/IRepositoryValidationInterceptorFactory.java @@ -1,8 +1,10 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common.validation; import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; public interface IRepositoryValidationInterceptorFactory { + + String ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR = "enable_repository_validating_interceptor"; RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions(); RepositoryValidatingInterceptor build(); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java similarity index 84% rename from src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryDstu3.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java index a68ae3eb2f0..f8874b31a50 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common.validation; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; @@ -19,6 +19,8 @@ import java.util.Map; import java.util.stream.Collectors; +import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR; + /** * This class can be customized to enable the {@link RepositoryValidatingInterceptor} * on this server. @@ -26,7 +28,7 @@ * The enable_repository_validating_interceptor property must be enabled in application.yaml * in order to use this class. */ -@ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") +@ConditionalOnProperty(prefix = "hapi.fhir", name = ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR, havingValue = "true") @Configuration @Conditional(OnDSTU3Condition.class) public class RepositoryValidationInterceptorFactoryDstu3 implements IRepositoryValidationInterceptorFactory { @@ -50,10 +52,9 @@ public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() { .map(StructureDefinition.class::cast) .collect(Collectors.groupingBy(StructureDefinition::getType)); - structureDefintions.entrySet().forEach(structureDefinitionListEntry -> - { - String[] urls = structureDefinitionListEntry.getValue().stream().map(StructureDefinition::getUrl).toArray(String[]::new); - repositoryValidatingRuleBuilder.forResourcesOfType(structureDefinitionListEntry.getKey()).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); + structureDefintions.forEach((key, value) -> { + String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new); + repositoryValidatingRuleBuilder.forResourcesOfType(key).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); }); List rules = repositoryValidatingRuleBuilder.build(); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4.java similarity index 84% rename from src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR4.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4.java index a563d3cb354..c4fca012c6b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common.validation; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; @@ -19,6 +19,8 @@ import java.util.Map; import java.util.stream.Collectors; +import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR; + /** * This class can be customized to enable the {@link ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor} * on this server. @@ -26,7 +28,7 @@ * The enable_repository_validating_interceptor property must be enabled in application.yaml * in order to use this class. */ -@ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") +@ConditionalOnProperty(prefix = "hapi.fhir", name = ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR, havingValue = "true") @Configuration @Conditional(OnR4Condition.class) public class RepositoryValidationInterceptorFactoryR4 implements IRepositoryValidationInterceptorFactory { @@ -51,10 +53,9 @@ public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() { .map(StructureDefinition.class::cast) .collect(Collectors.groupingBy(StructureDefinition::getType)); - structureDefintions.entrySet().forEach(structureDefinitionListEntry -> - { - String[] urls = structureDefinitionListEntry.getValue().stream().map(StructureDefinition::getUrl).toArray(String[]::new); - repositoryValidatingRuleBuilder.forResourcesOfType(structureDefinitionListEntry.getKey()).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); + structureDefintions.forEach((key, value) -> { + String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new); + repositoryValidatingRuleBuilder.forResourcesOfType(key).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); }); List rules = repositoryValidatingRuleBuilder.build(); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR5.java similarity index 84% rename from src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR5.java rename to src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR5.java index 7702ef0baf2..594800dd2d6 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR5.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.common.validation; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; @@ -19,6 +19,8 @@ import java.util.Map; import java.util.stream.Collectors; +import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR; + /** * This class can be customized to enable the {@link RepositoryValidatingInterceptor} * on this server. @@ -26,7 +28,7 @@ * The enable_repository_validating_interceptor property must be enabled in application.yaml * in order to use this class. */ -@ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") +@ConditionalOnProperty(prefix = "hapi.fhir", name = ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR, havingValue = "true") @Configuration @Conditional(OnR5Condition.class) public class RepositoryValidationInterceptorFactoryR5 implements IRepositoryValidationInterceptorFactory { @@ -50,10 +52,9 @@ public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() { .map(StructureDefinition.class::cast) .collect(Collectors.groupingBy(StructureDefinition::getType)); - structureDefintions.entrySet().forEach(structureDefinitionListEntry -> - { - String[] urls = structureDefinitionListEntry.getValue().stream().map(StructureDefinition::getUrl).toArray(String[]::new); - repositoryValidatingRuleBuilder.forResourcesOfType(structureDefinitionListEntry.getKey()).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); + structureDefintions.forEach((key, value) -> { + String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new); + repositoryValidatingRuleBuilder.forResourcesOfType(key).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); }); List rules = repositoryValidatingRuleBuilder.build(); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cql/CqlConfigCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/cql/CqlConfigCondition.java index 0a5f7f41515..38622ba9d89 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/cql/CqlConfigCondition.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/cql/CqlConfigCondition.java @@ -9,7 +9,6 @@ public class CqlConfigCondition implements Condition { @Override public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) { String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cql_enabled"); - boolean enabled = Boolean.parseBoolean(property); - return enabled; + return Boolean.parseBoolean(property); } } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java b/src/main/java/ca/uhn/fhir/jpa/starter/util/EnvironmentHelper.java similarity index 95% rename from src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java rename to src/main/java/ca/uhn/fhir/jpa/starter/util/EnvironmentHelper.java index 732705ac521..41bb556c4c3 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/EnvironmentHelper.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/util/EnvironmentHelper.java @@ -1,9 +1,10 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.util; import ca.uhn.fhir.jpa.config.HapiFhirLocalContainerEntityManagerFactoryBean; import ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers; import ca.uhn.fhir.jpa.search.elastic.ElasticsearchHibernatePropertiesBuilder; import org.apache.lucene.util.Version; +import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy; import org.hibernate.cfg.AvailableSettings; import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchBackendSettings; import org.hibernate.search.backend.elasticsearch.index.IndexStatus; @@ -27,6 +28,8 @@ import java.util.Map; import java.util.Properties; +import static java.util.Objects.requireNonNullElse; + public class EnvironmentHelper { public static Properties getHibernateProperties(ConfigurableEnvironment environment, @@ -41,7 +44,7 @@ public static Properties getHibernateProperties(ConfigurableEnvironment environm //Spring Boot Autoconfiguration defaults properties.putIfAbsent(AvailableSettings.SCANNER, "org.hibernate.boot.archive.scan.internal.DisabledScanner"); properties.putIfAbsent(AvailableSettings.IMPLICIT_NAMING_STRATEGY, SpringImplicitNamingStrategy.class.getName()); - properties.putIfAbsent(AvailableSettings.PHYSICAL_NAMING_STRATEGY, SpringPhysicalNamingStrategy.class.getName()); + properties.putIfAbsent(AvailableSettings.PHYSICAL_NAMING_STRATEGY, CamelCaseToUnderscoresNamingStrategy.class.getName()); //TODO The bean factory should be added as parameter but that requires that it can be injected from the entityManagerFactory bean from xBaseConfig //properties.putIfAbsent(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory)); @@ -102,18 +105,6 @@ public static Properties getHibernateProperties(ConfigurableEnvironment environm return properties; } - //TODO Removed when we're up on Java 11 - private static T requireNonNullElse(T obj, T defaultObj) { - return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj"); - } - - //TODO Removed when we're up on Java 11 - private static T requireNonNull(T obj, String message) { - if (obj == null) - throw new NullPointerException(message); - return obj; - } - public static String getElasticsearchServerUrl(ConfigurableEnvironment environment) { return environment.getProperty("elasticsearch.rest_url", String.class); } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/JpaHibernatePropertiesProvider.java b/src/main/java/ca/uhn/fhir/jpa/starter/util/JpaHibernatePropertiesProvider.java similarity index 96% rename from src/main/java/ca/uhn/fhir/jpa/starter/JpaHibernatePropertiesProvider.java rename to src/main/java/ca/uhn/fhir/jpa/starter/util/JpaHibernatePropertiesProvider.java index d090b9c29c7..83125a99e0f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/JpaHibernatePropertiesProvider.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/util/JpaHibernatePropertiesProvider.java @@ -1,4 +1,4 @@ -package ca.uhn.fhir.jpa.starter; +package ca.uhn.fhir.jpa.starter.util; import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.jpa.config.HibernatePropertiesProvider; diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index b8c322ca8f6..b1baff58e91 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -89,7 +89,7 @@ hapi: # default_pretty_print: true # default_page_size: 20 # delete_expunge_enabled: true - # enable_repository_validating_interceptor: false + # enable_repository_validating_interceptor: true # enable_index_missing_fields: false # enable_index_of_type: true # enable_index_contained_resource: false diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/Demo.java b/src/test/java/ca/uhn/fhir/jpa/starter/Demo.java deleted file mode 100644 index d46094360ee..00000000000 --- a/src/test/java/ca/uhn/fhir/jpa/starter/Demo.java +++ /dev/null @@ -1,20 +0,0 @@ -package ca.uhn.fhir.jpa.starter; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration; -import org.springframework.boot.web.servlet.ServletComponentScan; - -@ServletComponentScan(basePackageClasses = {JpaRestfulServer.class}) -@SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class) -public class Demo { - - public static void main(String[] args) { - - System.setProperty("spring.profiles.active", "r4"); - System.setProperty("spring.batch.job.enabled", "false"); - SpringApplication.run(Demo.class, args); - - //Server is now accessible at eg. http://localhost:8080/fhir/metadata - } -} diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index b4ca6c3cec3..0dfcf83da59 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -113,7 +113,7 @@ public void testCQLEvaluateMeasureEXM104() throws IOException { .execute(); List response = outParams.getParameter(); - Assert.assertTrue(!response.isEmpty()); + Assert.assertFalse(response.isEmpty()); Parameters.ParametersParameterComponent component = response.get(0); Assert.assertTrue(component.getResource() instanceof MeasureReport); MeasureReport report = (MeasureReport) component.getResource(); @@ -149,7 +149,7 @@ private int loadDataFromDirectory(String theDirectoryName) throws IOException { private Bundle loadBundle(String theLocation, FhirContext theCtx, IGenericClient theClient) throws IOException { String json = stringFromResource(theLocation); Bundle bundle = (Bundle) theCtx.newJsonParser().parseResource(json); - Bundle result = (Bundle) theClient.transaction().withBundle(bundle).execute(); + Bundle result = theClient.transaction().withBundle(bundle).execute(); return result; } diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 7b0548747a7..47834f50c0e 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -1,15 +1,11 @@ package ca.uhn.fhir.jpa.starter; import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.jpa.partition.SystemRequestDetails; -import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.MethodOutcome; -import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; - import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.WebSocketClient; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java b/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java index 9318a0aee6b..7734a23c6f2 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java @@ -15,10 +15,10 @@ public class SocketImplementation { private static final Logger ourLog = org.slf4j.LoggerFactory.getLogger(SocketImplementation.class); - private String myCriteria; + private final String myCriteria; protected String myError; protected boolean myGotBound; - private List myMessages = new ArrayList(); + private final List myMessages = new ArrayList(); protected int myPingCount; protected String mySubsId; private Session session; From 43d50a0c71bb5c3194c05a17db74386773c518f2 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Tue, 13 Sep 2022 18:54:14 +0200 Subject: [PATCH 108/192] Extract IG loading (#426) --- .../OnImplementationGuidesPresent.java | 18 +++++++++ .../starter/common/FhirServerConfigDstu2.java | 21 ++++++++-- .../jpa/starter/common/StarterJpaConfig.java | 40 ++++++++++++++----- .../fhir/jpa/starter/ExampleServerR4IT.java | 2 + 4 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnImplementationGuidesPresent.java diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnImplementationGuidesPresent.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnImplementationGuidesPresent.java new file mode 100644 index 00000000000..7b11df1618e --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnImplementationGuidesPresent.java @@ -0,0 +1,18 @@ +package ca.uhn.fhir.jpa.starter.annotations; + +import ca.uhn.fhir.jpa.starter.AppProperties; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class OnImplementationGuidesPresent implements Condition { + @Override + public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) { + + AppProperties config = Binder.get(conditionContext.getEnvironment()).bind("hapi.fhir", AppProperties.class).orElse(null); + if (config == null) return false; + if (config.getImplementationGuides() == null) return false; + return !config.getImplementationGuides().isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java index 151df82898f..cedf16997eb 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java @@ -2,15 +2,28 @@ import ca.uhn.fhir.jpa.config.JpaDstu2Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU2Condition; +import ca.uhn.fhir.jpa.term.TermCodeSystemStorageSvcImpl; +import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl; +import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; +import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; +import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration @Conditional(OnDSTU2Condition.class) -@Import({ - StarterJpaConfig.class, - JpaDstu2Config.class -}) +@Import({StarterJpaConfig.class, JpaDstu2Config.class}) public class FhirServerConfigDstu2 { + @Bean + public ITermLoaderSvc termLoaderService(ITermDeferredStorageSvc theDeferredStorageSvc, ITermCodeSystemStorageSvc theCodeSystemStorageSvc) { + return new TermLoaderSvcImpl(theDeferredStorageSvc, theCodeSystemStorageSvc); + } + + @Bean + public ITermCodeSystemStorageSvc termCodeSystemStorageSvc() { + return new TermCodeSystemStorageSvcImpl(); + } + } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index b2f108a084e..5f311ddf527 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -1,7 +1,10 @@ package ca.uhn.fhir.jpa.starter.common; +import ca.uhn.fhir.batch2.coordinator.JobDefinitionRegistry; import ca.uhn.fhir.batch2.jobs.imprt.BulkDataImportProvider; +import ca.uhn.fhir.batch2.jobs.reindex.ReindexJobParameters; import ca.uhn.fhir.batch2.jobs.reindex.ReindexProvider; +import ca.uhn.fhir.batch2.model.JobDefinition; import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; @@ -35,6 +38,7 @@ import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc; import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl; import ca.uhn.fhir.jpa.starter.AppProperties; +import ca.uhn.fhir.jpa.starter.annotations.OnImplementationGuidesPresent; import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory; import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper; import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor; @@ -62,6 +66,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.env.ConfigurableEnvironment; @@ -177,6 +182,27 @@ public LoggingInterceptor loggingInterceptor(AppProperties appProperties) { return loggingInterceptor; } + @Bean("packageInstaller") + @Primary + @Conditional(OnImplementationGuidesPresent.class) + public IPackageInstallerSvc packageInstaller(AppProperties appProperties, JobDefinition reindexJobParametersJobDefinition, JobDefinitionRegistry jobDefinitionRegistry, IPackageInstallerSvc packageInstallerSvc) + { + jobDefinitionRegistry.addJobDefinitionIfNotRegistered(reindexJobParametersJobDefinition); + + if (appProperties.getImplementationGuides() != null) { + Map guides = appProperties.getImplementationGuides(); + for (Map.Entry guide : guides.entrySet()) { + PackageInstallationSpec packageInstallationSpec = new PackageInstallationSpec().setPackageUrl(guide.getValue().getUrl()).setName(guide.getValue().getName()).setVersion(guide.getValue().getVersion()).setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL); + if (appProperties.getInstall_transitive_ig_dependencies()) { + packageInstallationSpec.setFetchDependencies(true); + packageInstallationSpec.setDependencyExcludes(ImmutableList.of("hl7.fhir.r2.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core", "hl7.fhir.r5.core")); + } + packageInstallerSvc.install(packageInstallationSpec); + } + } + return packageInstallerSvc; + } + @Bean @Primary /* @@ -222,6 +248,8 @@ public CorsInterceptor corsInterceptor(AppProperties appProperties) { public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc) { RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext()); + + List supportedResourceTypes = appProperties.getSupported_resource_types(); if (!supportedResourceTypes.isEmpty()) { @@ -388,17 +416,7 @@ public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProper repositoryValidatingInterceptor.ifPresent(fhirServer::registerInterceptor); - if (appProperties.getImplementationGuides() != null) { - Map guides = appProperties.getImplementationGuides(); - for (Map.Entry guide : guides.entrySet()) { - PackageInstallationSpec packageInstallationSpec = new PackageInstallationSpec().setPackageUrl(guide.getValue().getUrl()).setName(guide.getValue().getName()).setVersion(guide.getValue().getVersion()).setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL); - if (appProperties.getInstall_transitive_ig_dependencies()) { - packageInstallationSpec.setFetchDependencies(true); - packageInstallationSpec.setDependencyExcludes(ImmutableList.of("hl7.fhir.r2.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core", "hl7.fhir.r5.core")); - } - packageInstallerSvc.install(packageInstallationSpec); - } - } + return fhirServer; } diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 47834f50c0e..27a8c21be44 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -37,6 +37,8 @@ "hapi.fhir.fhir_version=r4", "hapi.fhir.subscription.websocket_enabled=true", "hapi.fhir.mdm_enabled=true", + "hapi.fhir.implementationguides.dk-core.name=hl7.fhir.dk.core", + "hapi.fhir.implementationguides.dk-core.version=1.1.0", // Override is currently required when using MDM as the construction of the MDM // beans are ambiguous as they are constructed multiple places. This is evident // when running in a spring boot environment From 38f37e4db04d3790432f70b1ccf4fb1329c74b36 Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Thu, 15 Sep 2022 13:10:22 +0200 Subject: [PATCH 109/192] added back lost config entry: allowed_bundle_types (#427) * added back lost config entry * disabled entry --- src/main/resources/application.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index b1baff58e91..a651fa9831f 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -78,6 +78,10 @@ hapi: # supported_resource_types: # - Patient # - Observation + ################################################## + # Allowed Bundle Types for persistence (defaults are: COLLECTION,DOCUMENT,MESSAGE) + ################################################## + # allowed_bundle_types: COLLECTION,DOCUMENT,MESSAGE,TRANSACTION,TRANSACTIONRESPONSE,BATCH,BATCHRESPONSE,HISTORY,SEARCHSET # allow_cascading_deletes: true # allow_contains_searches: true # allow_external_references: true From 5c1f99bf188de68dcf3dfc7beb3f38b58be75995 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Sep 2022 13:25:21 +0000 Subject: [PATCH 110/192] Bump snakeyaml from 1.30 to 1.31 Bumps [snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) from 1.30 to 1.31. - [Commits](https://bitbucket.org/snakeyaml/snakeyaml/branches/compare/snakeyaml-1.31..snakeyaml-1.30) --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3b2596f6f54..d1eb03b2c87 100644 --- a/pom.xml +++ b/pom.xml @@ -169,7 +169,7 @@ org.yaml snakeyaml - 1.30 + 1.31 From 3d03cd00c56f48a1115adce5b266fe9c3f157109 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Wed, 28 Sep 2022 22:51:57 +0200 Subject: [PATCH 111/192] fix: configuration of cors Refs: #430 --- .../jpa/starter/annotations/OnCorsPresent.java | 18 ++++++++++++++++++ .../jpa/starter/common/StarterJpaConfig.java | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnCorsPresent.java diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnCorsPresent.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnCorsPresent.java new file mode 100644 index 00000000000..e4a44d7c90f --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnCorsPresent.java @@ -0,0 +1,18 @@ +package ca.uhn.fhir.jpa.starter.annotations; + +import ca.uhn.fhir.jpa.starter.AppProperties; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class OnCorsPresent implements Condition { + @Override + public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) { + + AppProperties config = Binder.get(conditionContext.getEnvironment()).bind("hapi.fhir", AppProperties.class).orElse(null); + if (config == null) return false; + if (config.getCors() == null) return false; + return true; + } +} \ No newline at end of file diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 5f311ddf527..5ff3e699c8a 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -38,6 +38,7 @@ import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc; import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl; import ca.uhn.fhir.jpa.starter.AppProperties; +import ca.uhn.fhir.jpa.starter.annotations.OnCorsPresent; import ca.uhn.fhir.jpa.starter.annotations.OnImplementationGuidesPresent; import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory; import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper; @@ -214,7 +215,7 @@ IMdmLinkDao mdmLinkDao() { @Bean - @ConditionalOnProperty(prefix = "hapi.fhir", name = "cors") + @Conditional(OnCorsPresent.class) public CorsInterceptor corsInterceptor(AppProperties appProperties) { // Define your CORS configuration. This is an example // showing a typical setup. You should customize this From 531d2557820b5ecbe725a9142dd231413a6dd716 Mon Sep 17 00:00:00 2001 From: Thomas Papke Date: Sat, 1 Oct 2022 17:19:01 +0200 Subject: [PATCH 112/192] Proper close DB connection after dialect was resolved (#435) --- .../jpa/starter/util/JpaHibernatePropertiesProvider.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/util/JpaHibernatePropertiesProvider.java b/src/main/java/ca/uhn/fhir/jpa/starter/util/JpaHibernatePropertiesProvider.java index 83125a99e0f..696f34842e2 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/util/JpaHibernatePropertiesProvider.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/util/JpaHibernatePropertiesProvider.java @@ -8,6 +8,8 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import javax.sql.DataSource; + +import java.sql.Connection; import java.sql.SQLException; public class JpaHibernatePropertiesProvider extends HibernatePropertiesProvider { @@ -16,9 +18,9 @@ public class JpaHibernatePropertiesProvider extends HibernatePropertiesProvider public JpaHibernatePropertiesProvider(LocalContainerEntityManagerFactoryBean myEntityManagerFactory) { DataSource connection = myEntityManagerFactory.getDataSource(); - try { + try ( Connection dbConnection = connection.getConnection()){ dialect = new StandardDialectResolver() - .resolveDialect(new DatabaseMetaDataDialectResolutionInfoAdapter(connection.getConnection().getMetaData())); + .resolveDialect(new DatabaseMetaDataDialectResolutionInfoAdapter(dbConnection.getMetaData())); } catch (SQLException sqlException) { throw new ConfigurationException(sqlException.getMessage(), sqlException); } From 7a72c86a637548d3bb1fb7ee69fe7c5d7884c8c8 Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Thu, 6 Oct 2022 14:26:43 +0200 Subject: [PATCH 113/192] removed duplicated and wrong subscription code (#440) --- .../fhir/jpa/starter/common/FhirServerConfigCommon.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java index 4dd4412c77a..60cf2d8c355 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java @@ -202,15 +202,6 @@ public ModelConfig modelConfig(AppProperties appProperties, DaoConfig daoConfig) if(appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) modelConfig.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom()); - // You can enable these if you want to support Subscriptions from your server - if (appProperties.getSubscription() != null && appProperties.getSubscription().getResthook_enabled() != null) { - modelConfig.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.RESTHOOK); - } - - if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) { - modelConfig.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.EMAIL); - } - modelConfig.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); modelConfig.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); From a95c40dd05af40434a86a7b03c475e4142dd3743 Mon Sep 17 00:00:00 2001 From: patrick-werner Date: Thu, 6 Oct 2022 16:34:29 +0200 Subject: [PATCH 114/192] fixed SubscriptionDebugLogInterceptor adding logic --- .../java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 5ff3e699c8a..19bba57fa5b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -346,7 +346,7 @@ public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProper corsInterceptor.ifPresent(fhirServer::registerInterceptor); - if (appProperties.getSubscription() != null) { + if (daoConfig.getSupportedSubscriptionTypes().size() > 0) { // Subscription debug logging fhirServer.registerInterceptor(new SubscriptionDebugLogInterceptor()); } From d61c8a5f96aca475b6b5ccc8aedef64614127f7b Mon Sep 17 00:00:00 2001 From: rti Date: Tue, 11 Oct 2022 20:02:45 +0200 Subject: [PATCH 115/192] switch to postgres db (#444) --- docker-compose.yml | 19 ++++++++----------- src/main/resources/application.yaml | 11 +++++------ 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index fcf1f2b83ef..0fe0e457bec 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,18 +6,15 @@ services: restart: on-failure ports: - "8080:8080" - hapi-fhir-mysql: - image: mysql:latest - container_name: hapi-fhir-mysql - #https://dev.mysql.com/doc/refman/8.0/en/identifier-case-sensitivity.html - command: --lower_case_table_names=1 + hapi-fhir-postgres: + image: postgres:13-alpine + container_name: hapi-fhir-postgres restart: always environment: - MYSQL_DATABASE: 'hapi' - MYSQL_USER: 'admin' - MYSQL_PASSWORD: 'admin' - MYSQL_ROOT_PASSWORD: 'admin' + POSTGRES_DB: "hapi" + POSTGRES_USER: "admin" + POSTGRES_PASSWORD: "admin" volumes: - - hapi-fhir-mysql:/var/lib/mysql + - hapi-fhir-postgres:/var/lib/postgresql/data volumes: - hapi-fhir-mysql: + hapi-fhir-postgres: diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index a651fa9831f..2d84609cfed 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -14,11 +14,10 @@ spring: check-location: false baselineOnMigrate: true datasource: - url: 'jdbc:h2:file:./target/database/h2' - #url: jdbc:h2:mem:test_mem - username: sa - password: null - driverClassName: org.h2.Driver + url: jdbc:postgresql://hapi-fhir-postgres:5432/hapi + username: admin + password: admin + driverClassName: org.postgresql.Driver max-active: 15 # database connection pool size @@ -32,7 +31,7 @@ spring: #If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect #If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect - hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect + hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect # hibernate.hbm2ddl.auto: update # hibernate.jdbc.batch_size: 20 # hibernate.cache.use_query_cache: false From a1e2ca3ae13d24e7f66b856ac251c39de02d3eb5 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Thu, 27 Oct 2022 08:21:08 +0200 Subject: [PATCH 116/192] revering to H2 (#449) --- src/main/resources/application.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 2d84609cfed..a651fa9831f 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -14,10 +14,11 @@ spring: check-location: false baselineOnMigrate: true datasource: - url: jdbc:postgresql://hapi-fhir-postgres:5432/hapi - username: admin - password: admin - driverClassName: org.postgresql.Driver + url: 'jdbc:h2:file:./target/database/h2' + #url: jdbc:h2:mem:test_mem + username: sa + password: null + driverClassName: org.h2.Driver max-active: 15 # database connection pool size @@ -31,7 +32,7 @@ spring: #If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect #If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect - hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect + hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect # hibernate.hbm2ddl.auto: update # hibernate.jdbc.batch_size: 20 # hibernate.cache.use_query_cache: false From f8d749ae28dbccc173a18a28269456e87b1ea6a4 Mon Sep 17 00:00:00 2001 From: jmarchionatto <60409882+jmarchionatto@users.noreply.github.com> Date: Sat, 12 Nov 2022 08:16:38 -0500 Subject: [PATCH 117/192] Tracking Hapi 6.2-PRE releases (#408) * Tracking branch for 6.1 pre-releases. * Update to 6.1.0-PRE3-SNAPSHOT * Adjust for hapi-fhir namespace changes and version * Adjust version to include new hapi-fhir HSearch fast path feature * Bump hapi PRE * Update to PRE16 * Adjust configuration class name to HAPI-FHIR HSearch namespace consolidation. Add commented out sample properties for lucene and elastic. Move batch.job.enabled property under spring: prefix to have it considered. * Adjust enumeration renaming * Repoint FHIR 6.2.0-PRE1-SNAPSHOT * Add missing Bean to starter configuration * Update to hapi-fhir 6.2.0-PRE2-SNAPSHOT * Update application-integrationtest.yaml and rename it as application.yaml to make test configuration independent of prod. * Update to hapi-fhir 6.2.0-PRE5-SNAPSHOT * Update dep * Bump version fix failures * Remove dead import * Fix up * remove batch refs Co-authored-by: Michael Buckley Co-authored-by: michaelabuckley Co-authored-by: juan.marchionatto Co-authored-by: Tadgh --- pom.xml | 22 +-- .../common/FhirServerConfigCommon.java | 1 - .../starter/common/FhirServerConfigDstu2.java | 5 +- .../starter/common/FhirServerConfigDstu3.java | 2 +- .../starter/common/FhirServerConfigR4.java | 2 +- .../jpa/starter/common/StarterJpaConfig.java | 24 ++- src/main/resources/application.yaml | 21 +- .../jpa/starter/ElasticsearchLastNR4IT.java | 1 - .../jpa/starter/ExampleServerDstu2IT.java | 1 - .../jpa/starter/ExampleServerDstu3IT.java | 1 - .../fhir/jpa/starter/ExampleServerR4IT.java | 1 - .../fhir/jpa/starter/ExampleServerR5IT.java | 3 +- .../jpa/starter/MultitenantServerR4IT.java | 1 - .../application-integrationtest.yaml | 108 ---------- src/test/resources/application.yaml | 186 ++++++++++++++++++ 15 files changed, 219 insertions(+), 160 deletions(-) delete mode 100644 src/test/resources/application-integrationtest.yaml create mode 100644 src/test/resources/application.yaml diff --git a/pom.xml b/pom.xml index d1eb03b2c87..7293b3046bc 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 - + - @@ -566,8 +552,8 @@ - - + + jetty diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java index 60cf2d8c355..a80524eba70 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java @@ -137,7 +137,6 @@ public DaoConfig daoConfig(AppProperties appProperties) { daoConfig.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size()); } - daoConfig.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled()); daoConfig.getModelConfig().setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); daoConfig.getModelConfig().setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java index cedf16997eb..baf5044ce12 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java @@ -14,7 +14,10 @@ @Configuration @Conditional(OnDSTU2Condition.class) -@Import({StarterJpaConfig.class, JpaDstu2Config.class}) +@Import({ + JpaDstu2Config.class, + StarterJpaConfig.class +}) public class FhirServerConfigDstu2 { @Bean public ITermLoaderSvc termLoaderService(ITermDeferredStorageSvc theDeferredStorageSvc, ITermCodeSystemStorageSvc theCodeSystemStorageSvc) { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java index e0056bc1912..0e0c76358d1 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java @@ -10,8 +10,8 @@ @Configuration @Conditional(OnDSTU3Condition.class) @Import({ - StarterJpaConfig.class, JpaDstu3Config.class, + StarterJpaConfig.class, StarterCqlDstu3Config.class, ElasticsearchConfig.class}) public class FhirServerConfigDstu3 { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java index 4c212ef2bce..6ee7a990846 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java @@ -10,8 +10,8 @@ @Configuration @Conditional(OnR4Condition.class) @Import({ - StarterJpaConfig.class, JpaR4Config.class, + StarterJpaConfig.class, StarterCqlR4Config.class, ElasticsearchConfig.class }) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 19bba57fa5b..ed150154685 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -12,9 +12,9 @@ import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.jpa.api.IDaoRegistry; import ca.uhn.fhir.jpa.api.config.DaoConfig; +import ca.uhn.fhir.jpa.api.config.ThreadPoolFactoryConfig; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; -import ca.uhn.fhir.jpa.batch.config.NonPersistedBatchConfigurer; import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor; import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider; import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider; @@ -26,6 +26,8 @@ import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDaoJpaImpl; import ca.uhn.fhir.jpa.dao.search.HSearchSortHelperImpl; import ca.uhn.fhir.jpa.dao.search.IHSearchSortHelper; +import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService; +import ca.uhn.fhir.jpa.delete.ThreadSafeResourceDeleterSvc; import ca.uhn.fhir.jpa.graphql.GraphQLProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; @@ -62,14 +64,10 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport; -import org.springframework.batch.core.configuration.annotation.BatchConfigurer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Conditional; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.*; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.http.HttpHeaders; import org.springframework.orm.jpa.JpaTransactionManager; @@ -83,6 +81,9 @@ import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR; @Configuration +@Import( + ThreadPoolFactoryConfig.class +) public class StarterJpaConfig { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StarterJpaConfig.class); @@ -103,10 +104,6 @@ public CachingValidationSupport validationSupportChain(JpaValidationSupportChain return ValidationSupportConfigUtil.newCachingValidationSupport(theJpaValidationSupportChain); } - @Bean - public BatchConfigurer batchConfigurer() { - return new NonPersistedBatchConfigurer(); - } @Autowired private ConfigurableEnvironment configurableEnvironment; @@ -123,6 +120,7 @@ public DatabaseBackedPagingProvider databaseBackedPagingProvider(AppProperties a return pagingProvider; } + @Bean public IResourceSupportedSvc resourceSupportedSvc(IDaoRegistry theDaoRegistry) { return new DaoRegistryResourceSupportedSvc(theDaoRegistry); @@ -150,7 +148,7 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource my @Bean @Primary - public JpaTransactionManager hapiTransactionManager(EntityManagerFactory entityManagerFactory) { + public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager retVal = new JpaTransactionManager(); retVal.setEntityManagerFactory(entityManagerFactory); return retVal; @@ -246,7 +244,7 @@ public CorsInterceptor corsInterceptor(AppProperties appProperties) { } @Bean - public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc) { + public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc) { RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext()); @@ -352,7 +350,7 @@ public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProper } if (appProperties.getAllow_cascading_deletes()) { - CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(fhirSystemDao.getContext(), daoRegistry, interceptorBroadcaster); + CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(fhirSystemDao.getContext(), daoRegistry, interceptorBroadcaster, theThreadSafeResourceDeleterSvc); fhirServer.registerInterceptor(cascadingDeleteInterceptor); } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index a651fa9831f..19a166667d5 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -39,16 +39,17 @@ spring: # hibernate.cache.use_second_level_cache: false # hibernate.cache.use_structured_entries: false # hibernate.cache.use_minimal_puts: false - ### These settings will enable fulltext search with lucene - hibernate.search.enabled: false - # hibernate.search.backend.type: lucene - # hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer - # hibernate.search.backend.directory.type: local-filesystem - # hibernate.search.backend.directory.root: target/lucenefiles - # hibernate.search.backend.lucene_version: lucene_current - batch: - job: - enabled: false + ### These settings will enable fulltext search with lucene or elastic + hibernate.search.enabled: true + ### lucene parameters +# hibernate.search.backend.type: lucene +# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer +# hibernate.search.backend.directory.type: local-filesystem +# hibernate.search.backend.directory.root: target/lucenefiles +# hibernate.search.backend.lucene_version: lucene_current + ### elastic parameters ===> see also elasticsearch section below <=== + hibernate.search.backend.type: elasticsearch + hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer hapi: fhir: ### This enables the swagger-ui at /fhir/swagger-ui/index.html as well as the /fhir/api-docs (see https://hapifhir.io/hapi-fhir/docs/server_plain/openapi.html) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 6ad49c61cf5..3a8404772f2 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -38,7 +38,6 @@ @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { - "spring.batch.job.enabled=false", "spring.datasource.url=jdbc:h2:mem:dbr4", "hapi.fhir.fhir_version=r4", "hapi.fhir.lastn_enabled=true", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java index 964fae24a6f..e20aff8ff8a 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -18,7 +18,6 @@ @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { - "spring.batch.job.enabled=false", "hapi.fhir.fhir_version=dstu2", "spring.datasource.url=jdbc:h2:mem:dbr2", }) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index 0dfcf83da59..926a5003841 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -39,7 +39,6 @@ @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { - "spring.batch.job.enabled=false", "spring.datasource.url=jdbc:h2:mem:dbr3", "hapi.fhir.cql_enabled=true", "hapi.fhir.fhir_version=dstu3", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 27a8c21be44..278a5f0ccc8 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -31,7 +31,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { - "spring.batch.job.enabled=false", "spring.datasource.url=jdbc:h2:mem:dbr4", "hapi.fhir.enable_repository_validating_interceptor=true", "hapi.fhir.fhir_version=r4", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index 055d1ab25d7..ddbd6a77ac1 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -34,7 +34,6 @@ @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { - "spring.batch.job.enabled=false", "spring.datasource.url=jdbc:h2:mem:dbr5", "hapi.fhir.fhir_version=r5", "hapi.fhir.subscription.websocket_enabled=true", @@ -80,7 +79,7 @@ public void testWebsocketSubscription() throws Exception { subscription.getContained().add(topic); subscription.setTopic("#1"); subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)"); - subscription.setStatus(Enumerations.SubscriptionState.REQUESTED); + subscription.setStatus(Enumerations.SubscriptionStatusCodes.REQUESTED); subscription.getChannelType() .setSystem("http://terminology.hl7.org/CodeSystem/subscription-channel-type") .setCode("websocket"); diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java index 29af5e7482a..9d340b12444 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -20,7 +20,6 @@ @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { - "spring.batch.job.enabled=false", "spring.datasource.url=jdbc:h2:mem:dbr4-mt", "hapi.fhir.fhir_version=r4", "hapi.fhir.subscription.websocket_enabled=true", diff --git a/src/test/resources/application-integrationtest.yaml b/src/test/resources/application-integrationtest.yaml deleted file mode 100644 index 3ab724038f8..00000000000 --- a/src/test/resources/application-integrationtest.yaml +++ /dev/null @@ -1,108 +0,0 @@ -spring: - datasource: - url: 'jdbc:h2:file:./target/database/h2' - username: sa - 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: - #supported_resource_types: - # - Patient - # - Observation -# allow_cascading_deletes: true -# allow_contains_searches: true -# allow_external_references: true -# allow_multiple_delete: true -# allow_override_default_search_params: true -# allow_placeholder_references: true -# auto_create_placeholder_reference_targets: false -# cql_enabled: false -# default_encoding: JSON -# default_pretty_print: true -# default_page_size: 20 -# delete_expunge_enabled: true -# enable_index_missing_fields: false -# enforce_referential_integrity_on_delete: false -# enforce_referential_integrity_on_write: false -# etag_support_enabled: true -# expunge_enabled: true -# daoconfig_client_id_strategy: null -# fhirpath_interceptor_enabled: false -# filter_search_enabled: true -# graphql_enabled: true -# local_base_urls: -# - http://hapi.fhir.org/baseR4 - #partitioning: - # cross_partition_reference_mode: true - # multitenancy_enabled: true - # partitioning_include_in_search_hashes: true - #cors: - # allow_Credentials: true - # Supports multiple, comma separated allowed origin entries - # cors.allowed_origin=http://localhost:8080,https://localhost:8080,https://fhirtest.uhn.ca - # allowed_origin: - # - '*' - -# logger: -# error_format: 'ERROR - ${requestVerb} ${requestUrl}' -# format: >- -# Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] -# Operation[${operationType} ${operationName} ${idOrResourceName}] -# UA[${requestHeader.user-agent}] Params[${requestParameters}] -# ResponseEncoding[${responseEncodingNoDefault}] -# log_exceptions: true -# name: fhirtest.access -# max_binary_size: 104857600 -# max_page_size: 200 -# retain_cached_searches_mins: 60 -# reuse_cached_search_results_millis: 60000 - tester: - - - id: home - name: Local Tester - server_address: 'http://localhost:8080/hapi-fhir-jpaserver/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: -# resthook_enabled: false -# websocket_enabled: false -# email: -# from: some@test.com -# host: google.com -# port: -# username: -# password: -# auth: -# startTlsEnable: -# startTlsRequired: -# quitWait: - - -# -#elasticsearch: -# debug: -# pretty_print_json_log: false -# refresh_after_write: false -# enabled: false -# password: SomePassword -# required_index_status: YELLOW -# rest_url: 'http://localhost:9200' -# schema_management_strategy: CREATE -# username: SomeUsername diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml new file mode 100644 index 00000000000..4794df57468 --- /dev/null +++ b/src/test/resources/application.yaml @@ -0,0 +1,186 @@ +spring: + main: + allow-circular-references: true + #allow-bean-definition-overriding: true + flyway: + enabled: false + check-location: false + baselineOnMigrate: true + datasource: + url: jdbc:h2:mem:test_mem + username: sa + password: null + driverClassName: org.h2.Driver + max-active: 15 + + # database connection pool size + hikari: + maximum-pool-size: 10 + jpa: + properties: + hibernate.format_sql: false + hibernate.show_sql: false + #Hibernate dialect is automatically detected except Postgres and H2. + #If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect + #If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect + + hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect + # hibernate.hbm2ddl.auto: update + # hibernate.jdbc.batch_size: 20 + # hibernate.cache.use_query_cache: false + # hibernate.cache.use_second_level_cache: false + # hibernate.cache.use_structured_entries: false + # hibernate.cache.use_minimal_puts: false + ### These settings will enable fulltext search with lucene or elastic + hibernate.search.enabled: false + ### lucene parameters + # hibernate.search.backend.type: lucene + # hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer + # hibernate.search.backend.directory.type: local-filesystem + # hibernate.search.backend.directory.root: target/lucenefiles + # hibernate.search.backend.lucene_version: lucene_current + ### elastic parameters ===> see also elasticsearch section below <=== +# hibernate.search.backend.type: elasticsearch +# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer + +hapi: + fhir: + ### This enables the swagger-ui at /fhir/swagger-ui/index.html as well as the /fhir/api-docs (see https://hapifhir.io/hapi-fhir/docs/server_plain/openapi.html) + openapi_enabled: true + ### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5 + fhir_version: R4 + ### enable to use the ApacheProxyAddressStrategy which uses X-Forwarded-* headers + ### to determine the FHIR server address + # use_apache_address_strategy: false + ### forces the use of the https:// protocol for the returned server address. + ### alternatively, it may be set using the X-Forwarded-Proto header. + # use_apache_address_strategy_https: false + ### enable to set the Server URL + # server_address: http://hapi.fhir.org/baseR4 + # defer_indexing_for_codesystems_of_size: 101 + # install_transitive_ig_dependencies: true + # implementationguides: + ### example from registry (packages.fhir.org) + # swiss: + # name: swiss.mednet.fhir + # version: 0.8.0 + # example not from registry + # ips_1_0_0: + # url: https://build.fhir.org/ig/HL7/fhir-ips/package.tgz + # name: hl7.fhir.uv.ips + # version: 1.0.0 + # supported_resource_types: + # - Patient + # - Observation + # allow_cascading_deletes: true + # allow_contains_searches: true + # allow_external_references: true + # allow_multiple_delete: true + # allow_override_default_search_params: true + # auto_create_placeholder_reference_targets: false + # cql_enabled: true + # default_encoding: JSON + # default_pretty_print: true + # default_page_size: 20 + # delete_expunge_enabled: true + # enable_repository_validating_interceptor: false + # enable_index_missing_fields: false + # enable_index_of_type: true + # enable_index_contained_resource: false + ### !!Extended Lucene/Elasticsearch Indexing is still a experimental feature, expect some features (e.g. _total=accurate) to not work as expected!! + ### more information here: https://hapifhir.io/hapi-fhir/docs/server_jpa/elastic.html + advanced_lucene_indexing: false + # enforce_referential_integrity_on_delete: false + # This is an experimental feature, and does not fully support _total and other FHIR features. + # enforce_referential_integrity_on_delete: false + # enforce_referential_integrity_on_write: false + # etag_support_enabled: true + # expunge_enabled: true + # daoconfig_client_id_strategy: null + # client_id_strategy: ALPHANUMERIC + # fhirpath_interceptor_enabled: false + # filter_search_enabled: true + # graphql_enabled: true + # narrative_enabled: true + # mdm_enabled: true + # local_base_urls: + # - https://hapi.fhir.org/baseR4 + mdm_enabled: false + # partitioning: + # allow_references_across_partitions: false + # partitioning_include_in_search_hashes: false + #cors: + # allow_Credentials: true + # These are allowed_origin patterns, see: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/cors/CorsConfiguration.html#setAllowedOriginPatterns-java.util.List- + # allowed_origin: + # - '*' + + # Search coordinator thread pool sizes + search-coord-core-pool-size: 20 + search-coord-max-pool-size: 100 + search-coord-queue-capacity: 200 + + # Threadpool size for BATCH'ed GETs in a bundle. + # bundle_batch_pool_size: 10 + # bundle_batch_pool_max_size: 50 + + # logger: + # error_format: 'ERROR - ${requestVerb} ${requestUrl}' + # format: >- + # Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] + # Operation[${operationType} ${operationName} ${idOrResourceName}] + # UA[${requestHeader.user-agent}] Params[${requestParameters}] + # ResponseEncoding[${responseEncodingNoDefault}] + # log_exceptions: true + # name: fhirtest.access + # max_binary_size: 104857600 + # max_page_size: 200 + # retain_cached_searches_mins: 60 + # reuse_cached_search_results_millis: 60000 + tester: + home: + name: Local Tester + server_address: 'http://localhost:8080/fhir' + refuse_to_fetch_third_party_urls: false + fhir_version: R4 + 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 +# subscription: +# resthook_enabled: true +# websocket_enabled: false +# email: +# from: some@test.com +# host: google.com +# port: +# username: +# password: +# auth: +# startTlsEnable: +# startTlsRequired: +# quitWait: +# lastn_enabled: true +# store_resource_in_lucene_index_enabled: true +### This is configuration for normalized quantity serach level default is 0 +### 0: NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED - default +### 1: NORMALIZED_QUANTITY_STORAGE_SUPPORTED +### 2: NORMALIZED_QUANTITY_SEARCH_SUPPORTED +# normalized_quantity_search_level: 2 +#elasticsearch: +# debug: +# pretty_print_json_log: false +# refresh_after_write: false +# enabled: false +# password: SomePassword +# required_index_status: YELLOW +# rest_url: 'localhost:9200' +# protocol: 'http' +# schema_management_strategy: CREATE +# username: SomeUsername From 64aeb9b2fe250ce843e47a60763d5012dee19016 Mon Sep 17 00:00:00 2001 From: Kai-W Date: Sat, 12 Nov 2022 16:43:56 +0100 Subject: [PATCH 118/192] Added hibernate.dialect for Postgress to Readme (#451) --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index c104d2398ff..b30dd87de9a 100644 --- a/README.md +++ b/README.md @@ -218,6 +218,9 @@ spring: username: admin password: admin driverClassName: org.postgresql.Driver + jpa: + properties: + hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect ``` Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. @@ -235,6 +238,12 @@ spring: driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver ``` +Also, make sure you are not setting the Hibernate dialect explicitly, in other words remove any lines similar to: + +``` +hibernate.dialect: {some none Microsoft SQL dialect} +``` + Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. From 2e1f5f52769cf5f38883f3ac27e20f1fe1bdd84a Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Sat, 12 Nov 2022 18:39:38 +0100 Subject: [PATCH 119/192] fixes for support of R4B / 6.2.0 (#455) --- pom.xml | 11 +- .../starter/annotations/OnEitherVersion.java | 4 + .../starter/annotations/OnR4BCondition.java | 18 +++ .../starter/common/FhirServerConfigR4B.java | 17 +++ .../jpa/starter/common/StarterJpaConfig.java | 7 +- ...sitoryValidationInterceptorFactoryR4B.java | 77 +++++++++++ src/main/resources/application.yaml | 4 +- .../fhir/jpa/starter/ExampleServerR4BIT.java | 120 ++++++++++++++++++ 8 files changed, 252 insertions(+), 6 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4BCondition.java create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4B.java create mode 100644 src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java diff --git a/pom.xml b/pom.xml index 7293b3046bc..35ae0de8f2a 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.2.0-PRE18-SNAPSHOT + 6.2.0 hapi-fhir-jpaserver-starter @@ -316,11 +316,18 @@ ${spring_boot_version} + + + io.micrometer + micrometer-core + 1.9.4 + + io.micrometer micrometer-registry-prometheus - 1.8.5 + 1.9.4 diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnEitherVersion.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnEitherVersion.java index abf564f7fbf..463f77908cd 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnEitherVersion.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnEitherVersion.java @@ -28,6 +28,10 @@ static class OnDSTU3 { static class OnR4 { } + @Conditional(OnR4BCondition.class) + static class OnR4B { + } + @Conditional(OnR5Condition.class) static class OnR5 { } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4BCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4BCondition.java new file mode 100644 index 00000000000..e323a225132 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4BCondition.java @@ -0,0 +1,18 @@ +package ca.uhn.fhir.jpa.starter.annotations; + +import ca.uhn.fhir.context.FhirVersionEnum; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class OnR4BCondition implements Condition { + @Override + public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) { + String version = conditionContext. + getEnvironment() + .getProperty("hapi.fhir.fhir_version") + .toUpperCase(); + + return FhirVersionEnum.R4B.name().equals(version); + } +} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java new file mode 100644 index 00000000000..d99d1021058 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java @@ -0,0 +1,17 @@ +package ca.uhn.fhir.jpa.starter.common; + +import ca.uhn.fhir.jpa.config.r4b.JpaR4BConfig; +import ca.uhn.fhir.jpa.starter.annotations.OnR4BCondition; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Conditional(OnR4BCondition.class) +@Import({ + JpaR4BConfig.class, + StarterJpaConfig.class, + ElasticsearchConfig.class +}) +public class FhirServerConfigR4B { +} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index ed150154685..3f481bdadcf 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -26,7 +26,6 @@ import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDaoJpaImpl; import ca.uhn.fhir.jpa.dao.search.HSearchSortHelperImpl; import ca.uhn.fhir.jpa.dao.search.IHSearchSortHelper; -import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService; import ca.uhn.fhir.jpa.delete.ThreadSafeResourceDeleterSvc; import ca.uhn.fhir.jpa.graphql.GraphQLProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; @@ -423,7 +422,6 @@ public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProper public static IServerConformanceProvider calculateConformanceProvider(IFhirSystemDao fhirSystemDao, RestfulServer fhirServer, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport) { FhirVersionEnum fhirVersion = fhirSystemDao.getContext().getVersion().getVersion(); if (fhirVersion == FhirVersionEnum.DSTU2) { - JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(fhirServer, fhirSystemDao, daoConfig); confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server"); return confProvider; @@ -437,6 +435,11 @@ public static IServerConformanceProvider calculateConformanceProvider(IFhirSy JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, daoConfig, searchParamRegistry, theValidationSupport); confProvider.setImplementationDescription("HAPI FHIR R4 Server"); return confProvider; + } else if (fhirVersion == FhirVersionEnum.R4B) { + + JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, daoConfig, searchParamRegistry, theValidationSupport); + confProvider.setImplementationDescription("HAPI FHIR R4B Server"); + return confProvider; } else if (fhirVersion == FhirVersionEnum.R5) { JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, daoConfig, searchParamRegistry, theValidationSupport); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4B.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4B.java new file mode 100644 index 00000000000..277af2fcd5a --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4B.java @@ -0,0 +1,77 @@ +package ca.uhn.fhir.jpa.starter.common.validation; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.interceptor.validation.IRepositoryValidatingRule; +import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; +import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder; +import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; +import ca.uhn.fhir.jpa.starter.annotations.OnR4BCondition; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.TokenParam; +import org.hl7.fhir.r4b.model.StructureDefinition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR; + +/** + * This class can be customized to enable the {@link RepositoryValidatingInterceptor} + * on this server. + *

+ * The enable_repository_validating_interceptor property must be enabled in application.yaml + * in order to use this class. + */ +@ConditionalOnProperty(prefix = "hapi.fhir", name = ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR, havingValue = "true") +@Configuration +@Conditional(OnR4BCondition.class) +public class RepositoryValidationInterceptorFactoryR4B implements IRepositoryValidationInterceptorFactory { + + private final FhirContext fhirContext; + private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder; + private final IFhirResourceDao structureDefinitionResourceProvider; + + public RepositoryValidationInterceptorFactoryR4B(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) { + this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder; + this.fhirContext = daoRegistry.getSystemDao().getContext(); + structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition"); + + } + + @Override + public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() { + + IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource"))); + Map> structureDefintions = results.getResources(0, results.size()) + .stream() + .map(StructureDefinition.class::cast) + .collect(Collectors.groupingBy(StructureDefinition::getType)); + + structureDefintions.forEach((key, value) -> { + String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new); + repositoryValidatingRuleBuilder.forResourcesOfType(key).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); + }); + + List rules = repositoryValidatingRuleBuilder.build(); + return new RepositoryValidatingInterceptor(fhirContext, rules); + } + + @Override + public RepositoryValidatingInterceptor build() { + + // Customize the ruleBuilder here to have the rules you want! We will give a simple example + // of enabling validation for all Patient resources + repositoryValidatingRuleBuilder.forResourcesOfType("Patient").requireAtLeastProfile("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient").and().requireValidationToDeclaredProfiles(); + + // Do not customize below this line + List rules = repositoryValidatingRuleBuilder.build(); + return new RepositoryValidatingInterceptor(fhirContext, rules); + } + +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 19a166667d5..67a652fdbc8 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -48,8 +48,8 @@ spring: # hibernate.search.backend.directory.root: target/lucenefiles # hibernate.search.backend.lucene_version: lucene_current ### elastic parameters ===> see also elasticsearch section below <=== - hibernate.search.backend.type: elasticsearch - hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer +# hibernate.search.backend.type: elasticsearch +# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer hapi: fhir: ### This enables the swagger-ui at /fhir/swagger-ui/index.html as well as the /fhir/api-docs (see https://hapifhir.io/hapi-fhir/docs/server_plain/openapi.html) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java new file mode 100644 index 00000000000..00927220aee --- /dev/null +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java @@ -0,0 +1,120 @@ +package ca.uhn.fhir.jpa.starter; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4b.model.Bundle; +import org.hl7.fhir.r4b.model.Patient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { + "spring.datasource.url=jdbc:h2:mem:dbr4b", + "hapi.fhir.enable_repository_validating_interceptor=true", + "hapi.fhir.fhir_version=r4b", + "hapi.fhir.subscription.websocket_enabled=false", + "hapi.fhir.mdm_enabled=false", + "hapi.fhir.implementationguides.dk-core.name=hl7.fhir.dk.core", + "hapi.fhir.implementationguides.dk-core.version=1.1.0", + // Override is currently required when using MDM as the construction of the MDM + // beans are ambiguous as they are constructed multiple places. This is evident + // when running in a spring boot environment + "spring.main.allow-bean-definition-overriding=true"}) +class ExampleServerR4BIT { + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerR4BIT.class); + private IGenericClient ourClient; + private FhirContext ourCtx; + + @LocalServerPort + private int port; + + @Test + @Order(0) + void testCreateAndRead() { + String methodName = "testCreateAndRead"; + ourLog.info("Entering " + methodName + "()..."); + + Patient pt = new Patient(); + pt.setActive(true); + pt.getBirthDateElement().setValueAsString("2020-01-01"); + pt.addIdentifier().setSystem("http://foo").setValue("12345"); + pt.addName().setFamily(methodName); + IIdType id = ourClient.create().resource(pt).execute().getId(); + + Patient pt2 = ourClient.read().resource(Patient.class).withId(id).execute(); + assertEquals(methodName, pt2.getName().get(0).getFamily()); + + } + + + @Test + public void testBatchPutWithIdenticalTags() { + String batchPuts = "{\n" + + "\t\"resourceType\": \"Bundle\",\n" + + "\t\"id\": \"patients\",\n" + + "\t\"type\": \"batch\",\n" + + "\t\"entry\": [\n" + + "\t\t{\n" + + "\t\t\t\"request\": {\n" + + "\t\t\t\t\"method\": \"PUT\",\n" + + "\t\t\t\t\"url\": \"Patient/pat-1\"\n" + + "\t\t\t},\n" + + "\t\t\t\"resource\": {\n" + + "\t\t\t\t\"resourceType\": \"Patient\",\n" + + "\t\t\t\t\"id\": \"pat-1\",\n" + + "\t\t\t\t\"meta\": {\n" + + "\t\t\t\t\t\"tag\": [\n" + + "\t\t\t\t\t\t{\n" + + "\t\t\t\t\t\t\t\"system\": \"http://mysystem.org\",\n" + + "\t\t\t\t\t\t\t\"code\": \"value2\"\n" + + "\t\t\t\t\t\t}\n" + + "\t\t\t\t\t]\n" + + "\t\t\t\t}\n" + + "\t\t\t},\n" + + "\t\t\t\"fullUrl\": \"/Patient/pat-1\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"request\": {\n" + + "\t\t\t\t\"method\": \"PUT\",\n" + + "\t\t\t\t\"url\": \"Patient/pat-2\"\n" + + "\t\t\t},\n" + + "\t\t\t\"resource\": {\n" + + "\t\t\t\t\"resourceType\": \"Patient\",\n" + + "\t\t\t\t\"id\": \"pat-2\",\n" + + "\t\t\t\t\"meta\": {\n" + + "\t\t\t\t\t\"tag\": [\n" + + "\t\t\t\t\t\t{\n" + + "\t\t\t\t\t\t\t\"system\": \"http://mysystem.org\",\n" + + "\t\t\t\t\t\t\t\"code\": \"value2\"\n" + + "\t\t\t\t\t\t}\n" + + "\t\t\t\t\t]\n" + + "\t\t\t\t}\n" + + "\t\t\t},\n" + + "\t\t\t\"fullUrl\": \"/Patient/pat-2\"\n" + + "\t\t}\n" + + "\t]\n" + + "}"; + Bundle bundle = FhirContext.forR4B().newJsonParser().parseResource(Bundle.class, batchPuts); + ourClient.transaction().withBundle(bundle).execute(); + } + + + + @BeforeEach + void beforeEach() { + + ourCtx = FhirContext.forR4B(); + ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); + ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); + String ourServerBase = "http://localhost:" + port + "/fhir/"; + ourClient = ourCtx.newRestfulGenericClient(ourServerBase); + + + } +} From 4fb2558d7ce123a4c8187bba5d4788525f8e4bf3 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Thu, 17 Nov 2022 10:07:25 -0500 Subject: [PATCH 120/192] upping hapi version to 6.2.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 35ae0de8f2a..fa56b60d47c 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.2.0 + 6.2.1 hapi-fhir-jpaserver-starter From 05d76c78ad8508dfe9bfa7d6ddaa3968804dd631 Mon Sep 17 00:00:00 2001 From: chgl Date: Thu, 24 Nov 2022 23:09:24 +0100 Subject: [PATCH 121/192] Updated Helm chart to use image 6.2.1 and latest PostgreSQL (#458) --- charts/hapi-fhir-jpaserver/Chart.lock | 6 +++--- charts/hapi-fhir-jpaserver/Chart.yaml | 14 +++++++++----- charts/hapi-fhir-jpaserver/README.md | 6 +++--- .../hapi-fhir-jpaserver/templates/deployment.yaml | 2 +- .../templates/tests/test-endpoints.yaml | 6 +++--- charts/hapi-fhir-jpaserver/values.yaml | 4 ++-- 6 files changed, 21 insertions(+), 17 deletions(-) diff --git a/charts/hapi-fhir-jpaserver/Chart.lock b/charts/hapi-fhir-jpaserver/Chart.lock index 411bc270ef5..5c8ec4a2289 100644 --- a/charts/hapi-fhir-jpaserver/Chart.lock +++ b/charts/hapi-fhir-jpaserver/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 11.8.1 -digest: sha256:671325f8b3d0b85183fa241190e72705fb124a41254a5db6445bcc105e1ca7ec -generated: "2022-08-25T02:14:58.3432514+02:00" + version: 12.1.2 +digest: sha256:525689611a29f90b0bc8cd674df5d97024c99eda8104216390f6747904fd0208 +generated: "2022-11-21T22:55:45.1699395+01:00" diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index 4632de77230..736c5d5e577 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -7,17 +7,21 @@ sources: - https://github.com/hapifhir/hapi-fhir-jpaserver-starter dependencies: - name: postgresql - version: 11.8.1 + version: 12.1.2 repository: https://charts.bitnami.com/bitnami condition: postgresql.enabled -appVersion: v6.x -version: 0.10.1 +appVersion: 6.2.1 +version: 0.11.0 annotations: artifacthub.io/license: Apache-2.0 artifacthub.io/changes: | # When using the list of objects option the valid supported kinds are # added, changed, deprecated, removed, fixed, and security. - kind: changed - description: updated image version to v6.1.0 + description: updated HAPI FHIR JPA Server app image version to v6.2.1 - kind: changed - description: added section on configuring the chart for distributed tracing to the README.md + description: | + Reduced `startupProbe.initialDelaySeconds` to a more realistic `30` from `60`. + This should allow the server to become ready quicker and recover from failures faster. + - kind: changed + description: "⚠️ BREAKING CHANGE: updated included postgresql chart to v12, which is based on PostgreSQL 15.1" diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index 798e001bb0f..5ab71f70228 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -1,6 +1,6 @@ # HAPI FHIR JPA Server Starter Helm Chart -![Version: 0.10.1](https://img.shields.io/badge/Version-0.10.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v6.x](https://img.shields.io/badge/AppVersion-v6.x-informational?style=flat-square) +![Version: 0.11.0](https://img.shields.io/badge/Version-0.11.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.2.1](https://img.shields.io/badge/AppVersion-6.2.1-informational?style=flat-square) This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment. @@ -32,7 +32,7 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | image.pullPolicy | string | `"IfNotPresent"` | image pullPolicy to use | | image.registry | string | `"docker.io"` | registry where the HAPI FHIR server image is hosted | | image.repository | string | `"hapiproject/hapi"` | the path inside the repository | -| image.tag | string | `"v6.1.0@sha256:253f87bb1f5b7627f8e25f76a4b0aa7a83f31968c6e111ad74d3cc4ad9ae812e"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. | +| image.tag | string | `"v6.2.1@sha256:8d1b4c1c8abd613f685267a3dda494d87aba4cff449eed39902a6ece2c086f3c"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. | | imagePullSecrets | list | `[]` | image pull secrets to use when pulling the image | | ingress.annotations | object | `{}` | provide any additional annotations which may be required. Evaluated as a template. | | ingress.enabled | bool | `false` | whether to create an Ingress to expose the FHIR server HTTP endpoint | @@ -80,7 +80,7 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | service.port | int | `8080` | port where the server will be exposed at | | service.type | string | `"ClusterIP"` | service type | | startupProbe.failureThreshold | int | `10` | | -| startupProbe.initialDelaySeconds | int | `60` | | +| startupProbe.initialDelaySeconds | int | `30` | | | startupProbe.periodSeconds | int | `30` | | | startupProbe.successThreshold | int | `1` | | | startupProbe.timeoutSeconds | int | `30` | | diff --git a/charts/hapi-fhir-jpaserver/templates/deployment.yaml b/charts/hapi-fhir-jpaserver/templates/deployment.yaml index fa88745b016..8f3c65e3137 100644 --- a/charts/hapi-fhir-jpaserver/templates/deployment.yaml +++ b/charts/hapi-fhir-jpaserver/templates/deployment.yaml @@ -30,7 +30,7 @@ spec: {{- toYaml .Values.podSecurityContext | nindent 8 }} initContainers: - name: wait-for-db-to-be-ready - image: docker.io/bitnami/postgresql:14.5.0@sha256:4355265e33e9c2a786aa145884d4b36ffd4c41c516b35d60df0b7495141ec738 + image: docker.io/bitnami/postgresql:15.1.0-debian-11-r0@sha256:27915588d5203a10a1c23624d9c81644437f33b7c224e25f79bcd9bd09bbb8e2 imagePullPolicy: IfNotPresent {{- with .Values.restrictedContainerSecurityContext }} securityContext: diff --git a/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml index 30aab5aba93..bf99dbce369 100644 --- a/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml +++ b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml @@ -11,7 +11,7 @@ spec: restartPolicy: Never containers: - name: test-metadata-endpoint - image: docker.io/curlimages/curl:7.84.0@sha256:5a2a25d96aa941ea2fc47acc50122f7c3d007399a075df61a82d6d2c3a567a2b + image: docker.io/curlimages/curl:7.86.0@sha256:cfdeba7f88bb85f6c87f2ec9135115b523a1c24943976a61fbf59c4f2eafd78e command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/metadata?_summary=true"] {{- with .Values.restrictedContainerSecurityContext }} @@ -32,7 +32,7 @@ spec: exec: command: ["true"] - name: test-patient-endpoint - image: docker.io/curlimages/curl:7.84.0@sha256:5a2a25d96aa941ea2fc47acc50122f7c3d007399a075df61a82d6d2c3a567a2b + image: docker.io/curlimages/curl:7.86.0@sha256:cfdeba7f88bb85f6c87f2ec9135115b523a1c24943976a61fbf59c4f2eafd78e command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/Patient?_count=1&_summary=true"] {{- with .Values.restrictedContainerSecurityContext }} @@ -53,7 +53,7 @@ spec: exec: command: ["true"] - name: test-metrics-endpoint - image: docker.io/curlimages/curl:7.84.0@sha256:5a2a25d96aa941ea2fc47acc50122f7c3d007399a075df61a82d6d2c3a567a2b + image: docker.io/curlimages/curl:7.86.0@sha256:cfdeba7f88bb85f6c87f2ec9135115b523a1c24943976a61fbf59c4f2eafd78e command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.metrics.service.port }}/actuator/prometheus"] {{- with .Values.restrictedContainerSecurityContext }} diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index 8b05fbe1146..b55d4ea7ea0 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -7,7 +7,7 @@ image: # -- the path inside the repository repository: hapiproject/hapi # -- the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. - tag: "v6.1.0@sha256:253f87bb1f5b7627f8e25f76a4b0aa7a83f31968c6e111ad74d3cc4ad9ae812e" + tag: "v6.2.1@sha256:8d1b4c1c8abd613f685267a3dda494d87aba4cff449eed39902a6ece2c086f3c" # -- image pullPolicy to use pullPolicy: IfNotPresent @@ -140,7 +140,7 @@ readinessProbe: startupProbe: failureThreshold: 10 - initialDelaySeconds: 60 + initialDelaySeconds: 30 periodSeconds: 30 successThreshold: 1 timeoutSeconds: 30 From 19c68e7cfcbb0eec064da8b4c9b5a43dc1879e83 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Sat, 3 Dec 2022 14:43:37 +0100 Subject: [PATCH 122/192] Bumped version (#462) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fa56b60d47c..700161b66d7 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.2.1 + 6.2.2 hapi-fhir-jpaserver-starter From ba58a71624c6fc5669394848ce0614af152225dd Mon Sep 17 00:00:00 2001 From: Craig McClendon Date: Tue, 20 Dec 2022 20:07:18 -0600 Subject: [PATCH 123/192] allow interceptors to be registered via properties --- README.md | 10 +++ .../uhn/fhir/jpa/starter/AppProperties.java | 6 ++ .../jpa/starter/common/StarterJpaConfig.java | 52 +++++++++++++-- src/main/resources/application.yaml | 8 +++ .../uhn/fhir/jpa/starter/CustomBeanTest.java | 24 +++++++ .../jpa/starter/CustomInterceptorTest.java | 64 +++++++++++++++++++ .../java/some/custom/pkg1/CustomBean.java | 18 ++++++ .../custom/pkg1/CustomInterceptorBean.java | 31 +++++++++ .../custom/pkg1/CustomInterceptorPojo.java | 26 ++++++++ 9 files changed, 233 insertions(+), 6 deletions(-) create mode 100644 src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java create mode 100644 src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java create mode 100644 src/test/java/some/custom/pkg1/CustomBean.java create mode 100644 src/test/java/some/custom/pkg1/CustomInterceptorBean.java create mode 100644 src/test/java/some/custom/pkg1/CustomInterceptorPojo.java diff --git a/README.md b/README.md index b30dd87de9a..3d9d0b8bc44 100644 --- a/README.md +++ b/README.md @@ -251,6 +251,16 @@ Because the integration tests within the project rely on the default H2 database NOTE: MS SQL Server by default uses a case-insensitive codepage. This will cause errors with some operations - such as when expanding case-sensitive valuesets (UCUM) as there are unique indexes defined on the terminology tables for codes. It is recommended to deploy a case-sensitive database prior to running HAPI FHIR when using MS SQL Server to avoid these and potentially other issues. +## Adding custom interceptors +Custom interceptors can be registered with the server by including the property `hapi.fhir.custom-interceptor-classes`. This will take a comma separated list of fully-qualified class names which will be registered with the server. +Interceptors will be discovered in one of two ways: + +1) discovered from the Spring application context as existing Beans (can be used in conjunction with `hapi.fhir.custom-bean-packages`) or registered with Spring via other methods + +or + +2) classes will be instantiated via reflection if no matching Bean is found + ## Customizing The Web Testpage UI The UI that comes with this server is an exact clone of the server available at [http://hapi.fhir.org](http://hapi.fhir.org). You may skin this UI if you'd like. For example, you might change the introductory text or replace the logo with your own. 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 e7599a8b284..e075c1e075b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -82,6 +82,12 @@ public class AppProperties { private Integer bundle_batch_pool_size = 20; private Integer bundle_batch_pool_max_size = 100; private final List local_base_urls = new ArrayList<>(); + + private final List custom_interceptor_classes = new ArrayList<>(); + + public List getCustomInterceptorClasses() { + return custom_interceptor_classes; + } public Boolean getOpenapi_enabled() { return openapi_enabled; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 3f481bdadcf..74ac24cc8e5 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -63,9 +63,11 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.*; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.http.HttpHeaders; @@ -75,13 +77,16 @@ import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; + import java.util.*; import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR; @Configuration +//allow users to configure custom packages to scan for additional beans +@ComponentScan(basePackages = { "${hapi.fhir.custom-bean-packages:}" }) @Import( - ThreadPoolFactoryConfig.class + ThreadPoolFactoryConfig.class ) public class StarterJpaConfig { @@ -243,11 +248,9 @@ public CorsInterceptor corsInterceptor(AppProperties appProperties) { } @Bean - public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc) { + public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext) { RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext()); - - List supportedResourceTypes = appProperties.getSupported_resource_types(); if (!supportedResourceTypes.isEmpty()) { @@ -410,13 +413,50 @@ public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProper fhirServer.setTenantIdentificationStrategy(new UrlBaseTenantIdentificationStrategy()); fhirServer.registerProviders(partitionManagementProvider); } + repositoryValidatingInterceptor.ifPresent(fhirServer::registerInterceptor); + // register custom interceptors + registerCustomInterceptors(fhirServer, appContext, appProperties.getCustomInterceptorClasses()); - repositoryValidatingInterceptor.ifPresent(fhirServer::registerInterceptor); + return fhirServer; + } + + /** + * check the properties for custom interceptor classes and registers them. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + private void registerCustomInterceptors(RestfulServer fhirServer, ApplicationContext theAppContext, List customInterceptorClasses) { + if (customInterceptorClasses == null) { + return; + } + for (String className : customInterceptorClasses) { + Class clazz; + try { + clazz = Class.forName(className); + } catch (ClassNotFoundException e) { + throw new ConfigurationException("Interceptor class was not found on classpath: " + className, e); + } - return fhirServer; + // first check if the class a Bean in the app context + Object interceptor = null; + try { + interceptor = theAppContext.getBean(clazz); + } catch (NoSuchBeanDefinitionException ex) { + // no op - if it's not a bean we'll try to create it + } + + // if not a bean, instantiate the interceptor via reflection + if (interceptor == null) { + try { + interceptor = clazz.getConstructor().newInstance(); + } catch (Exception e) { + throw new ConfigurationException("Unable to instantiate interceptor class : " + className, e); + } + } + fhirServer.registerInterceptor(interceptor); + } } public static IServerConformanceProvider calculateConformanceProvider(IFhirSystemDao fhirSystemDao, RestfulServer fhirServer, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport) { diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 67a652fdbc8..deb2bf2739f 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -131,6 +131,14 @@ hapi: search-coord-core-pool-size: 20 search-coord-max-pool-size: 100 search-coord-queue-capacity: 200 + + # comma-separated package names, will be @ComponentScan'ed by Spring to allow for creating custom Spring beans + #custom-bean-packages: + + # comma-separated list of fully qualified interceptor classes. + # classes listed here will be fetched from the Spring context when combined with 'custom-bean-packages', + # or will be instantiated via reflection using an no-arg contructor; then registered with the server + #custom-interceptor-classes: # Threadpool size for BATCH'ed GETs in a bundle. # bundle_batch_pool_size: 10 diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java new file mode 100644 index 00000000000..af9db0d98fc --- /dev/null +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java @@ -0,0 +1,24 @@ +package ca.uhn.fhir.jpa.starter; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { + "hapi.fhir.custom-bean-packages=some.custom.pkg1,some.custom.pkg2", + "spring.datasource.url=jdbc:h2:mem:dbr4", + // "hapi.fhir.enable_repository_validating_interceptor=true", + "hapi.fhir.fhir_version=r4" +}) +public class CustomBeanTest { + + @Autowired + some.custom.pkg1.CustomBean customBean1; + + @Test + void testCustomBeanExists() { + Assertions.assertNotNull(customBean1); + Assertions.assertEquals("I am alive", customBean1.getInitFlag()); + } +} diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java new file mode 100644 index 00000000000..377719e22f1 --- /dev/null +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java @@ -0,0 +1,64 @@ +package ca.uhn.fhir.jpa.starter; + +import org.hl7.fhir.r4.model.Patient; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.server.LocalServerPort; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { + "hapi.fhir.custom-bean-packages=some.custom.pkg1", + "hapi.fhir.custom-interceptor-classes=some.custom.pkg1.CustomInterceptorBean,some.custom.pkg1.CustomInterceptorPojo", + "spring.datasource.url=jdbc:h2:mem:dbr4", + // "hapi.fhir.enable_repository_validating_interceptor=true", + "hapi.fhir.fhir_version=r4" +}) + +public class CustomInterceptorTest { + + @LocalServerPort + private int port; + + @Autowired + private IFhirResourceDao patientResourceDao; + + private IGenericClient client; + private FhirContext ctx; + + @BeforeEach + void setUp() { + ctx = FhirContext.forR4(); + ctx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); + ctx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); + String ourServerBase = "http://localhost:" + port + "/fhir/"; + client = ctx.newRestfulGenericClient(ourServerBase); + + // Properties props = new Properties(); + // props.put("spring.autoconfigure.exclude", "org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration"); + } + + @Test + void testAuditInterceptors() { + + // we registered two custom interceptors via the property 'hapi.fhir.custom-interceptor-classes' + // one is discovered as a Spring Bean, one instantiated via reflection + // both should be registered with the server and will add a custom extension to any Patient resource created + // so we can verify they were registered + + Patient pat = new Patient(); + String patId = client.create().resource(pat).execute().getId().getIdPart(); + + Patient readPat = client.read().resource(Patient.class).withId(patId).execute(); + + Assertions.assertNotNull(readPat.getExtensionByUrl("http://some.custom.pkg1/CustomInterceptorBean")); + Assertions.assertNotNull(readPat.getExtensionByUrl("http://some.custom.pkg1/CustomInterceptorPojo")); + + } +} diff --git a/src/test/java/some/custom/pkg1/CustomBean.java b/src/test/java/some/custom/pkg1/CustomBean.java new file mode 100644 index 00000000000..8160871f403 --- /dev/null +++ b/src/test/java/some/custom/pkg1/CustomBean.java @@ -0,0 +1,18 @@ +package some.custom.pkg1; + +import org.springframework.stereotype.Component; + +@Component +public class CustomBean { + + private String initFlag; + + public CustomBean() { + initFlag = "I am alive"; + } + + public String getInitFlag() { + return initFlag; + } + +} diff --git a/src/test/java/some/custom/pkg1/CustomInterceptorBean.java b/src/test/java/some/custom/pkg1/CustomInterceptorBean.java new file mode 100644 index 00000000000..5a0b4df19aa --- /dev/null +++ b/src/test/java/some/custom/pkg1/CustomInterceptorBean.java @@ -0,0 +1,31 @@ +package some.custom.pkg1; + +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.StringType; +import org.springframework.stereotype.Component; + +import ca.uhn.fhir.interceptor.api.Hook; +import ca.uhn.fhir.interceptor.api.Interceptor; +import ca.uhn.fhir.interceptor.api.Pointcut; +import ca.uhn.fhir.rest.api.RestOperationTypeEnum; +import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; + +@Interceptor +@Component +public class CustomInterceptorBean { + + @Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED) + void preHandleResource(ServletRequestDetails servletRequestDetails, RestOperationTypeEnum opType) { + IBaseResource resource = servletRequestDetails.getResource(); + + // add an extension before saving the resource to mark it + if (opType == RestOperationTypeEnum.CREATE && resource instanceof Patient) { + Patient pat = (Patient) resource; + Extension ext = pat.addExtension(); + ext.setUrl("http://some.custom.pkg1/CustomInterceptorBean"); + ext.setValue(new StringType("CustomInterceptorBean wuz here")); + } + } +} diff --git a/src/test/java/some/custom/pkg1/CustomInterceptorPojo.java b/src/test/java/some/custom/pkg1/CustomInterceptorPojo.java new file mode 100644 index 00000000000..1df67c9acd6 --- /dev/null +++ b/src/test/java/some/custom/pkg1/CustomInterceptorPojo.java @@ -0,0 +1,26 @@ +package some.custom.pkg1; + +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.StringType; +import ca.uhn.fhir.interceptor.api.Hook; +import ca.uhn.fhir.interceptor.api.Pointcut; +import ca.uhn.fhir.rest.api.RestOperationTypeEnum; +import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; + +public class CustomInterceptorPojo { + + @Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED) + void preHandleResource(ServletRequestDetails servletRequestDetails, RestOperationTypeEnum opType) { + IBaseResource resource = servletRequestDetails.getResource(); + + // add an extension before saving the resource to mark it + if (opType == RestOperationTypeEnum.CREATE && resource instanceof Patient) { + Patient pat = (Patient) resource; + Extension ext = pat.addExtension(); + ext.setUrl("http://some.custom.pkg1/CustomInterceptorPojo"); + ext.setValue(new StringType("CustomInterceptorPojo wuz here")); + } + } +} From 9a513cd1845723c630565ac2b124d74e56491006 Mon Sep 17 00:00:00 2001 From: Luke deGruchy Date: Thu, 5 Jan 2023 16:56:01 -0500 Subject: [PATCH 124/192] Update pom.xml to reference hapi-fhir 6.3.6-SNAPSHOT. This hapi-fhir release contains a fix for POSTing an XML resource with comments results in a fhir_comments error (#465) * Update pom.xml to reference hapi-fhir 6.3.4-SNAPSHOT. This also involves renaming websocket dependencies whose names have changed since 6.2.2 (ex websocket-api to websocket-jetty-api). * Update pom to reference logback 1.2.10 explicitly to resolve the missing StaticLoggerBinder errors. * Fix logback issue by pulling the same logback version as hapi-fhir and setting the following system property at boot: org.springframework.boot.logging.LoggingSystem=none. Also, fix the hapi-fhir-jpaserver-base dependency error by setting this in application.yaml: allow-bean-definition-overriding: true * Set allow-bean-definition-overriding: true on test application.yaml as well. * Remove lines in ExampleServerR4BIT that causes an implementation guide version error. * Upgrade to 6.3.6-SNAPSHOT and once again disable allow-bean-definition-overriding. Also remove the Bean for IMdmLinkDoa from StartJpaConfig and the Bean for ITermCodeSystemStorageSvc in FhirServerConfigDstu2. * Explicitly use logback 1.2.10 for both logback-classic and logback-core to resolve StaticBinderLogger not found errors. Also, remove explici logger disabling code in Application.java. * Restore Application.java as well as both application.yaml files to the same as master. --- pom.xml | 20 +++++++++++++++---- .../starter/common/FhirServerConfigDstu2.java | 6 ------ .../jpa/starter/common/StarterJpaConfig.java | 10 ---------- .../fhir/jpa/starter/ExampleServerR4BIT.java | 2 -- 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/pom.xml b/pom.xml index 700161b66d7..d043e79b295 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.2.2 + 6.3.6-SNAPSHOT hapi-fhir-jpaserver-starter @@ -44,12 +44,12 @@ org.eclipse.jetty.websocket - websocket-api + websocket-jetty-api ${jetty_version} org.eclipse.jetty.websocket - websocket-client + websocket-jetty-client ${jetty_version} @@ -150,8 +150,20 @@ ch.qos.logback logback-classic + + + 1.2.10 + + ch.qos.logback + logback-core + + + 1.2.10 + + + javax.servlet @@ -246,7 +258,7 @@ org.eclipse.jetty.websocket - websocket-server + websocket-jetty-server test diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java index baf5044ce12..9416d2835e0 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java @@ -2,7 +2,6 @@ import ca.uhn.fhir.jpa.config.JpaDstu2Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU2Condition; -import ca.uhn.fhir.jpa.term.TermCodeSystemStorageSvcImpl; import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; @@ -24,9 +23,4 @@ public ITermLoaderSvc termLoaderService(ITermDeferredStorageSvc theDeferredStora return new TermLoaderSvcImpl(theDeferredStorageSvc, theCodeSystemStorageSvc); } - @Bean - public ITermCodeSystemStorageSvc termCodeSystemStorageSvc() { - return new TermCodeSystemStorageSvcImpl(); - } - } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 74ac24cc8e5..3fac5b7ce57 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -206,16 +206,6 @@ public IPackageInstallerSvc packageInstaller(AppProperties appProperties, JobDef return packageInstallerSvc; } - @Bean - @Primary - /* - This bean is currently necessary to override from MDM settings - */ - IMdmLinkDao mdmLinkDao() { - return new MdmLinkDaoJpaImpl(); - } - - @Bean @Conditional(OnCorsPresent.class) public CorsInterceptor corsInterceptor(AppProperties appProperties) { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java index 00927220aee..fc7bf58c4f9 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java @@ -20,8 +20,6 @@ "hapi.fhir.fhir_version=r4b", "hapi.fhir.subscription.websocket_enabled=false", "hapi.fhir.mdm_enabled=false", - "hapi.fhir.implementationguides.dk-core.name=hl7.fhir.dk.core", - "hapi.fhir.implementationguides.dk-core.version=1.1.0", // Override is currently required when using MDM as the construction of the MDM // beans are ambiguous as they are constructed multiple places. This is evident // when running in a spring boot environment From 96ff27f173143aaf7c3f88d1e563809603fc23b5 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Thu, 5 Jan 2023 23:26:09 +0100 Subject: [PATCH 125/192] Feature/static files (#456) * Added mapping * Added documentation --- .../uhn/fhir/jpa/starter/AppProperties.java | 12 ++++++++++ .../starter/ExtraStaticFilesConfigurer.java | 22 +++++++++++++++++++ src/main/resources/application.yaml | 3 +++ 3 files changed, 37 insertions(+) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java 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 e075c1e075b..8d3e878e1c2 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -72,6 +72,8 @@ public class AppProperties { private Boolean install_transitive_ig_dependencies = true; private Map implementationGuides = null; + private String staticLocation = null; + private Boolean lastn_enabled = false; private boolean store_resource_in_lucene_index_enabled = false; private NormalizedQuantitySearchLevel normalized_quantity_search_level = NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED; @@ -89,6 +91,16 @@ public List getCustomInterceptorClasses() { return custom_interceptor_classes; } + + public String getStaticLocation() { + return staticLocation; + } + + public void setStaticLocation(String staticLocation) { + this.staticLocation = staticLocation; + } + + public Boolean getOpenapi_enabled() { return openapi_enabled; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java b/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java new file mode 100644 index 00000000000..fce7291db41 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java @@ -0,0 +1,22 @@ +package ca.uhn.fhir.jpa.starter; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@ConditionalOnProperty(prefix = "hapi.fhir", name = "staticLocation") +public class ExtraStaticFilesConfigurer implements WebMvcConfigurer { + + @Autowired + AppProperties appProperties; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry theRegistry) { + theRegistry + .addResourceHandler("/static/**") + .addResourceLocations(appProperties.getStaticLocation()); + } +} \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index deb2bf2739f..f2a92693ec7 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -52,6 +52,7 @@ spring: # hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer hapi: fhir: + ### This enables the swagger-ui at /fhir/swagger-ui/index.html as well as the /fhir/api-docs (see https://hapifhir.io/hapi-fhir/docs/server_plain/openapi.html) openapi_enabled: true ### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5 @@ -62,6 +63,8 @@ hapi: ### forces the use of the https:// protocol for the returned server address. ### alternatively, it may be set using the X-Forwarded-Proto header. # use_apache_address_strategy_https: false + ### enables the server to host content like HTML, css, etc. under the url pattern of /static/** + # staticLocation: file:/usr/somewhere/ ### enable to set the Server URL # server_address: http://hapi.fhir.org/baseR4 # defer_indexing_for_codesystems_of_size: 101 From d903ab9661d148a8f6777c5f30122bc580638df1 Mon Sep 17 00:00:00 2001 From: isims Date: Tue, 10 Jan 2023 11:21:21 +0100 Subject: [PATCH 126/192] Remove old junit4 usage. --- .../ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index 926a5003841..826f31152e3 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -15,7 +15,6 @@ import org.eclipse.jetty.websocket.client.WebSocketClient; import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.instance.model.api.IIdType; -import org.junit.Assert; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -35,6 +34,8 @@ import static ca.uhn.fhir.util.TestUtil.waitForSize; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = @@ -112,11 +113,11 @@ public void testCQLEvaluateMeasureEXM104() throws IOException { .execute(); List response = outParams.getParameter(); - Assert.assertFalse(response.isEmpty()); + assertFalse(response.isEmpty()); Parameters.ParametersParameterComponent component = response.get(0); - Assert.assertTrue(component.getResource() instanceof MeasureReport); + assertTrue(component.getResource() instanceof MeasureReport); MeasureReport report = (MeasureReport) component.getResource(); - Assert.assertEquals("Measure/"+measureId, report.getMeasure()); + assertEquals("Measure/"+measureId, report.getMeasure()); } private int loadDataFromDirectory(String theDirectoryName) throws IOException { From 0c7e48cb4da3e00742ea975636fefed55cdb9eae Mon Sep 17 00:00:00 2001 From: Luke deGruchy Date: Tue, 10 Jan 2023 14:14:52 -0500 Subject: [PATCH 127/192] Revert "Update pom.xml to reference hapi-fhir 6.3.6-SNAPSHOT. This hapi-fhir release contains a fix for POSTing an XML resource with comments results in a fhir_comments error (#465)" (#476) This reverts commit 9a513cd1845723c630565ac2b124d74e56491006. --- pom.xml | 20 ++++--------------- .../starter/common/FhirServerConfigDstu2.java | 6 ++++++ .../jpa/starter/common/StarterJpaConfig.java | 10 ++++++++++ .../fhir/jpa/starter/ExampleServerR4BIT.java | 2 ++ 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/pom.xml b/pom.xml index d043e79b295..700161b66d7 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.6-SNAPSHOT + 6.2.2 hapi-fhir-jpaserver-starter @@ -44,12 +44,12 @@ org.eclipse.jetty.websocket - websocket-jetty-api + websocket-api ${jetty_version} org.eclipse.jetty.websocket - websocket-jetty-client + websocket-client ${jetty_version} @@ -150,20 +150,8 @@ ch.qos.logback logback-classic - - - 1.2.10 - - ch.qos.logback - logback-core - - - 1.2.10 - - - javax.servlet @@ -258,7 +246,7 @@ org.eclipse.jetty.websocket - websocket-jetty-server + websocket-server test diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java index 9416d2835e0..baf5044ce12 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java @@ -2,6 +2,7 @@ import ca.uhn.fhir.jpa.config.JpaDstu2Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU2Condition; +import ca.uhn.fhir.jpa.term.TermCodeSystemStorageSvcImpl; import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; @@ -23,4 +24,9 @@ public ITermLoaderSvc termLoaderService(ITermDeferredStorageSvc theDeferredStora return new TermLoaderSvcImpl(theDeferredStorageSvc, theCodeSystemStorageSvc); } + @Bean + public ITermCodeSystemStorageSvc termCodeSystemStorageSvc() { + return new TermCodeSystemStorageSvcImpl(); + } + } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 3fac5b7ce57..74ac24cc8e5 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -206,6 +206,16 @@ public IPackageInstallerSvc packageInstaller(AppProperties appProperties, JobDef return packageInstallerSvc; } + @Bean + @Primary + /* + This bean is currently necessary to override from MDM settings + */ + IMdmLinkDao mdmLinkDao() { + return new MdmLinkDaoJpaImpl(); + } + + @Bean @Conditional(OnCorsPresent.class) public CorsInterceptor corsInterceptor(AppProperties appProperties) { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java index fc7bf58c4f9..00927220aee 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java @@ -20,6 +20,8 @@ "hapi.fhir.fhir_version=r4b", "hapi.fhir.subscription.websocket_enabled=false", "hapi.fhir.mdm_enabled=false", + "hapi.fhir.implementationguides.dk-core.name=hl7.fhir.dk.core", + "hapi.fhir.implementationguides.dk-core.version=1.1.0", // Override is currently required when using MDM as the construction of the MDM // beans are ambiguous as they are constructed multiple places. This is evident // when running in a spring boot environment From f3493c7026a545c2be7a35455bd285f384f1642d Mon Sep 17 00:00:00 2001 From: Luke deGruchy Date: Tue, 10 Jan 2023 14:51:31 -0500 Subject: [PATCH 128/192] Restore rolled back changes to ExampleServerR4BIT that pass unnecessary properties that will cause problems when using hapi-fhir 6.3.6-SNAPSHOT. (#479) --- src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java index 00927220aee..fc7bf58c4f9 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java @@ -20,8 +20,6 @@ "hapi.fhir.fhir_version=r4b", "hapi.fhir.subscription.websocket_enabled=false", "hapi.fhir.mdm_enabled=false", - "hapi.fhir.implementationguides.dk-core.name=hl7.fhir.dk.core", - "hapi.fhir.implementationguides.dk-core.version=1.1.0", // Override is currently required when using MDM as the construction of the MDM // beans are ambiguous as they are constructed multiple places. This is evident // when running in a spring boot environment From 76650df4dcd0bf6944b9a80ddd1d0070ffc41422 Mon Sep 17 00:00:00 2001 From: Luke deGruchy Date: Tue, 10 Jan 2023 14:51:32 -0500 Subject: [PATCH 129/192] First commit to restore hapi-fhir 6.3.6-SNAPSHOT changes. Add static code blocks to Application.java as well as all tests to System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); --- pom.xml | 8 ++++---- src/main/java/ca/uhn/fhir/jpa/starter/Application.java | 4 ++++ .../fhir/jpa/starter/common/FhirServerConfigDstu2.java | 6 ------ .../uhn/fhir/jpa/starter/common/StarterJpaConfig.java | 10 ---------- .../java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java | 4 ++++ .../ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java | 4 ++++ .../uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java | 6 +++++- .../ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java | 4 ++++ .../ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java | 4 ++++ .../ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java | 6 ++++-- .../ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java | 5 +++++ .../ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java | 6 +++++- .../ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java | 3 +++ 13 files changed, 46 insertions(+), 24 deletions(-) diff --git a/pom.xml b/pom.xml index 700161b66d7..d56db5cfdbd 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.2.2 + 6.3.6-SNAPSHOT hapi-fhir-jpaserver-starter @@ -44,12 +44,12 @@ org.eclipse.jetty.websocket - websocket-api + websocket-jetty-api ${jetty_version} org.eclipse.jetty.websocket - websocket-client + websocket-jetty-client ${jetty_version} @@ -246,7 +246,7 @@ org.eclipse.jetty.websocket - websocket-server + websocket-jetty-server test 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 8031c598f7e..71ada0b8b86 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -38,6 +38,10 @@ }) public class Application extends SpringBootServletInitializer { + static { + System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); + } + public static void main(String[] args) { SpringApplication.run(Application.class, args); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java index baf5044ce12..9416d2835e0 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java @@ -2,7 +2,6 @@ import ca.uhn.fhir.jpa.config.JpaDstu2Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU2Condition; -import ca.uhn.fhir.jpa.term.TermCodeSystemStorageSvcImpl; import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; @@ -24,9 +23,4 @@ public ITermLoaderSvc termLoaderService(ITermDeferredStorageSvc theDeferredStora return new TermLoaderSvcImpl(theDeferredStorageSvc, theCodeSystemStorageSvc); } - @Bean - public ITermCodeSystemStorageSvc termCodeSystemStorageSvc() { - return new TermCodeSystemStorageSvcImpl(); - } - } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 74ac24cc8e5..3fac5b7ce57 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -206,16 +206,6 @@ public IPackageInstallerSvc packageInstaller(AppProperties appProperties, JobDef return packageInstallerSvc; } - @Bean - @Primary - /* - This bean is currently necessary to override from MDM settings - */ - IMdmLinkDao mdmLinkDao() { - return new MdmLinkDaoJpaImpl(); - } - - @Bean @Conditional(OnCorsPresent.class) public CorsInterceptor corsInterceptor(AppProperties appProperties) { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java index af9db0d98fc..842798c04b3 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java @@ -13,6 +13,10 @@ }) public class CustomBeanTest { + static { + System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); + } + @Autowired some.custom.pkg1.CustomBean customBean1; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java index 377719e22f1..99392102534 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java @@ -23,6 +23,10 @@ public class CustomInterceptorTest { + static { + System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); + } + @LocalServerPort private int port; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 3a8404772f2..0aea7f8eb58 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -57,8 +57,12 @@ }) @ContextConfiguration(initializers = ElasticsearchLastNR4IT.Initializer.class) public class ElasticsearchLastNR4IT { + static { + System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); + } - private IGenericClient ourClient; + + private IGenericClient ourClient; private FhirContext ourCtx; private static final String ELASTIC_VERSION = "7.16.3"; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java index e20aff8ff8a..1c5a5653e25 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -23,6 +23,10 @@ }) public class ExampleServerDstu2IT { + static { + System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); + } + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index 826f31152e3..d7745bdfcb3 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -51,6 +51,10 @@ public class ExampleServerDstu3IT implements IServerSupport { + static { + System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); + } + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java index 00927220aee..2157c28f5f1 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java @@ -20,13 +20,15 @@ "hapi.fhir.fhir_version=r4b", "hapi.fhir.subscription.websocket_enabled=false", "hapi.fhir.mdm_enabled=false", - "hapi.fhir.implementationguides.dk-core.name=hl7.fhir.dk.core", - "hapi.fhir.implementationguides.dk-core.version=1.1.0", // Override is currently required when using MDM as the construction of the MDM // beans are ambiguous as they are constructed multiple places. This is evident // when running in a spring boot environment "spring.main.allow-bean-definition-overriding=true"}) class ExampleServerR4BIT { + + static { + System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); + } private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerR4BIT.class); private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 278a5f0ccc8..44808add08a 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -43,6 +43,11 @@ // when running in a spring boot environment "spring.main.allow-bean-definition-overriding=true" }) class ExampleServerR4IT { + + static { + System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); + } + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerR4IT.class); private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index ddbd6a77ac1..f8e807e75c4 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -41,7 +41,11 @@ }) public class ExampleServerR5IT { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); + static { + System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); + } + + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java index 9d340b12444..a5c2da563b9 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -28,6 +28,9 @@ }) public class MultitenantServerR4IT { + static { + System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); + } private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); private IGenericClient ourClient; From 07d9a193d2d9add9ae561839477ed9593f690484 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Tue, 10 Jan 2023 20:51:47 +0100 Subject: [PATCH 130/192] Feature/index default (#475) * Added default * Refactored the default resolution --- .../starter/ExtraStaticFilesConfigurer.java | 34 ++++++++++++++----- src/main/resources/application.yaml | 3 +- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java b/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java index fce7291db41..d875ec6a5d6 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java @@ -3,20 +3,38 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.net.URI; + @Configuration @ConditionalOnProperty(prefix = "hapi.fhir", name = "staticLocation") public class ExtraStaticFilesConfigurer implements WebMvcConfigurer { - @Autowired - AppProperties appProperties; + public static final String ROOT_CONTEXT_PATH = "/static"; + @Autowired + AppProperties appProperties; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry theRegistry) { + theRegistry.addResourceHandler(ROOT_CONTEXT_PATH + "/**").addResourceLocations(appProperties.getStaticLocation()); + } + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + String path = URI.create(appProperties.getStaticLocation()).getPath(); + String lastSegment = path.substring(path.lastIndexOf('/') + 1); + + registry.addViewController(ROOT_CONTEXT_PATH).setViewName("redirect:" + ROOT_CONTEXT_PATH + "/" + lastSegment + "/index.html"); + + registry.addViewController(ROOT_CONTEXT_PATH + "/*").setViewName("redirect:" + ROOT_CONTEXT_PATH + "/" + lastSegment + "/index.html"); + + registry.addViewController(ROOT_CONTEXT_PATH + "/" + lastSegment + "/").setViewName("redirect:" + ROOT_CONTEXT_PATH + "/" + lastSegment + "/index.html"); + + registry.setOrder(Ordered.HIGHEST_PRECEDENCE); + } - @Override - public void addResourceHandlers(ResourceHandlerRegistry theRegistry) { - theRegistry - .addResourceHandler("/static/**") - .addResourceLocations(appProperties.getStaticLocation()); - } } \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index f2a92693ec7..fc94a82b707 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -64,7 +64,8 @@ hapi: ### alternatively, it may be set using the X-Forwarded-Proto header. # use_apache_address_strategy_https: false ### enables the server to host content like HTML, css, etc. under the url pattern of /static/** - # staticLocation: file:/usr/somewhere/ + ### the deepest folder level will be used. E.g. - if you put file:/foo/bar/bazz as value then the files are resolved under /static/bazz/** + #staticLocation: file:/foo/bar/bazz ### enable to set the Server URL # server_address: http://hapi.fhir.org/baseR4 # defer_indexing_for_codesystems_of_size: 101 From ef8c487da43cfe6bb43d1dd2cadc004194ccd126 Mon Sep 17 00:00:00 2001 From: chgl Date: Tue, 10 Jan 2023 20:52:16 +0100 Subject: [PATCH 131/192] Updated Helm chart to use hapi fhir image 6.2.2 (#472) --- charts/hapi-fhir-jpaserver/Chart.yaml | 12 ++++-------- charts/hapi-fhir-jpaserver/README.md | 4 ++-- .../templates/tests/test-endpoints.yaml | 6 +++--- charts/hapi-fhir-jpaserver/values.yaml | 2 +- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index 736c5d5e577..91580077790 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -10,18 +10,14 @@ dependencies: version: 12.1.2 repository: https://charts.bitnami.com/bitnami condition: postgresql.enabled -appVersion: 6.2.1 -version: 0.11.0 +appVersion: 6.2.2 +version: 0.11.1 annotations: artifacthub.io/license: Apache-2.0 artifacthub.io/changes: | # When using the list of objects option the valid supported kinds are # added, changed, deprecated, removed, fixed, and security. - kind: changed - description: updated HAPI FHIR JPA Server app image version to v6.2.1 + description: updated HAPI FHIR JPA Server app image version to v6.2.2 - kind: changed - description: | - Reduced `startupProbe.initialDelaySeconds` to a more realistic `30` from `60`. - This should allow the server to become ready quicker and recover from failures faster. - - kind: changed - description: "⚠️ BREAKING CHANGE: updated included postgresql chart to v12, which is based on PostgreSQL 15.1" + description: updated curl used by helm tests to version to v7.87.0 diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index 5ab71f70228..8b4b4619d43 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -1,6 +1,6 @@ # HAPI FHIR JPA Server Starter Helm Chart -![Version: 0.11.0](https://img.shields.io/badge/Version-0.11.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.2.1](https://img.shields.io/badge/AppVersion-6.2.1-informational?style=flat-square) +![Version: 0.11.1](https://img.shields.io/badge/Version-0.11.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.2.2](https://img.shields.io/badge/AppVersion-6.2.2-informational?style=flat-square) This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment. @@ -32,7 +32,7 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | image.pullPolicy | string | `"IfNotPresent"` | image pullPolicy to use | | image.registry | string | `"docker.io"` | registry where the HAPI FHIR server image is hosted | | image.repository | string | `"hapiproject/hapi"` | the path inside the repository | -| image.tag | string | `"v6.2.1@sha256:8d1b4c1c8abd613f685267a3dda494d87aba4cff449eed39902a6ece2c086f3c"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. | +| image.tag | string | `"v6.2.2@sha256:9c4e8af94d81ac0049dbb589e4cd855bf78c9c13be6f6844e814c63d63545b44"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. | | imagePullSecrets | list | `[]` | image pull secrets to use when pulling the image | | ingress.annotations | object | `{}` | provide any additional annotations which may be required. Evaluated as a template. | | ingress.enabled | bool | `false` | whether to create an Ingress to expose the FHIR server HTTP endpoint | diff --git a/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml index bf99dbce369..034efb12e02 100644 --- a/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml +++ b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml @@ -11,7 +11,7 @@ spec: restartPolicy: Never containers: - name: test-metadata-endpoint - image: docker.io/curlimages/curl:7.86.0@sha256:cfdeba7f88bb85f6c87f2ec9135115b523a1c24943976a61fbf59c4f2eafd78e + image: docker.io/curlimages/curl:7.87.0@sha256:f7f265d5c64eb4463a43a99b6bf773f9e61a50aaa7cefaf564f43e42549a01dd command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/metadata?_summary=true"] {{- with .Values.restrictedContainerSecurityContext }} @@ -32,7 +32,7 @@ spec: exec: command: ["true"] - name: test-patient-endpoint - image: docker.io/curlimages/curl:7.86.0@sha256:cfdeba7f88bb85f6c87f2ec9135115b523a1c24943976a61fbf59c4f2eafd78e + image: docker.io/curlimages/curl:7.87.0@sha256:f7f265d5c64eb4463a43a99b6bf773f9e61a50aaa7cefaf564f43e42549a01dd command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/Patient?_count=1&_summary=true"] {{- with .Values.restrictedContainerSecurityContext }} @@ -53,7 +53,7 @@ spec: exec: command: ["true"] - name: test-metrics-endpoint - image: docker.io/curlimages/curl:7.86.0@sha256:cfdeba7f88bb85f6c87f2ec9135115b523a1c24943976a61fbf59c4f2eafd78e + image: docker.io/curlimages/curl:7.87.0@sha256:f7f265d5c64eb4463a43a99b6bf773f9e61a50aaa7cefaf564f43e42549a01dd command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.metrics.service.port }}/actuator/prometheus"] {{- with .Values.restrictedContainerSecurityContext }} diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index b55d4ea7ea0..be02b18983b 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -7,7 +7,7 @@ image: # -- the path inside the repository repository: hapiproject/hapi # -- the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. - tag: "v6.2.1@sha256:8d1b4c1c8abd613f685267a3dda494d87aba4cff449eed39902a6ece2c086f3c" + tag: "v6.2.2@sha256:9c4e8af94d81ac0049dbb589e4cd855bf78c9c13be6f6844e814c63d63545b44" # -- image pullPolicy to use pullPolicy: IfNotPresent From 38ed00a84b1b7ff70771b5367e85ca41f7301251 Mon Sep 17 00:00:00 2001 From: Luke deGruchy Date: Tue, 10 Jan 2023 16:53:57 -0500 Subject: [PATCH 132/192] Implement a new solution: Instead of static code blocks disabling logging, rollback slf4j-api, logback-classic, and logback-core to older versions. It's the addition of the rollback for slf4j-api that seems to restore logging. --- pom.xml | 19 +++++++++++++++++++ .../ca/uhn/fhir/jpa/starter/Application.java | 4 ---- .../uhn/fhir/jpa/starter/CustomBeanTest.java | 4 ---- .../jpa/starter/CustomInterceptorTest.java | 4 ---- .../jpa/starter/ElasticsearchLastNR4IT.java | 4 ---- .../jpa/starter/ExampleServerDstu2IT.java | 4 ---- .../jpa/starter/ExampleServerDstu3IT.java | 4 ---- .../fhir/jpa/starter/ExampleServerR4BIT.java | 4 ---- .../fhir/jpa/starter/ExampleServerR4IT.java | 5 ----- .../fhir/jpa/starter/ExampleServerR5IT.java | 6 +----- .../jpa/starter/MultitenantServerR4IT.java | 3 --- 11 files changed, 20 insertions(+), 41 deletions(-) diff --git a/pom.xml b/pom.xml index d56db5cfdbd..bfa441943f3 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,8 @@ 11 + 1.2.11 + 1.7.25 @@ -357,6 +359,23 @@ test + + org.slf4j + slf4j-api + ${slf4j-api.version} + + + + ch.qos.logback + logback-classic + ${logback-classic.version} + + + ch.qos.logback + logback-core + ${logback-classic.version} + + 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 71ada0b8b86..8031c598f7e 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -38,10 +38,6 @@ }) public class Application extends SpringBootServletInitializer { - static { - System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); - } - public static void main(String[] args) { SpringApplication.run(Application.class, args); diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java index 842798c04b3..af9db0d98fc 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java @@ -13,10 +13,6 @@ }) public class CustomBeanTest { - static { - System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); - } - @Autowired some.custom.pkg1.CustomBean customBean1; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java index 99392102534..377719e22f1 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java @@ -23,10 +23,6 @@ public class CustomInterceptorTest { - static { - System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); - } - @LocalServerPort private int port; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 0aea7f8eb58..064c2401492 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -57,10 +57,6 @@ }) @ContextConfiguration(initializers = ElasticsearchLastNR4IT.Initializer.class) public class ElasticsearchLastNR4IT { - static { - System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); - } - private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java index 1c5a5653e25..e20aff8ff8a 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -23,10 +23,6 @@ }) public class ExampleServerDstu2IT { - static { - System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); - } - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index d7745bdfcb3..826f31152e3 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -51,10 +51,6 @@ public class ExampleServerDstu3IT implements IServerSupport { - static { - System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); - } - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java index 2157c28f5f1..fc7bf58c4f9 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java @@ -25,10 +25,6 @@ // when running in a spring boot environment "spring.main.allow-bean-definition-overriding=true"}) class ExampleServerR4BIT { - - static { - System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); - } private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerR4BIT.class); private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 44808add08a..278a5f0ccc8 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -43,11 +43,6 @@ // when running in a spring boot environment "spring.main.allow-bean-definition-overriding=true" }) class ExampleServerR4IT { - - static { - System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); - } - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerR4IT.class); private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index f8e807e75c4..ddbd6a77ac1 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -41,11 +41,7 @@ }) public class ExampleServerR5IT { - static { - System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); - } - - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); private IGenericClient ourClient; private FhirContext ourCtx; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java index a5c2da563b9..9d340b12444 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -28,9 +28,6 @@ }) public class MultitenantServerR4IT { - static { - System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); - } private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); private IGenericClient ourClient; From ea3d858563e97b5e6cd617ecd1c4e0ece6e08dcc Mon Sep 17 00:00:00 2001 From: James Agnew Date: Wed, 11 Jan 2023 16:30:12 -0500 Subject: [PATCH 133/192] Fix tests for websocket --- .../uhn/fhir/jpa/starter/CustomBeanTest.java | 2 +- .../jpa/starter/CustomInterceptorTest.java | 2 +- .../jpa/starter/ElasticsearchLastNR4IT.java | 2 +- .../jpa/starter/ExampleServerDstu2IT.java | 2 +- .../jpa/starter/ExampleServerDstu3IT.java | 2 +- .../fhir/jpa/starter/ExampleServerR4BIT.java | 2 +- .../fhir/jpa/starter/ExampleServerR4IT.java | 2 +- .../fhir/jpa/starter/ExampleServerR5IT.java | 2 +- .../JpaStarterWebsocketDispatcherConfig.java | 34 +++++++++++++++++++ .../jpa/starter/MultitenantServerR4IT.java | 2 +- 10 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 src/test/java/ca/uhn/fhir/jpa/starter/JpaStarterWebsocketDispatcherConfig.java diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java index af9db0d98fc..07e7f581a30 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java @@ -5,7 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "hapi.fhir.custom-bean-packages=some.custom.pkg1,some.custom.pkg2", "spring.datasource.url=jdbc:h2:mem:dbr4", // "hapi.fhir.enable_repository_validating_interceptor=true", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java index 377719e22f1..367857b7009 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java @@ -13,7 +13,7 @@ import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "hapi.fhir.custom-bean-packages=some.custom.pkg1", "hapi.fhir.custom-interceptor-classes=some.custom.pkg1.CustomInterceptorBean,some.custom.pkg1.CustomInterceptorPojo", "spring.datasource.url=jdbc:h2:mem:dbr4", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 064c2401492..5cb0a4e7072 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -36,7 +36,7 @@ import org.testcontainers.elasticsearch.ElasticsearchContainer; @ExtendWith(SpringExtension.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr4", "hapi.fhir.fhir_version=r4", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java index e20aff8ff8a..4369086733f 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(SpringExtension.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "hapi.fhir.fhir_version=dstu2", "spring.datasource.url=jdbc:h2:mem:dbr2", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index 826f31152e3..fb90784c99d 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -38,7 +38,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @ExtendWith(SpringExtension.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr3", "hapi.fhir.cql_enabled=true", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java index fc7bf58c4f9..9f19fcb74de 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java @@ -14,7 +14,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr4b", "hapi.fhir.enable_repository_validating_interceptor=true", "hapi.fhir.fhir_version=r4b", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 278a5f0ccc8..319ed1cd7a2 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -30,7 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = { +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr4", "hapi.fhir.enable_repository_validating_interceptor=true", "hapi.fhir.fhir_version=r4", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index ddbd6a77ac1..87e012197f9 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -32,7 +32,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr5", "hapi.fhir.fhir_version=r5", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/JpaStarterWebsocketDispatcherConfig.java b/src/test/java/ca/uhn/fhir/jpa/starter/JpaStarterWebsocketDispatcherConfig.java new file mode 100644 index 00000000000..3503338fc79 --- /dev/null +++ b/src/test/java/ca/uhn/fhir/jpa/starter/JpaStarterWebsocketDispatcherConfig.java @@ -0,0 +1,34 @@ +package ca.uhn.fhir.jpa.starter; + +import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer; +import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * This class ensures that websockets work with + * Spring + Spring Boot + Jetty + */ +@Configuration +public class JpaStarterWebsocketDispatcherConfig { + + @Bean + public Jetty10WebSocketServletWebServerCustomizer jetty10WebSocketServletWebServerCustomizer() { + return new Jetty10WebSocketServletWebServerCustomizer(); + } + + static class Jetty10WebSocketServletWebServerCustomizer implements WebServerFactoryCustomizer { + + @Override + public void customize(JettyServletWebServerFactory factory) { + + factory.addServerCustomizers(server -> { + WebAppContext ctx = (WebAppContext) server.getHandler(); + JettyWebSocketServletContainerInitializer.configure(ctx, null); + }); + + } + } +} diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java index 9d340b12444..463a1c6c0ad 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -18,7 +18,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(SpringExtension.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class, properties = +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr4-mt", "hapi.fhir.fhir_version=r4", From 8f528dbddbb62c2849bdba33bd75ce44b4cea4be Mon Sep 17 00:00:00 2001 From: Luke deGruchy Date: Wed, 11 Jan 2023 17:09:38 -0500 Subject: [PATCH 134/192] Update pipeline to run integration tests. --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 7fc93b8be73..405c48a6001 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -26,4 +26,4 @@ jobs: with: java-version: 17 - name: Build with Maven - run: mvn -B package --file pom.xml + run: mvn -B package --file pom.xml verify From 7c89addbefe20a44534197434e04e02b511c6cf8 Mon Sep 17 00:00:00 2001 From: Panayiotis Savva Date: Mon, 16 Jan 2023 02:27:33 +0200 Subject: [PATCH 135/192] Initial IPS + Cql to Cr migration --- .vscode/launch.json | 14 ++++++++++ .vscode/settings.json | 3 ++- pom.xml | 10 +++++-- .../starter/common/FhirServerConfigDstu3.java | 4 +-- .../starter/common/FhirServerConfigR4.java | 4 +-- .../jpa/starter/common/StarterJpaConfig.java | 27 ++++++++++++++++++- .../jpa/starter/cql/StarterCqlR4Config.java | 11 -------- .../CrConfigCondition.java} | 6 ++--- .../StarterCrDstu3Config.java} | 10 +++---- .../jpa/starter/cr/StarterCrR4Config.java | 11 ++++++++ src/main/resources/application.yaml | 4 +-- 11 files changed, 75 insertions(+), 29 deletions(-) create mode 100644 .vscode/launch.json delete mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/cql/StarterCqlR4Config.java rename src/main/java/ca/uhn/fhir/jpa/starter/{cql/CqlConfigCondition.java => cr/CrConfigCondition.java} (77%) rename src/main/java/ca/uhn/fhir/jpa/starter/{cql/StarterCqlDstu3Config.java => cr/StarterCrDstu3Config.java} (53%) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrR4Config.java diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000000..b898333e5cd --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + "configurations": [ + { + "type": "java", + "name": "Spring Boot-Application", + "request": "launch", + "cwd": "${workspaceFolder}", + "mainClass": "ca.uhn.fhir.jpa.starter.Application", + "projectName": "hapi-fhir-jpaserver-starter", + "args": "", + "envFile": "${workspaceFolder}/.env" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 2421e386c30..5b1ccac9909 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,6 @@ "**/.project": true, "**/.settings": true, "**/.factorypath": true - } + }, + "java.compile.nullAnalysis.mode": "disabled" } \ No newline at end of file diff --git a/pom.xml b/pom.xml index bfa441943f3..428df3e32cd 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.6-SNAPSHOT + 6.3.7-SNAPSHOT hapi-fhir-jpaserver-starter @@ -117,7 +117,7 @@ ca.uhn.hapi.fhir - hapi-fhir-jpaserver-cql + hapi-fhir-storage-cr ${project.version} @@ -146,6 +146,12 @@ ${project.version} classes + + + ca.uhn.hapi.fhir + hapi-fhir-jpaserver-ips + ${project.version} + diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java index 0e0c76358d1..bb0f12f164c 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java @@ -2,7 +2,7 @@ import ca.uhn.fhir.jpa.config.dstu3.JpaDstu3Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU3Condition; -import ca.uhn.fhir.jpa.starter.cql.StarterCqlDstu3Config; +import ca.uhn.fhir.jpa.starter.cr.StarterCrDstu3Config; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -12,7 +12,7 @@ @Import({ JpaDstu3Config.class, StarterJpaConfig.class, - StarterCqlDstu3Config.class, + StarterCrDstu3Config.class, ElasticsearchConfig.class}) public class FhirServerConfigDstu3 { } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java index 6ee7a990846..0e1e6360660 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java @@ -2,7 +2,7 @@ import ca.uhn.fhir.jpa.config.r4.JpaR4Config; import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; -import ca.uhn.fhir.jpa.starter.cql.StarterCqlR4Config; +import ca.uhn.fhir.jpa.starter.cr.StarterCrR4Config; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -12,7 +12,7 @@ @Import({ JpaR4Config.class, StarterJpaConfig.class, - StarterCqlR4Config.class, + StarterCrR4Config.class, ElasticsearchConfig.class }) public class FhirServerConfigR4 { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 3fac5b7ce57..c9bf910b667 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -30,6 +30,11 @@ import ca.uhn.fhir.jpa.graphql.GraphQLProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; +import ca.uhn.fhir.jpa.ips.api.IIpsGenerationStrategy; +import ca.uhn.fhir.jpa.ips.generator.DefaultIpsGenerationStrategy; +import ca.uhn.fhir.jpa.ips.generator.IIpsGeneratorSvc; +import ca.uhn.fhir.jpa.ips.generator.IpsGeneratorSvcImpl; +import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider; import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc; import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; import ca.uhn.fhir.jpa.partition.PartitionManagementProvider; @@ -238,7 +243,7 @@ public CorsInterceptor corsInterceptor(AppProperties appProperties) { } @Bean - public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext) { + public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext, IpsOperationProvider theIpsOperationProvider) { RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext()); List supportedResourceTypes = appProperties.getSupported_resource_types(); @@ -408,9 +413,29 @@ public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProper // register custom interceptors registerCustomInterceptors(fhirServer, appContext, appProperties.getCustomInterceptorClasses()); + + //register the IPS Provider + fhirServer.registerProvider(theIpsOperationProvider); return fhirServer; } + @Bean + public IIpsGeneratorSvc IpsGeneratorSvcImpl(FhirContext theFhirContext, IIpsGenerationStrategy theGenerationStrategy, DaoRegistry theDaoRegistry) + { + return new IpsGeneratorSvcImpl(theFhirContext, theGenerationStrategy, theDaoRegistry); + } + + @Bean + public IpsOperationProvider IpsOperationProvider(IIpsGeneratorSvc theIpsGeneratorSvc){ + return new IpsOperationProvider(theIpsGeneratorSvc); + } + + @Bean IIpsGenerationStrategy IpsGenerationStrategy() + { + return new DefaultIpsGenerationStrategy(); + } + + /** * check the properties for custom interceptor classes and registers them. */ diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cql/StarterCqlR4Config.java b/src/main/java/ca/uhn/fhir/jpa/starter/cql/StarterCqlR4Config.java deleted file mode 100644 index ff9bf169b20..00000000000 --- a/src/main/java/ca/uhn/fhir/jpa/starter/cql/StarterCqlR4Config.java +++ /dev/null @@ -1,11 +0,0 @@ -package ca.uhn.fhir.jpa.starter.cql; - -import ca.uhn.fhir.cql.config.CqlR4Config; -import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; -import org.springframework.context.annotation.Conditional; -import org.springframework.context.annotation.Import; - -@Conditional({OnR4Condition.class, CqlConfigCondition.class}) -@Import({CqlR4Config.class}) -public class StarterCqlR4Config { -} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cql/CqlConfigCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java similarity index 77% rename from src/main/java/ca/uhn/fhir/jpa/starter/cql/CqlConfigCondition.java rename to src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java index 38622ba9d89..b488bcfe1fa 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/cql/CqlConfigCondition.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java @@ -1,14 +1,14 @@ -package ca.uhn.fhir.jpa.starter.cql; +package ca.uhn.fhir.jpa.starter.cr; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; -public class CqlConfigCondition implements Condition { +public class CrConfigCondition implements Condition { @Override public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) { - String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cql_enabled"); + String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cr_enabled"); return Boolean.parseBoolean(property); } } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cql/StarterCqlDstu3Config.java b/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrDstu3Config.java similarity index 53% rename from src/main/java/ca/uhn/fhir/jpa/starter/cql/StarterCqlDstu3Config.java rename to src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrDstu3Config.java index 5753dce2f8a..9efc08645b9 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/cql/StarterCqlDstu3Config.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrDstu3Config.java @@ -1,13 +1,13 @@ -package ca.uhn.fhir.jpa.starter.cql; +package ca.uhn.fhir.jpa.starter.cr; -import ca.uhn.fhir.cql.config.CqlDstu3Config; +import ca.uhn.fhir.cr.config.CrDstu3Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU3Condition; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration -@Conditional({OnDSTU3Condition.class, CqlConfigCondition.class}) -@Import({CqlDstu3Config.class}) -public class StarterCqlDstu3Config { +@Conditional({OnDSTU3Condition.class, CrConfigCondition.class}) +@Import({CrDstu3Config.class}) +public class StarterCrDstu3Config { } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrR4Config.java b/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrR4Config.java new file mode 100644 index 00000000000..a97cea7835f --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrR4Config.java @@ -0,0 +1,11 @@ +package ca.uhn.fhir.jpa.starter.cr; + +import ca.uhn.fhir.cr.config.CrR4Config; +import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Import; + +@Conditional({OnR4Condition.class, CrConfigCondition.class}) +@Import({CrR4Config.class}) +public class StarterCrR4Config { +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index fc94a82b707..52cfa8504a7 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -93,7 +93,7 @@ hapi: # allow_multiple_delete: true # allow_override_default_search_params: true # auto_create_placeholder_reference_targets: false - # cql_enabled: true + # cr_enabled: true # default_encoding: JSON # default_pretty_print: true # default_page_size: 20 @@ -117,7 +117,7 @@ hapi: # fhirpath_interceptor_enabled: false # filter_search_enabled: true # graphql_enabled: true - # narrative_enabled: true + narrative_enabled: false # mdm_enabled: true # local_base_urls: # - https://hapi.fhir.org/baseR4 From c7ee984b301d1bd1aa8d41c47f6dd9f27b8fbc24 Mon Sep 17 00:00:00 2001 From: Panayiotis Savva Date: Mon, 16 Jan 2023 03:32:58 +0200 Subject: [PATCH 136/192] Allow Enabling IPS via config --- .../uhn/fhir/jpa/starter/AppProperties.java | 20 ++++++++--- .../starter/common/FhirServerConfigDstu3.java | 2 +- .../starter/common/FhirServerConfigR4.java | 5 ++- .../jpa/starter/common/StarterJpaConfig.java | 29 ++++------------ .../jpa/starter/cr/CrConfigCondition.java | 2 +- .../jpa/starter/ips/IpsConfigCondition.java | 14 ++++++++ .../jpa/starter/ips/StarterIpsConfig.java | 34 +++++++++++++++++++ src/main/resources/application.yaml | 1 + 8 files changed, 76 insertions(+), 31 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/ips/IpsConfigCondition.java create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java 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 8d3e878e1c2..fa0dac29858 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -21,7 +21,8 @@ @EnableConfigurationProperties public class AppProperties { - private Boolean cql_enabled = false; + private Boolean cr_enabled = false; + private Boolean ips_enabled = false; private Boolean openapi_enabled = false; private Boolean mdm_enabled = false; private boolean advanced_lucene_indexing = false; @@ -149,14 +150,23 @@ public void setPartitioning(Partitioning partitioning) { this.partitioning = partitioning; } - public Boolean getCql_enabled() { - return cql_enabled; + public Boolean getCr_enabled() { + return cr_enabled; } - public void setCql_enabled(Boolean cql_enabled) { - this.cql_enabled = cql_enabled; + public void setCr_enabled(Boolean cr_enabled) { + this.cr_enabled = cr_enabled; } + public Boolean getIps_enabled() { + return ips_enabled; + } + + public void setIps_enabled(Boolean ips_enabled) { + this.ips_enabled = ips_enabled; + } + + public Boolean getMdm_enabled() { return mdm_enabled; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java index bb0f12f164c..085764d1bd6 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java @@ -12,7 +12,7 @@ @Import({ JpaDstu3Config.class, StarterJpaConfig.class, - StarterCrDstu3Config.class, + StarterCrDstu3Config.class, ElasticsearchConfig.class}) public class FhirServerConfigDstu3 { } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java index 0e1e6360660..61dbab53a9a 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java @@ -3,6 +3,8 @@ import ca.uhn.fhir.jpa.config.r4.JpaR4Config; import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; import ca.uhn.fhir.jpa.starter.cr.StarterCrR4Config; +import ca.uhn.fhir.jpa.starter.ips.StarterIpsConfig; + import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -13,7 +15,8 @@ JpaR4Config.class, StarterJpaConfig.class, StarterCrR4Config.class, - ElasticsearchConfig.class + ElasticsearchConfig.class, + StarterIpsConfig.class }) public class FhirServerConfigR4 { } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index c9bf910b667..3c8abd07123 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -30,10 +30,6 @@ import ca.uhn.fhir.jpa.graphql.GraphQLProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; -import ca.uhn.fhir.jpa.ips.api.IIpsGenerationStrategy; -import ca.uhn.fhir.jpa.ips.generator.DefaultIpsGenerationStrategy; -import ca.uhn.fhir.jpa.ips.generator.IIpsGeneratorSvc; -import ca.uhn.fhir.jpa.ips.generator.IpsGeneratorSvcImpl; import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider; import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc; import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; @@ -47,6 +43,7 @@ import ca.uhn.fhir.jpa.starter.annotations.OnCorsPresent; import ca.uhn.fhir.jpa.starter.annotations.OnImplementationGuidesPresent; import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory; +import ca.uhn.fhir.jpa.starter.ips.IpsConfigCondition; import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper; import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor; import ca.uhn.fhir.jpa.util.ResourceCountCache; @@ -243,7 +240,7 @@ public CorsInterceptor corsInterceptor(AppProperties appProperties) { } @Bean - public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext, IpsOperationProvider theIpsOperationProvider) { + public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext, Optional theIpsOperationProvider) { RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext()); List supportedResourceTypes = appProperties.getSupported_resource_types(); @@ -415,27 +412,13 @@ public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProper //register the IPS Provider - fhirServer.registerProvider(theIpsOperationProvider); - return fhirServer; - } - - @Bean - public IIpsGeneratorSvc IpsGeneratorSvcImpl(FhirContext theFhirContext, IIpsGenerationStrategy theGenerationStrategy, DaoRegistry theDaoRegistry) - { - return new IpsGeneratorSvcImpl(theFhirContext, theGenerationStrategy, theDaoRegistry); - } - - @Bean - public IpsOperationProvider IpsOperationProvider(IIpsGeneratorSvc theIpsGeneratorSvc){ - return new IpsOperationProvider(theIpsGeneratorSvc); - } + if (!theIpsOperationProvider.isEmpty()) { + fhirServer.registerProvider(theIpsOperationProvider.get()); + } - @Bean IIpsGenerationStrategy IpsGenerationStrategy() - { - return new DefaultIpsGenerationStrategy(); + return fhirServer; } - /** * check the properties for custom interceptor classes and registers them. */ diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java index b488bcfe1fa..72e331c7ba8 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java @@ -8,7 +8,7 @@ public class CrConfigCondition implements Condition { @Override public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) { - String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cr_enabled"); + String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cql_enabled"); return Boolean.parseBoolean(property); } } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ips/IpsConfigCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/ips/IpsConfigCondition.java new file mode 100644 index 00000000000..973491a1f3f --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ips/IpsConfigCondition.java @@ -0,0 +1,14 @@ +package ca.uhn.fhir.jpa.starter.ips; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class IpsConfigCondition implements Condition { + + @Override + public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) { + String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.ips_enabled"); + return Boolean.parseBoolean(property); + } +} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java new file mode 100644 index 00000000000..698fd919065 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java @@ -0,0 +1,34 @@ +package ca.uhn.fhir.jpa.starter.ips; + +import org.springframework.context.annotation.Bean; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.jpa.ips.api.IIpsGenerationStrategy; +import ca.uhn.fhir.jpa.ips.generator.DefaultIpsGenerationStrategy; +import ca.uhn.fhir.jpa.ips.generator.IIpsGeneratorSvc; +import org.springframework.context.annotation.Conditional; +import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider; +import ca.uhn.fhir.jpa.ips.generator.IpsGeneratorSvcImpl; + + +@Conditional(IpsConfigCondition.class) +public class StarterIpsConfig { + @Bean + IIpsGenerationStrategy IpsGenerationStrategy() + { + return new DefaultIpsGenerationStrategy(); + } + + @Bean + public IpsOperationProvider IpsOperationProvider(IIpsGeneratorSvc theIpsGeneratorSvc){ + return new IpsOperationProvider(theIpsGeneratorSvc); + } + + @Bean + public IIpsGeneratorSvc IpsGeneratorSvcImpl(FhirContext theFhirContext, IIpsGenerationStrategy theGenerationStrategy, DaoRegistry theDaoRegistry) + { + return new IpsGeneratorSvcImpl(theFhirContext, theGenerationStrategy, theDaoRegistry); + } + +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 52cfa8504a7..405d03a24a2 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -94,6 +94,7 @@ hapi: # allow_override_default_search_params: true # auto_create_placeholder_reference_targets: false # cr_enabled: true + # ips_enabled: false # default_encoding: JSON # default_pretty_print: true # default_page_size: 20 From 99ea176a9cd11c53c5b30662a62ef2ac50cfd38e Mon Sep 17 00:00:00 2001 From: Panayiotis Savva Date: Mon, 16 Jan 2023 03:35:30 +0200 Subject: [PATCH 137/192] typo --- src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java index 72e331c7ba8..b488bcfe1fa 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java @@ -8,7 +8,7 @@ public class CrConfigCondition implements Condition { @Override public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) { - String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cql_enabled"); + String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cr_enabled"); return Boolean.parseBoolean(property); } } From e905da77338dc7bb8f5d08b18d7a953b8206223f Mon Sep 17 00:00:00 2001 From: Panayiotis Savva Date: Mon, 16 Jan 2023 03:38:17 +0200 Subject: [PATCH 138/192] CQL to CR --- README.md | 4 ++-- .../java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java | 2 +- src/test/resources/application.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3d9d0b8bc44..3b2a1efeef9 100644 --- a/README.md +++ b/README.md @@ -374,9 +374,9 @@ The server may be configured with subscription support by enabling properties in - `hapi.fhir.subscription.websocket_enabled` - Enables websocket subscriptions. With this enabled, your server will accept incoming websocket connections on the following URL (this example uses the default context path and port, you may need to tweak depending on your deployment environment): [ws://localhost:8080/websocket](ws://localhost:8080/websocket) -## Enabling CQL +## Enabling Clinical Reasoning -Set `hapi.fhir.cql_enabled=true` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file to enable [Clinical Quality Language](https://cql.hl7.org/) on this server. +Set `hapi.fhir.cr_enabled=true` in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file to enable [Clinical Quality Language](https://cql.hl7.org/) on this server. ## Enabling MDM (EMPI) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index fb90784c99d..850bdb36c98 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -41,7 +41,7 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr3", - "hapi.fhir.cql_enabled=true", + "hapi.fhir.cr_enabled=true", "hapi.fhir.fhir_version=dstu3", "hapi.fhir.subscription.websocket_enabled=true", "hapi.fhir.allow_external_references=true", diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml index 4794df57468..89229c9f0a1 100644 --- a/src/test/resources/application.yaml +++ b/src/test/resources/application.yaml @@ -78,7 +78,7 @@ hapi: # allow_multiple_delete: true # allow_override_default_search_params: true # auto_create_placeholder_reference_targets: false - # cql_enabled: true + # cr_enabled: true # default_encoding: JSON # default_pretty_print: true # default_page_size: 20 From 64b497e4e9b17f38c77b83a3b7085fc06a994604 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Tue, 24 Jan 2023 13:30:09 -0500 Subject: [PATCH 139/192] HAPI FHIR bump --- pom.xml | 2 +- src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 428df3e32cd..8987c6d3631 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.7-SNAPSHOT + 6.3.13-SNAPSHOT hapi-fhir-jpaserver-starter diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java index 698fd919065..e777879a580 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java @@ -5,7 +5,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.ips.api.IIpsGenerationStrategy; -import ca.uhn.fhir.jpa.ips.generator.DefaultIpsGenerationStrategy; +import ca.uhn.fhir.jpa.ips.strategy.DefaultIpsGenerationStrategy; import ca.uhn.fhir.jpa.ips.generator.IIpsGeneratorSvc; import org.springframework.context.annotation.Conditional; import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider; From 3f669739528303c940601b9a024a4917193848fb Mon Sep 17 00:00:00 2001 From: Juvar Abrera Date: Sat, 4 Feb 2023 21:20:37 +0800 Subject: [PATCH 140/192] docs: Updated README.md. Discontinue mysql --- README.md | 47 +++++++++++------------------------------------ 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 3b2a1efeef9..2fb5359f679 100644 --- a/README.md +++ b/README.md @@ -177,35 +177,11 @@ Server will then be accessible at http://localhost:8080/ and eg. http://localhos Much of this HAPI starter project can be configured using the yaml file in _src/main/resources/application.yaml_. By default, this starter project is configured to use H2 as the database. -### MySql configuration +### MySQL configuration -To configure the starter app to use MySQL, instead of the default H2, update the application.yaml file to have the following: +HAPI FHIR JPA Server does not support MySQL as it is deprecated. -```yaml -spring: - datasource: - url: 'jdbc:mysql://localhost:3306/hapi_dstu3' - username: admin - password: admin - driverClassName: com.mysql.jdbc.Driver -``` - -Also, make sure you are not setting the Hibernate dialect explicitly, in other words remove any lines similar to: - -``` -hibernate.dialect: {some none MySQL dialect} -``` - -On some systems, it might be necessary to override hibernate's default naming strategy. The naming strategy must be set using spring.jpa.hibernate.physical_naming_strategy. - -```yaml -spring: - jpa: - hibernate.physical_naming_strategy: NAME_OF_PREFERRED_STRATEGY -``` -On linux systems or when using docker mysql containers, it will be necessary to review the case-sensitive setup for -mysql schema identifiers. See https://dev.mysql.com/doc/refman/8.0/en/identifier-case-sensitivity.html. We suggest you -set `lower_case_table_names=1` during mysql startup. +See more at https://hapifhir.io/hapi-fhir/docs/server_jpa/database_support.html ### PostgreSQL configuration @@ -214,7 +190,7 @@ To configure the starter app to use PostgreSQL, instead of the default H2, updat ```yaml spring: datasource: - url: 'jdbc:postgresql://localhost:5432/hapi_dstu3' + url: 'jdbc:postgresql://localhost:5432/hapi' username: admin password: admin driverClassName: org.postgresql.Driver @@ -313,20 +289,21 @@ reached at http://localhost:8080/. In order to use another port, change the `ports` parameter inside `docker-compose.yml` to `8888:8080`, where 8888 is a port of your choice. -The docker compose set also includes my MySQL database, if you choose to use MySQL instead of H2, change the following -properties in application.yaml: +The docker compose set also includes my PoPostgreSQL database, if you choose to use PostgreSQL instead of H2, change the following +properties in `src/main/resources/application.yaml`: ```yaml spring: datasource: - url: 'jdbc:mysql://hapi-fhir-mysql:3306/hapi' + url: 'jdbc:postgresql://hapi-fhir-postgres:5432/hapi' username: admin password: admin - driverClassName: com.mysql.jdbc.Driver + driverClassName: org.postgresql.Driver +jpa: + properties: + hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect ``` -Also, make sure you are not setting the Hibernate Dialect explicitly, see more details in the section about MySQL. - ## Running hapi-fhir-jpaserver directly from IntelliJ as Spring Boot Make sure you run with the maven profile called ```boot``` and NOT also ```jetty```. Then you are ready to press debug the project directly without any extra Application Servers. @@ -362,8 +339,6 @@ Run the configuration. Point your browser (or fiddler, or what have you) to `http://localhost:8080/hapi/baseDstu3/Patient` -It is important to use MySQL5Dialect when using MySQL version 5+. - ## Enabling Subscriptions The server may be configured with subscription support by enabling properties in the [application.yaml](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/blob/master/src/main/resources/application.yaml) file: From c9bc40c10aeb76120b1d28cb53c2db03b3404d9f Mon Sep 17 00:00:00 2001 From: Craig McClendon Date: Wed, 8 Feb 2023 16:46:15 -0600 Subject: [PATCH 141/192] removed mysql-connector-java dependency since no longer supported and due to CVE-2022-3171 in transitive dependency on protobuf-java-3.19.4 --- pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pom.xml b/pom.xml index 8987c6d3631..8eb0e001ec3 100644 --- a/pom.xml +++ b/pom.xml @@ -54,10 +54,6 @@ websocket-jetty-client ${jetty_version} - - mysql - mysql-connector-java - org.postgresql postgresql From c88d26d2e5657cf2fa8f18e686413805715495fd Mon Sep 17 00:00:00 2001 From: Juvar Abrera Date: Sun, 5 Feb 2023 09:50:41 +0800 Subject: [PATCH 142/192] docs: Fix postgresql typo in docker-compose --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2fb5359f679..123d1fc7d1c 100644 --- a/README.md +++ b/README.md @@ -289,7 +289,7 @@ reached at http://localhost:8080/. In order to use another port, change the `ports` parameter inside `docker-compose.yml` to `8888:8080`, where 8888 is a port of your choice. -The docker compose set also includes my PoPostgreSQL database, if you choose to use PostgreSQL instead of H2, change the following +The docker compose set also includes PostgreSQL database, if you choose to use PostgreSQL instead of H2, change the following properties in `src/main/resources/application.yaml`: ```yaml From b6c1b9f47c17b468e68edc4dd605ad0660f58ce3 Mon Sep 17 00:00:00 2001 From: Juvar Abrera Date: Sun, 5 Feb 2023 20:47:08 +0800 Subject: [PATCH 143/192] docs: Explicitly set hibnerate.search.enabled to false if database is postgresql --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 123d1fc7d1c..b17e46b866d 100644 --- a/README.md +++ b/README.md @@ -197,9 +197,10 @@ spring: jpa: properties: hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect -``` + hibernate.search.enabled: false -Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. + # Then comment all hibernate.search.backend.* +``` ### Microsoft SQL Server configuration From 74be71351588aee7a69e221cc71da52dbe6d77e5 Mon Sep 17 00:00:00 2001 From: Juvar Abrera Date: Sun, 5 Feb 2023 20:48:24 +0800 Subject: [PATCH 144/192] refactor: Separate unrelated settings and documentation --- src/main/resources/application.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 405d03a24a2..502dbfaecdd 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -28,10 +28,10 @@ spring: properties: hibernate.format_sql: false hibernate.show_sql: false + #Hibernate dialect is automatically detected except Postgres and H2. #If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect #If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect - hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect # hibernate.hbm2ddl.auto: update # hibernate.jdbc.batch_size: 20 @@ -39,6 +39,7 @@ spring: # hibernate.cache.use_second_level_cache: false # hibernate.cache.use_structured_entries: false # hibernate.cache.use_minimal_puts: false + ### These settings will enable fulltext search with lucene or elastic hibernate.search.enabled: true ### lucene parameters From 7f7ea920d0e7c39873b2b30f4e8329d7aae270bc Mon Sep 17 00:00:00 2001 From: Juvar Abrera Date: Sun, 5 Feb 2023 20:57:34 +0800 Subject: [PATCH 145/192] docs: Explicitly set hibernate.search.enabled to false if database is postgress in docker-compose instructions --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b17e46b866d..64625b83f85 100644 --- a/README.md +++ b/README.md @@ -303,6 +303,9 @@ spring: jpa: properties: hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect + hibernate.search.enabled: false + + # Then comment all hibernate.search.backend.* ``` ## Running hapi-fhir-jpaserver directly from IntelliJ as Spring Boot From 35d09cce16c6585a86102d9a224319812ab5f4b5 Mon Sep 17 00:00:00 2001 From: Juvar Abrera Date: Sun, 5 Feb 2023 21:10:34 +0800 Subject: [PATCH 146/192] docs: Revert dislaimer in postgres --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 64625b83f85..b6a954837c8 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,8 @@ spring: # Then comment all hibernate.search.backend.* ``` +Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. + ### Microsoft SQL Server configuration To configure the starter app to use MS SQL Server, instead of the default H2, update the application.yaml file to have the following: From 19988c505d8b341d7dee0a838d643d141d992525 Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 14 Feb 2023 12:47:32 -0500 Subject: [PATCH 147/192] Bump Hapi --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8eb0e001ec3..c6f9baf0e9a 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.3.13-SNAPSHOT + 6.4.0 hapi-fhir-jpaserver-starter From 9d126a4f563f60e05f29dd34a926fc5ccfe73627 Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 14 Feb 2023 14:52:03 -0500 Subject: [PATCH 148/192] Fix Application error regarding multiple beans --- src/main/java/ca/uhn/fhir/jpa/starter/Application.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 8031c598f7e..42faf1c1769 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -15,6 +15,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration; +import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.ServletRegistrationBean; @@ -26,7 +27,7 @@ import org.springframework.web.servlet.DispatcherServlet; @ServletComponentScan(basePackageClasses = {RestfulServer.class}) -@SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class}) +@SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class, ThymeleafAutoConfiguration.class}) @Import({ SubscriptionSubmitterConfig.class, SubscriptionProcessorConfig.class, From afcd2fc13138c5f105d81932a473d9afbf2398fe Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 14 Feb 2023 14:52:26 -0500 Subject: [PATCH 149/192] =?UTF-8?q?Add=C2=A0optional=20explicit=20ip=20con?= =?UTF-8?q?fig=20for=20smoke=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/smoketest/http-client.env.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/smoketest/http-client.env.json b/src/test/smoketest/http-client.env.json index 85b8ef4a45d..f4a7afb0b14 100644 --- a/src/test/smoketest/http-client.env.json +++ b/src/test/smoketest/http-client.env.json @@ -3,5 +3,10 @@ "host": "localhost:8080", "username": "username", "password": "password" + }, + "explicit-ip": { + "host": "0.0.0.0:8080", + "username": "username", + "password": "password" } } \ No newline at end of file From 20ed5d90ab6330617b6c64e832bde0c20af0d561 Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 14 Feb 2023 14:52:26 -0500 Subject: [PATCH 150/192] =?UTF-8?q?Revert=20"Add=C2=A0optional=20explicit?= =?UTF-8?q?=20ip=20config=20for=20smoke=20tests"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit afcd2fc13138c5f105d81932a473d9afbf2398fe. --- src/test/smoketest/http-client.env.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/test/smoketest/http-client.env.json b/src/test/smoketest/http-client.env.json index f4a7afb0b14..85b8ef4a45d 100644 --- a/src/test/smoketest/http-client.env.json +++ b/src/test/smoketest/http-client.env.json @@ -3,10 +3,5 @@ "host": "localhost:8080", "username": "username", "password": "password" - }, - "explicit-ip": { - "host": "0.0.0.0:8080", - "username": "username", - "password": "password" } } \ No newline at end of file From 236c1e82bac4749a14f05a7b9d509f0bdee67f5e Mon Sep 17 00:00:00 2001 From: Panayiotis Savva Date: Wed, 1 Mar 2023 14:04:42 +0200 Subject: [PATCH 151/192] Spelling error in Application.yaml Fix spelling error in comments section --- src/main/resources/application.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 502dbfaecdd..f104fbcf293 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -195,7 +195,7 @@ hapi: # quitWait: # lastn_enabled: true # store_resource_in_lucene_index_enabled: true -### This is configuration for normalized quantity serach level default is 0 +### This is configuration for normalized quantity search level default is 0 ### 0: NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED - default ### 1: NORMALIZED_QUANTITY_STORAGE_SUPPORTED ### 2: NORMALIZED_QUANTITY_SEARCH_SUPPORTED @@ -210,4 +210,4 @@ hapi: # rest_url: 'localhost:9200' # protocol: 'http' # schema_management_strategy: CREATE -# username: SomeUsername \ No newline at end of file +# username: SomeUsername From c83e324692f337f3405b18dbd69f2c1cfc0236b4 Mon Sep 17 00:00:00 2001 From: Craig McClendon Date: Thu, 23 Mar 2023 14:54:20 -0500 Subject: [PATCH 152/192] configuration option to not reload IG resources that are already loaded --- .../java/ca/uhn/fhir/jpa/starter/AppProperties.java | 11 ++++++++++- .../uhn/fhir/jpa/starter/common/StarterJpaConfig.java | 1 + src/main/resources/application.yaml | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) 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 fa0dac29858..271ab636cdc 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -71,6 +71,7 @@ public class AppProperties { private Cors cors = null; private Partitioning partitioning = null; private Boolean install_transitive_ig_dependencies = true; + private Boolean reload_existing_implementationguides = false; private Map implementationGuides = null; private String staticLocation = null; @@ -541,10 +542,18 @@ public void setNormalized_quantity_search_level(NormalizedQuantitySearchLevel no public boolean getInstall_transitive_ig_dependencies() { return install_transitive_ig_dependencies; } - + public void setInstall_transitive_ig_dependencies(boolean install_transitive_ig_dependencies) { this.install_transitive_ig_dependencies = install_transitive_ig_dependencies; } + + public boolean getReload_existing_implementationguides() { + return reload_existing_implementationguides; + } + + public void setReload_existing_implementationguides(boolean reload_existing_implementationguides) { + this.reload_existing_implementationguides = reload_existing_implementationguides; + } public Integer getBundle_batch_pool_size() { return this.bundle_batch_pool_size; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 3c8abd07123..47dce924682 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -198,6 +198,7 @@ public IPackageInstallerSvc packageInstaller(AppProperties appProperties, JobDef Map guides = appProperties.getImplementationGuides(); for (Map.Entry guide : guides.entrySet()) { PackageInstallationSpec packageInstallationSpec = new PackageInstallationSpec().setPackageUrl(guide.getValue().getUrl()).setName(guide.getValue().getName()).setVersion(guide.getValue().getVersion()).setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL); + packageInstallationSpec.setReloadExisting(appProperties.getReload_existing_implementationguides()); if (appProperties.getInstall_transitive_ig_dependencies()) { packageInstallationSpec.setFetchDependencies(true); packageInstallationSpec.setDependencyExcludes(ImmutableList.of("hl7.fhir.r2.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core", "hl7.fhir.r5.core")); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index f104fbcf293..13d85fd978a 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -71,6 +71,8 @@ hapi: # server_address: http://hapi.fhir.org/baseR4 # defer_indexing_for_codesystems_of_size: 101 # install_transitive_ig_dependencies: true + ### tells the server whether to attempt to load IG resources that are already present + # reload_existing_implementationGuides : false # implementationguides: ### example from registry (packages.fhir.org) # swiss: From 600f3fe692c6c55b49eb8e9cd581f1108c428c3d Mon Sep 17 00:00:00 2001 From: Bert Roos Date: Wed, 22 Feb 2023 20:05:27 +0100 Subject: [PATCH 153/192] Update docker-compose sample with small application.properties When running from Docker Hub, it is not convenient to have to copy the full application.yaml as a starting point. Based on Spring's property initialization order, it's possible to mount a small version of application.yaml in the config folder in the run directory. --- README.md | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b6a954837c8..9da490b0925 100644 --- a/README.md +++ b/README.md @@ -58,28 +58,51 @@ docker run -p 8090:8080 -e "--spring.config.location=classpath:/another.applicat ``` Here, the configuration file (*another.application.yaml*) is part of the compiled set of resources. -### Example using docker-compose.yml for docker-compose +### Example using ``docker-compose.yml`` for docker-compose -``` +```yaml version: '3.7' + services: - web: + fhir: + container_name: fhir image: "hapiproject/hapi:latest" ports: - - "8090:8080" + - "8080:8080" configs: - source: hapi - target: /data/hapi/application.yaml - volumes: - - hapi-data:/data/hapi + target: /app/config/application.yaml + depends_on: + - db + + db: + image: postgres + restart: always environment: - SPRING_CONFIG_LOCATION: 'file:///data/hapi/application.yaml' + POSTGRES_PASSWORD: admin + POSTGRES_USER: admin + POSTGRES_DB: hapi + volumes: + - ./hapi.postgress.data:/var/lib/postgresql/data + configs: hapi: - external: true -volumes: - hapi-data: - external: true + file: ./hapi.application.yaml +``` + +Provide the following content in ``./hapi.aplication.yaml``: + +```yaml +spring: + datasource: + url: 'jdbc:postgresql://db:5432/hapi' + username: admin + password: admin + driverClassName: org.postgresql.Driver + jpa: + properties: + hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect + hibernate.search.enabled: false ``` ## Running locally From 43890a4b9db8c8a5aec48de64382238c8697b18b Mon Sep 17 00:00:00 2001 From: Kevin Dougan Date: Fri, 31 Mar 2023 12:54:27 -0400 Subject: [PATCH 154/192] Removed explicit inclusion of snakeyaml and allow spring-boot-starter-actuator to pull it in as a needed dependency. --- pom.xml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index c6f9baf0e9a..bd01af26c67 100644 --- a/pom.xml +++ b/pom.xml @@ -127,6 +127,12 @@ ca.uhn.hapi.fhir hapi-fhir-server-openapi ${project.version} + + + org.yaml + snakeyaml + + @@ -169,13 +175,6 @@ thymeleaf - - - org.yaml - snakeyaml - 1.31 - - From 7e0fb80dac478dee882ecf23e9590aff557acb4d Mon Sep 17 00:00:00 2001 From: Bert Roos Date: Fri, 31 Mar 2023 12:17:33 +0200 Subject: [PATCH 155/192] Simplify using an interceptor with Docker Now it is possible to mount a folder with extra classes that are loaded by HAPI. This makes it easy to load an interceptor JAR while using the standard Docker image. The README explains how to use it. Spring by default uses the WarLauncher. Now the ENTRYPOINT uses the PropertiesLauncher, configured in such a way that it is compatible with the WarLauncher, but adding the folder /app/extra-classes to the loader.path. --- Dockerfile | 2 +- README.md | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 89ada58c6cc..263fe9c52da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,4 +46,4 @@ WORKDIR /app COPY --chown=nonroot:nonroot --from=build-distroless /app /app COPY --chown=nonroot:nonroot --from=build-hapi /tmp/hapi-fhir-jpaserver-starter/opentelemetry-javaagent.jar /app -CMD ["/app/main.war"] +ENTRYPOINT ["java", "--class-path", "/app/main.war", "-Dloader.path=main.war!/WEB-INF/classes/,main.war!/WEB-INF/,/app/extra-classes", "org.springframework.boot.loader.PropertiesLauncher", "app/main.war"] diff --git a/README.md b/README.md index 9da490b0925..dbb57406e64 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ services: depends_on: - db + db: image: postgres restart: always @@ -105,6 +106,87 @@ spring: hibernate.search.enabled: false ``` +### Example running custom interceptor using docker-compose + +This example is an extension of the above one, now adding a custom interceptor. + +```yaml +version: '3.7' + +services: + fhir: + container_name: fhir + image: "hapiproject/hapi:latest" + ports: + - "8080:8080" + configs: + - source: hapi + target: /app/config/application.yaml + - source: hapi-extra-classes + target: /app/extra-classes + depends_on: + - db + + db: + image: postgres + restart: always + environment: + POSTGRES_PASSWORD: admin + POSTGRES_USER: admin + POSTGRES_DB: hapi + volumes: + - ./hapi.postgress.data:/var/lib/postgresql/data + +configs: + hapi: + file: ./hapi.application.yaml + hapi-extra-classes: + file: ./hapi-extra-classes +``` + +Provide the following content in ``./hapi.aplication.yaml``: + +```yaml +spring: + datasource: + url: 'jdbc:postgresql://db:5432/hapi' + username: admin + password: admin + driverClassName: org.postgresql.Driver + jpa: + properties: + hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect + hibernate.search.enabled: false +hapi: + fhir: + custom-bean-packages: the.package.containing.your.interceptor + custom-interceptor-classes: the.package.containing.your.interceptor.YourInterceptor +``` + +The basic interceptor structure would be like this: + +```java +package the.package.containing.your.interceptor; + +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.springframework.stereotype.Component; + +import ca.uhn.fhir.interceptor.api.Hook; +import ca.uhn.fhir.interceptor.api.Interceptor; +import ca.uhn.fhir.interceptor.api.Pointcut; + +@Component +@Interceptor +public class YourInterceptor +{ + @Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED) + public void resourceCreated(IBaseResource newResource) + { + System.out.println("YourInterceptor.resourceCreated"); + } +} +``` + ## Running locally The easiest way to run this server entirely depends on your environment requirements. At least, the following 4 ways are supported: From c73c5808239f9fcd26fa4c2f5ca6d81a53f602ff Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Mon, 27 Feb 2023 20:46:39 +0100 Subject: [PATCH 156/192] Update pom.xml Update to 6.4.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bd01af26c67..79791b71acf 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.4.0 + 6.4.1 hapi-fhir-jpaserver-starter From a1bdba589038aba0614c356fe16951af01abff00 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Fri, 3 Mar 2023 19:51:08 +0100 Subject: [PATCH 157/192] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 79791b71acf..ce24462b0cc 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.4.1 + 6.4.2 hapi-fhir-jpaserver-starter From d96c90c18f984d4b9db7502ed089ceda5e2d69af Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Thu, 30 Mar 2023 10:25:13 +0200 Subject: [PATCH 158/192] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ce24462b0cc..6a5138fc4b7 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.4.2 + 6.4.4 hapi-fhir-jpaserver-starter From 75e0e681045bc0cdc1665f8f58db792954db90f8 Mon Sep 17 00:00:00 2001 From: Kevin Dougan Date: Fri, 5 May 2023 10:49:13 -0400 Subject: [PATCH 159/192] 497 - Fix typo on property setter. --- .../ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java index a80524eba70..1607c87976a 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java @@ -156,8 +156,7 @@ public DaoConfig daoConfig(AppProperties appProperties) { } //Parallel Batch GET execution settings daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_size()); - daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_max_size()); - + daoConfig.setBundleBatchMaxPoolSize(appProperties.getBundle_batch_pool_max_size()); return daoConfig; } From e8d19311997f924c3c7adfcff2322f4f0ab0d8fe Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 9 May 2023 16:08:13 -0400 Subject: [PATCH 160/192] Create smoke-tests.yml --- .github/workflows/smoke-tests.yml | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/smoke-tests.yml diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml new file mode 100644 index 00000000000..0467b364779 --- /dev/null +++ b/.github/workflows/smoke-tests.yml @@ -0,0 +1,34 @@ +# This workflow will build the Java project with Maven and peform IntelliJ smoke tests +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Smoke Tests + +on: + push: + branches: + - '**' + paths-ignore: + - "charts/**" + pull_request: + branches: [ master ] + paths-ignore: + - "charts/**" + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Checkout project + uses: actions/checkout@v2 + - name: Set up JDK 17 + uses: actions/setup-java@v1 + with: + java-version: 17 + - name: Build with Maven + run: mvn -B package --file pom.xml verify + - name: Download and install HTTP client + run: | + curl -f -L -o ijhttp.zip "https://jb.gg/ijhttp/latest" + unzip ijhttp.zip From d47d048a4f3bb31f1fead85eb0ae851f7dbee3a4 Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 9 May 2023 16:25:55 -0400 Subject: [PATCH 161/192] Update smoke-tests.yml Don't do integration tests. Start server Run smoke tests Stop Server --- .github/workflows/smoke-tests.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index 0467b364779..f2038568f92 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -15,7 +15,7 @@ on: - "charts/**" jobs: - build: + build_and_smoke_test: runs-on: ubuntu-latest @@ -27,8 +27,17 @@ jobs: with: java-version: 17 - name: Build with Maven - run: mvn -B package --file pom.xml verify + run: mvn -B package --file pom.xml - name: Download and install HTTP client run: | curl -f -L -o ijhttp.zip "https://jb.gg/ijhttp/latest" unzip ijhttp.zip + - name: Start server with jetty + run: | + mvn jetty:run & export JPA_PROCESS=$! + sleep 20 + - name: Execute smoke tests + run: ./ijhttp/ijhttp ./src/test/smoketest/plain_server.http --env-file ./src/test/smoketest/http-client.env.json --env default + - name: Stop server + run: kill $JPA_PROCESS + From f1765a314f197a9234966ffb72c27aa93e29a886 Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 9 May 2023 16:26:31 -0400 Subject: [PATCH 162/192] Rename plain_server.rest to plain_server.http --- src/test/smoketest/{plain_server.rest => plain_server.http} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/test/smoketest/{plain_server.rest => plain_server.http} (99%) diff --git a/src/test/smoketest/plain_server.rest b/src/test/smoketest/plain_server.http similarity index 99% rename from src/test/smoketest/plain_server.rest rename to src/test/smoketest/plain_server.http index c5856ffa8f9..ff159a46a17 100644 --- a/src/test/smoketest/plain_server.rest +++ b/src/test/smoketest/plain_server.http @@ -220,4 +220,4 @@ POST http://{{host}}/fhir/Patient/{{batch_patient_id}}/$validate const resourceType = response.body.resourceType; client.assert(resourceType === "OperationOutcome", "Expected 'OperationOutcome' but received '" + resourceType + "'"); }); -%} \ No newline at end of file +%} From dbd6ff0eddf28bdc661b7f3fc499553b7279e5ba Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 9 May 2023 16:34:55 -0400 Subject: [PATCH 163/192] Update smoke-tests.yml Skip maven tests Wait longer for server --- .github/workflows/smoke-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index f2038568f92..a07e1c1a41b 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -27,7 +27,7 @@ jobs: with: java-version: 17 - name: Build with Maven - run: mvn -B package --file pom.xml + run: mvn -B package --file pom.xml -Dmaven.test.skip=true - name: Download and install HTTP client run: | curl -f -L -o ijhttp.zip "https://jb.gg/ijhttp/latest" @@ -35,7 +35,7 @@ jobs: - name: Start server with jetty run: | mvn jetty:run & export JPA_PROCESS=$! - sleep 20 + sleep 45 - name: Execute smoke tests run: ./ijhttp/ijhttp ./src/test/smoketest/plain_server.http --env-file ./src/test/smoketest/http-client.env.json --env default - name: Stop server From ec64299976a9d1b3bc9c03ed88d68ce945f56bf1 Mon Sep 17 00:00:00 2001 From: dotasek Date: Tue, 9 May 2023 16:41:42 -0400 Subject: [PATCH 164/192] Update smoke-tests.yml Wait longer just in case Maybe don't kill the jetty server? --- .github/workflows/smoke-tests.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index a07e1c1a41b..c0f90c30a34 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -35,9 +35,8 @@ jobs: - name: Start server with jetty run: | mvn jetty:run & export JPA_PROCESS=$! - sleep 45 + sleep 60 - name: Execute smoke tests run: ./ijhttp/ijhttp ./src/test/smoketest/plain_server.http --env-file ./src/test/smoketest/http-client.env.json --env default - - name: Stop server - run: kill $JPA_PROCESS + From 3eab2fcf9efe7f50b2cc438d4e925d5c2fecad5a Mon Sep 17 00:00:00 2001 From: dotasek Date: Fri, 19 May 2023 16:06:11 -0400 Subject: [PATCH 165/192] Use docker for HTTP client --- .github/workflows/smoke-tests.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index c0f90c30a34..cdf58f1619d 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -28,15 +28,13 @@ jobs: java-version: 17 - name: Build with Maven run: mvn -B package --file pom.xml -Dmaven.test.skip=true - - name: Download and install HTTP client - run: | - curl -f -L -o ijhttp.zip "https://jb.gg/ijhttp/latest" - unzip ijhttp.zip + - name: Docker Pull HTTP client + run: docker pull jetbrains/intellij-http-client - name: Start server with jetty run: | mvn jetty:run & export JPA_PROCESS=$! sleep 60 - name: Execute smoke tests - run: ./ijhttp/ijhttp ./src/test/smoketest/plain_server.http --env-file ./src/test/smoketest/http-client.env.json --env default + run: docker run --rm -i -t -v $PWD:/workdir jetbrains/intellij-http-client -D src/test/smoketest/plain_server.http --env-file src/test/smoketest/http-client.env.json --env default From 8b7c35c9dc44cc3340634386b68d5a90d1ff0b93 Mon Sep 17 00:00:00 2001 From: dotasek Date: Fri, 19 May 2023 16:13:49 -0400 Subject: [PATCH 166/192] Try fixing TTY issue --- .github/workflows/smoke-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index cdf58f1619d..71d3274092b 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -35,6 +35,6 @@ jobs: mvn jetty:run & export JPA_PROCESS=$! sleep 60 - name: Execute smoke tests - run: docker run --rm -i -t -v $PWD:/workdir jetbrains/intellij-http-client -D src/test/smoketest/plain_server.http --env-file src/test/smoketest/http-client.env.json --env default + run: docker run --rm -v $PWD:/workdir jetbrains/intellij-http-client -D src/test/smoketest/plain_server.http --env-file src/test/smoketest/http-client.env.json --env default From f54088efab6bc745f7a99ae9c1dbc166f5bf9fea Mon Sep 17 00:00:00 2001 From: dotasek Date: Fri, 19 May 2023 16:17:54 -0400 Subject: [PATCH 167/192] Sleep a little longer... --- .github/workflows/smoke-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index 71d3274092b..13778058e27 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -33,7 +33,7 @@ jobs: - name: Start server with jetty run: | mvn jetty:run & export JPA_PROCESS=$! - sleep 60 + sleep 80 - name: Execute smoke tests run: docker run --rm -v $PWD:/workdir jetbrains/intellij-http-client -D src/test/smoketest/plain_server.http --env-file src/test/smoketest/http-client.env.json --env default From 9a18b23a26214fcd5512a79967fbe95f73fcb3c6 Mon Sep 17 00:00:00 2001 From: dotasek Date: Fri, 19 May 2023 16:26:23 -0400 Subject: [PATCH 168/192] Additional param for linux localhost --- .github/workflows/smoke-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index 13778058e27..6fa35600ba5 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -35,6 +35,6 @@ jobs: mvn jetty:run & export JPA_PROCESS=$! sleep 80 - name: Execute smoke tests - run: docker run --rm -v $PWD:/workdir jetbrains/intellij-http-client -D src/test/smoketest/plain_server.http --env-file src/test/smoketest/http-client.env.json --env default + run: docker run --rm -v $PWD:/workdir --add-host host.docker.internal:host-gateway jetbrains/intellij-http-client -D src/test/smoketest/plain_server.http --env-file src/test/smoketest/http-client.env.json --env default From 8bf9dfd1cf4de7967684f0452812109a1691ac62 Mon Sep 17 00:00:00 2001 From: dotasek Date: Fri, 19 May 2023 16:31:42 -0400 Subject: [PATCH 169/192] Intentional failure --- .github/workflows/smoke-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index 6fa35600ba5..3281b72e135 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -33,7 +33,7 @@ jobs: - name: Start server with jetty run: | mvn jetty:run & export JPA_PROCESS=$! - sleep 80 + sleep 10 - name: Execute smoke tests run: docker run --rm -v $PWD:/workdir --add-host host.docker.internal:host-gateway jetbrains/intellij-http-client -D src/test/smoketest/plain_server.http --env-file src/test/smoketest/http-client.env.json --env default From a2cf95ae5e4fe43951aeed3307b008b9cf13be8f Mon Sep 17 00:00:00 2001 From: dotasek Date: Fri, 19 May 2023 16:35:48 -0400 Subject: [PATCH 170/192] Restore reasonable sleep time --- .github/workflows/smoke-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index 3281b72e135..6fa35600ba5 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -33,7 +33,7 @@ jobs: - name: Start server with jetty run: | mvn jetty:run & export JPA_PROCESS=$! - sleep 10 + sleep 80 - name: Execute smoke tests run: docker run --rm -v $PWD:/workdir --add-host host.docker.internal:host-gateway jetbrains/intellij-http-client -D src/test/smoketest/plain_server.http --env-file src/test/smoketest/http-client.env.json --env default From 53a958ac664231c4d17b25fcb2337ffdc1236cde Mon Sep 17 00:00:00 2001 From: dotasek Date: Mon, 29 May 2023 14:33:45 -0400 Subject: [PATCH 171/192] Bump HAPI to release 6.6.0 (#539) * Start tracking 6.5 * Use JpaStorageSettings and StorageSettings * Bump parent pom version + add deps for jaxb * Bump HAPI * Fix Subscription/Topic resource creation * fix subscription topic beans * Change to rel_6_6 hapi-fhir SNAPSHOT * Fix emailSender config * Split method calls by line. * Merge pull request #524 from hapifhir/do-20230509-smoke-test-ci Create smoke-tests.yml * Bump core to release 6.6.0 --------- Co-authored-by: Michael Buckley Co-authored-by: Kevin Dougan SmileCDR <72025369+KevinDougan-SmileCDR@users.noreply.github.com> Co-authored-by: Ken Stevens Co-authored-by: Mark Iantorno --- pom.xml | 14 +- .../uhn/fhir/jpa/starter/AppProperties.java | 2 +- .../common/FhirServerConfigCommon.java | 130 +++++++++--------- .../starter/common/FhirServerConfigR4B.java | 2 + .../starter/common/FhirServerConfigR5.java | 2 + .../jpa/starter/common/StarterJpaConfig.java | 20 +-- .../fhir/jpa/starter/ExampleServerR5IT.java | 60 ++++++-- 7 files changed, 138 insertions(+), 92 deletions(-) diff --git a/pom.xml b/pom.xml index 6a5138fc4b7..1fc9a25f8ad 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.4.4 + 6.6.0 hapi-fhir-jpaserver-starter @@ -62,7 +62,17 @@ com.microsoft.sqlserver mssql-jdbc - + + jakarta.xml.bind + jakarta.xml.bind-api + 2.3.3 + + + com.sun.xml.bind + jaxb-ri + 2.3.5 + pom + org.simplejavamail 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 271ab636cdc..b48d4e1550f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -2,7 +2,7 @@ import ca.uhn.fhir.context.FhirVersionEnum; -import ca.uhn.fhir.jpa.api.config.DaoConfig.ClientIdStrategyEnum; +import ca.uhn.fhir.jpa.api.config.JpaStorageSettings.ClientIdStrategyEnum; import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel; import ca.uhn.fhir.rest.api.EncodingEnum; import com.google.common.collect.ImmutableList; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java index 1607c87976a..9751ba70f8d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java @@ -1,12 +1,12 @@ package ca.uhn.fhir.jpa.starter.common; -import ca.uhn.fhir.jpa.api.config.DaoConfig; +import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; import ca.uhn.fhir.jpa.binary.api.IBinaryStorageSvc; import ca.uhn.fhir.jpa.binstore.DatabaseBlobBinaryStorageSvcImpl; import ca.uhn.fhir.jpa.config.HibernatePropertiesProvider; import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings.CrossPartitionReferenceMode; -import ca.uhn.fhir.jpa.model.entity.ModelConfig; +import ca.uhn.fhir.jpa.model.entity.StorageSettings; import ca.uhn.fhir.jpa.starter.AppProperties; import ca.uhn.fhir.jpa.starter.util.JpaHibernatePropertiesProvider; import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory; @@ -17,7 +17,7 @@ import ca.uhn.fhir.rest.server.mail.MailSvc; import com.google.common.base.Strings; import org.hl7.fhir.r4.model.Bundle.BundleType; -import org.hl7.fhir.dstu2.model.Subscription; + import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -81,84 +81,85 @@ public FhirServerConfigCommon(AppProperties appProperties) { * Configure FHIR properties around the the JPA server via this bean */ @Bean - public DaoConfig daoConfig(AppProperties appProperties) { - DaoConfig daoConfig = new DaoConfig(); - - daoConfig.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? DaoConfig.IndexEnabledEnum.ENABLED : DaoConfig.IndexEnabledEnum.DISABLED); - daoConfig.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets()); - daoConfig.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write()); - daoConfig.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete()); - daoConfig.setAllowContainsSearches(appProperties.getAllow_contains_searches()); - daoConfig.setAllowMultipleDelete(appProperties.getAllow_multiple_delete()); - daoConfig.setAllowExternalReferences(appProperties.getAllow_external_references()); - daoConfig.setSchedulingDisabled(!appProperties.getDao_scheduling_enabled()); - daoConfig.setDeleteExpungeEnabled(appProperties.getDelete_expunge_enabled()); - daoConfig.setExpungeEnabled(appProperties.getExpunge_enabled()); + public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) { + JpaStorageSettings jpaStorageSettings = new JpaStorageSettings(); + + jpaStorageSettings.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? JpaStorageSettings.IndexEnabledEnum.ENABLED : JpaStorageSettings.IndexEnabledEnum.DISABLED); + jpaStorageSettings.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets()); + jpaStorageSettings.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write()); + jpaStorageSettings.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete()); + jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches()); + jpaStorageSettings.setAllowMultipleDelete(appProperties.getAllow_multiple_delete()); + jpaStorageSettings.setAllowExternalReferences(appProperties.getAllow_external_references()); + jpaStorageSettings.setSchedulingDisabled(!appProperties.getDao_scheduling_enabled()); + jpaStorageSettings.setDeleteExpungeEnabled(appProperties.getDelete_expunge_enabled()); + jpaStorageSettings.setExpungeEnabled(appProperties.getExpunge_enabled()); if(appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) - daoConfig.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom()); + jpaStorageSettings.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom()); Integer maxFetchSize = appProperties.getMax_page_size(); - daoConfig.setFetchSizeDefaultMaximum(maxFetchSize); + jpaStorageSettings.setFetchSizeDefaultMaximum(maxFetchSize); ourLog.info("Server configured to have a maximum fetch size of " + (maxFetchSize == Integer.MAX_VALUE ? "'unlimited'" : maxFetchSize)); Long reuseCachedSearchResultsMillis = appProperties.getReuse_cached_search_results_millis(); - daoConfig.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis); + jpaStorageSettings.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis); ourLog.info("Server configured to cache search results for {} milliseconds", reuseCachedSearchResultsMillis); Long retainCachedSearchesMinutes = appProperties.getRetain_cached_searches_mins(); - daoConfig.setExpireSearchResultsAfterMillis(retainCachedSearchesMinutes * 60 * 1000); + jpaStorageSettings.setExpireSearchResultsAfterMillis(retainCachedSearchesMinutes * 60 * 1000); if(appProperties.getSubscription() != null) { // Subscriptions are enabled by channel type if (appProperties.getSubscription().getResthook_enabled()) { ourLog.info("Enabling REST-hook subscriptions"); - daoConfig.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK); + jpaStorageSettings.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK); } if (appProperties.getSubscription().getEmail() != null) { ourLog.info("Enabling email subscriptions"); - daoConfig.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL); + jpaStorageSettings.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL); } if (appProperties.getSubscription().getWebsocket_enabled()) { ourLog.info("Enabling websocket subscriptions"); - daoConfig.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET); + jpaStorageSettings.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET); } } - daoConfig.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); - daoConfig.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing()); - daoConfig.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls())); + jpaStorageSettings.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); + jpaStorageSettings.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing()); + jpaStorageSettings.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls())); if (appProperties.getLastn_enabled()) { - daoConfig.setLastNEnabled(true); + jpaStorageSettings.setLastNEnabled(true); } if(appProperties.getInline_resource_storage_below_size() != 0){ - daoConfig.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size()); + jpaStorageSettings.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size()); } - daoConfig.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled()); - daoConfig.getModelConfig().setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); - daoConfig.getModelConfig().setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); + jpaStorageSettings.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled()); + jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); + jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); if (appProperties.getAllowed_bundle_types() != null) { - daoConfig.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream().map(BundleType::toCode).collect(Collectors.toSet())); + jpaStorageSettings.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream().map(BundleType::toCode).collect(Collectors.toSet())); } - daoConfig.setDeferIndexingForCodesystemsOfSize(appProperties.getDefer_indexing_for_codesystems_of_size()); + jpaStorageSettings.setDeferIndexingForCodesystemsOfSize(appProperties.getDefer_indexing_for_codesystems_of_size()); - if (appProperties.getClient_id_strategy() == DaoConfig.ClientIdStrategyEnum.ANY) { - daoConfig.setResourceServerIdStrategy(DaoConfig.IdStrategyEnum.UUID); - daoConfig.setResourceClientIdStrategy(appProperties.getClient_id_strategy()); + if (appProperties.getClient_id_strategy() == JpaStorageSettings.ClientIdStrategyEnum.ANY) { + jpaStorageSettings.setResourceServerIdStrategy(JpaStorageSettings.IdStrategyEnum.UUID); + jpaStorageSettings.setResourceClientIdStrategy(appProperties.getClient_id_strategy()); } //Parallel Batch GET execution settings - daoConfig.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_size()); - daoConfig.setBundleBatchMaxPoolSize(appProperties.getBundle_batch_pool_max_size()); + jpaStorageSettings.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_size()); + jpaStorageSettings.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_max_size()); - return daoConfig; + storageSettings(appProperties, jpaStorageSettings); + return jpaStorageSettings; } @Bean @@ -191,20 +192,19 @@ public HibernatePropertiesProvider jpaStarterDialectProvider(LocalContainerEntit return new JpaHibernatePropertiesProvider(myEntityManagerFactory); } - @Bean - public ModelConfig modelConfig(AppProperties appProperties, DaoConfig daoConfig) { - ModelConfig modelConfig = daoConfig.getModelConfig(); - modelConfig.setAllowContainsSearches(appProperties.getAllow_contains_searches()); - modelConfig.setAllowExternalReferences(appProperties.getAllow_external_references()); - modelConfig.setDefaultSearchParamsCanBeOverridden(appProperties.getAllow_override_default_search_params()); + + protected StorageSettings storageSettings(AppProperties appProperties, JpaStorageSettings jpaStorageSettings) { + jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches()); + jpaStorageSettings.setAllowExternalReferences(appProperties.getAllow_external_references()); + jpaStorageSettings.setDefaultSearchParamsCanBeOverridden(appProperties.getAllow_override_default_search_params()); if(appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) - modelConfig.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom()); + jpaStorageSettings.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom()); - modelConfig.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); + jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); - modelConfig.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); - modelConfig.setIndexIdentifierOfType(appProperties.getEnable_index_of_type()); - return modelConfig; + jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); + jpaStorageSettings.setIndexIdentifierOfType(appProperties.getEnable_index_of_type()); + return jpaStorageSettings; } @Lazy @@ -220,25 +220,23 @@ public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) { } @Bean - public IEmailSender emailSender(AppProperties appProperties, Optional subscriptionDeliveryHandlerFactory) { - if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) { - MailConfig mailConfig = new MailConfig(); + public IEmailSender emailSender(AppProperties appProperties) { + if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) { + MailConfig mailConfig = new MailConfig(); - AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail(); - mailConfig.setSmtpHostname(email.getHost()); - mailConfig.setSmtpPort(email.getPort()); - mailConfig.setSmtpUsername(email.getUsername()); - mailConfig.setSmtpPassword(email.getPassword()); - mailConfig.setSmtpUseStartTLS(email.getStartTlsEnable()); + AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail(); + mailConfig.setSmtpHostname(email.getHost()); + mailConfig.setSmtpPort(email.getPort()); + mailConfig.setSmtpUsername(email.getUsername()); + mailConfig.setSmtpPassword(email.getPassword()); + mailConfig.setSmtpUseStartTLS(email.getStartTlsEnable()); - IMailSvc mailSvc = new MailSvc(mailConfig); - IEmailSender emailSender = new EmailSenderImpl(mailSvc); + IMailSvc mailSvc = new MailSvc(mailConfig); + IEmailSender emailSender = new EmailSenderImpl(mailSvc); - subscriptionDeliveryHandlerFactory.ifPresent(theSubscriptionDeliveryHandlerFactory -> theSubscriptionDeliveryHandlerFactory.setEmailSender(emailSender)); - - return emailSender; - } + return emailSender; + } - return null; + return null; } } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java index d99d1021058..4272017b022 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java @@ -2,6 +2,7 @@ import ca.uhn.fhir.jpa.config.r4b.JpaR4BConfig; import ca.uhn.fhir.jpa.starter.annotations.OnR4BCondition; +import ca.uhn.fhir.jpa.topic.SubscriptionTopicConfig; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -10,6 +11,7 @@ @Conditional(OnR4BCondition.class) @Import({ JpaR4BConfig.class, + SubscriptionTopicConfig.class, StarterJpaConfig.class, ElasticsearchConfig.class }) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java index 1552aef7aee..5e2e4305b5d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java @@ -2,6 +2,7 @@ import ca.uhn.fhir.jpa.config.r5.JpaR5Config; import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition; +import ca.uhn.fhir.jpa.topic.SubscriptionTopicConfig; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -11,6 +12,7 @@ @Import({ StarterJpaConfig.class, JpaR5Config.class, + SubscriptionTopicConfig.class, ElasticsearchConfig.class }) public class FhirServerConfigR5 { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 47dce924682..a7ac187192e 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -11,7 +11,7 @@ import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.jpa.api.IDaoRegistry; -import ca.uhn.fhir.jpa.api.config.DaoConfig; +import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; import ca.uhn.fhir.jpa.api.config.ThreadPoolFactoryConfig; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; @@ -241,7 +241,7 @@ public CorsInterceptor corsInterceptor(AppProperties appProperties) { } @Bean - public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext, Optional theIpsOperationProvider) { + public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, JpaStorageSettings jpaStorageSettings, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext, Optional theIpsOperationProvider) { RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext()); List supportedResourceTypes = appProperties.getSupported_resource_types(); @@ -263,7 +263,7 @@ public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProper fhirServer.registerProviders(resourceProviderFactory.createProviders()); fhirServer.registerProvider(jpaSystemProvider); - fhirServer.setServerConformanceProvider(calculateConformanceProvider(fhirSystemDao, fhirServer, daoConfig, searchParamRegistry, theValidationSupport)); + fhirServer.setServerConformanceProvider(calculateConformanceProvider(fhirSystemDao, fhirServer, jpaStorageSettings, searchParamRegistry, theValidationSupport)); /* * ETag Support @@ -339,7 +339,7 @@ public RestfulServer restfulServer(IFhirSystemDao fhirSystemDao, AppProper corsInterceptor.ifPresent(fhirServer::registerInterceptor); - if (daoConfig.getSupportedSubscriptionTypes().size() > 0) { + if (jpaStorageSettings.getSupportedSubscriptionTypes().size() > 0) { // Subscription debug logging fhirServer.registerInterceptor(new SubscriptionDebugLogInterceptor()); } @@ -458,30 +458,30 @@ private void registerCustomInterceptors(RestfulServer fhirServer, ApplicationCon } } - public static IServerConformanceProvider calculateConformanceProvider(IFhirSystemDao fhirSystemDao, RestfulServer fhirServer, DaoConfig daoConfig, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport) { + public static IServerConformanceProvider calculateConformanceProvider(IFhirSystemDao fhirSystemDao, RestfulServer fhirServer, JpaStorageSettings jpaStorageSettings, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport) { FhirVersionEnum fhirVersion = fhirSystemDao.getContext().getVersion().getVersion(); if (fhirVersion == FhirVersionEnum.DSTU2) { - JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(fhirServer, fhirSystemDao, daoConfig); + JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(fhirServer, fhirSystemDao, jpaStorageSettings); confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server"); return confProvider; } else if (fhirVersion == FhirVersionEnum.DSTU3) { - JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(fhirServer, fhirSystemDao, daoConfig, searchParamRegistry); + JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry); confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server"); return confProvider; } else if (fhirVersion == FhirVersionEnum.R4) { - JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, daoConfig, searchParamRegistry, theValidationSupport); + JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry, theValidationSupport); confProvider.setImplementationDescription("HAPI FHIR R4 Server"); return confProvider; } else if (fhirVersion == FhirVersionEnum.R4B) { - JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, daoConfig, searchParamRegistry, theValidationSupport); + JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry, theValidationSupport); confProvider.setImplementationDescription("HAPI FHIR R4B Server"); return confProvider; } else if (fhirVersion == FhirVersionEnum.R5) { - JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, daoConfig, searchParamRegistry, theValidationSupport); + JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry, theValidationSupport); confProvider.setImplementationDescription("HAPI FHIR R5 Server"); return confProvider; } else { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index 87e012197f9..8ecfb737462 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -37,7 +37,7 @@ "spring.datasource.url=jdbc:h2:mem:dbr5", "hapi.fhir.fhir_version=r5", "hapi.fhir.subscription.websocket_enabled=true", - "hapi.fhir.subscription.websocket_enabled=true", + "hapi.fhir.subscription.websocket_enabled=true" }) public class ExampleServerR5IT { @@ -45,7 +45,10 @@ public class ExampleServerR5IT { private IGenericClient ourClient; private FhirContext ourCtx; - @LocalServerPort + public static final String SUBSCRIPTION_TOPIC_TEST_URL = "http://example.com/topic/test"; + + + @LocalServerPort private int port; @@ -64,32 +67,62 @@ public void testCreateAndRead() { @Test public void testWebsocketSubscription() throws Exception { - + String endpoint = "ws://localhost:" + port + "/websocket"; /* - * Create topic (will be contained in subscription) + * Create topic */ SubscriptionTopic topic = new SubscriptionTopic(); - topic.setId("#1"); - topic.getResourceTriggerFirstRep().getQueryCriteria().setCurrent("Observation?status=final"); - /* + topic.setUrl(SUBSCRIPTION_TOPIC_TEST_URL); + topic.setStatus(Enumerations.PublicationStatus.ACTIVE); + SubscriptionTopic.SubscriptionTopicResourceTriggerComponent trigger = topic.addResourceTrigger(); + trigger.setResource("Observation"); + trigger.addSupportedInteraction(SubscriptionTopic.InteractionTrigger.CREATE); + trigger.addSupportedInteraction(SubscriptionTopic.InteractionTrigger.UPDATE); + + ourClient.create().resource(topic).execute(); + + waitForSize(1, () -> ourClient + .search() + .forResource(SubscriptionTopic.class) + .where(Subscription.STATUS.exactly().code("active")) + .cacheControl( + new CacheControlDirective() + .setNoCache(true)) + .returnBundle(Bundle.class) + .execute() + .getEntry() + .size()); + + /* * Create subscription */ Subscription subscription = new Subscription(); - subscription.getContained().add(topic); - subscription.setTopic("#1"); + + subscription.setTopic(SUBSCRIPTION_TOPIC_TEST_URL); subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)"); subscription.setStatus(Enumerations.SubscriptionStatusCodes.REQUESTED); subscription.getChannelType() .setSystem("http://terminology.hl7.org/CodeSystem/subscription-channel-type") .setCode("websocket"); - subscription.setContentType("application/json"); + subscription.setContentType("application/fhir+json"); + subscription.setEndpoint(endpoint); MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute(); IIdType mySubscriptionId = methodOutcome.getId(); // Wait for the subscription to be activated - waitForSize(1, () -> ourClient.search().forResource(Subscription.class).where(Subscription.STATUS.exactly().code("active")).cacheControl(new CacheControlDirective().setNoCache(true)).returnBundle(Bundle.class).execute().getEntry().size()); + waitForSize(1, () -> ourClient + .search() + .forResource(Subscription.class) + .where(Subscription.STATUS.exactly().code("active")) + .cacheControl( + new CacheControlDirective() + .setNoCache(true)) + .returnBundle(Bundle.class) + .execute() + .getEntry() + .size()); /* * Attach websocket @@ -99,8 +132,9 @@ public void testWebsocketSubscription() throws Exception { SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); myWebSocketClient.start(); - URI echoUri = new URI("ws://localhost:" + port + "/websocket"); - ClientUpgradeRequest request = new ClientUpgradeRequest(); + + URI echoUri = new URI(endpoint); + ClientUpgradeRequest request = new ClientUpgradeRequest(); ourLog.info("Connecting to : {}", echoUri); Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); Session session = connection.get(2, TimeUnit.SECONDS); From 9e9c08bafe5c3533e5e2b149fae141be402c32ba Mon Sep 17 00:00:00 2001 From: Chalma Maadaadi Date: Tue, 30 May 2023 15:28:55 -0400 Subject: [PATCH 172/192] Add fix to enable the CR module. --- .../java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java | 4 ++++ src/main/resources/application.yaml | 1 + 2 files changed, 5 insertions(+) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 47dce924682..34863759518 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -9,6 +9,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.cr.config.CrProviderLoader; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.jpa.api.IDaoRegistry; import ca.uhn.fhir.jpa.api.config.DaoConfig; @@ -114,6 +115,9 @@ public CachingValidationSupport validationSupportChain(JpaValidationSupportChain @Autowired private ConfigurableEnvironment configurableEnvironment; + @Autowired(required=false) + private CrProviderLoader crProviderLoader; + /** * Customize the default/max page sizes for search results. You can set these however * you want, although very large page sizes will require a lot of RAM. diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 13d85fd978a..0a8bb47c88f 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -58,6 +58,7 @@ hapi: openapi_enabled: true ### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5 fhir_version: R4 + cr_enabled: "${CR_ENABLED: false}" ### enable to use the ApacheProxyAddressStrategy which uses X-Forwarded-* headers ### to determine the FHIR server address # use_apache_address_strategy: false From 2899060de07868e07693143d40a5592893896ce3 Mon Sep 17 00:00:00 2001 From: Chalma Maadaadi Date: Tue, 30 May 2023 19:20:19 -0400 Subject: [PATCH 173/192] Addressed comment to for cr_enabled flag. --- src/main/resources/application.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 0a8bb47c88f..9b1e11872a5 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -58,6 +58,8 @@ hapi: openapi_enabled: true ### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5 fhir_version: R4 + ### This flag when enabled to true, will avail evaluate measure operations from CR Module. + ### Flag is false by default, can be passed as command line argument to override. cr_enabled: "${CR_ENABLED: false}" ### enable to use the ApacheProxyAddressStrategy which uses X-Forwarded-* headers ### to determine the FHIR server address From afaec85653197db5516f8495eff71a46314e24cf Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Fri, 9 Jun 2023 11:39:54 +0200 Subject: [PATCH 174/192] Addressing https://github.com/hapifhir/hapi-fhir-jpaserver-starter/issues/486 and https://github.com/hapifhir/hapi-fhir-jpaserver-starter/issues/485 --- .../uhn/fhir/jpa/starter/AppProperties.java | 13 +++++++- .../starter/ExtraStaticFilesConfigurer.java | 31 +++++++++++++------ src/main/resources/application.yaml | 3 +- 3 files changed, 35 insertions(+), 12 deletions(-) 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 b48d4e1550f..ecd880eb3f4 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -76,6 +76,8 @@ public class AppProperties { private String staticLocation = null; + private String staticLocationPrefix = "/static"; + private Boolean lastn_enabled = false; private boolean store_resource_in_lucene_index_enabled = false; private NormalizedQuantitySearchLevel normalized_quantity_search_level = NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED; @@ -89,7 +91,16 @@ public class AppProperties { private final List custom_interceptor_classes = new ArrayList<>(); - public List getCustomInterceptorClasses() { + public String getStaticLocationPrefix() { + return staticLocationPrefix; + } + + public void setStaticLocationPrefix(String staticLocationPrefix) { + this.staticLocationPrefix = staticLocationPrefix; + } + + + public List getCustomInterceptorClasses() { return custom_interceptor_classes; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java b/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java index d875ec6a5d6..a3b528c0bda 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java @@ -1,6 +1,5 @@ package ca.uhn.fhir.jpa.starter; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; @@ -14,25 +13,37 @@ @ConditionalOnProperty(prefix = "hapi.fhir", name = "staticLocation") public class ExtraStaticFilesConfigurer implements WebMvcConfigurer { - public static final String ROOT_CONTEXT_PATH = "/static"; - @Autowired - AppProperties appProperties; + private String staticLocation; + private String rootContextPath; - @Override + public ExtraStaticFilesConfigurer(AppProperties appProperties) { + + rootContextPath = appProperties.getStaticLocationPrefix(); + if(rootContextPath.endsWith("/")) + rootContextPath = rootContextPath.substring(0, rootContextPath.lastIndexOf('/')); + + staticLocation = appProperties.getStaticLocation(); + if(staticLocation.endsWith("/")) + staticLocation = staticLocation.substring(0, staticLocation.lastIndexOf('/')); + + } + + + @Override public void addResourceHandlers(ResourceHandlerRegistry theRegistry) { - theRegistry.addResourceHandler(ROOT_CONTEXT_PATH + "/**").addResourceLocations(appProperties.getStaticLocation()); + theRegistry.addResourceHandler(rootContextPath + "/**").addResourceLocations(staticLocation); } @Override public void addViewControllers(ViewControllerRegistry registry) { - String path = URI.create(appProperties.getStaticLocation()).getPath(); + String path = URI.create(staticLocation).getPath(); String lastSegment = path.substring(path.lastIndexOf('/') + 1); - registry.addViewController(ROOT_CONTEXT_PATH).setViewName("redirect:" + ROOT_CONTEXT_PATH + "/" + lastSegment + "/index.html"); + registry.addViewController(rootContextPath).setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html"); - registry.addViewController(ROOT_CONTEXT_PATH + "/*").setViewName("redirect:" + ROOT_CONTEXT_PATH + "/" + lastSegment + "/index.html"); + registry.addViewController(rootContextPath + "/*").setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html"); - registry.addViewController(ROOT_CONTEXT_PATH + "/" + lastSegment + "/").setViewName("redirect:" + ROOT_CONTEXT_PATH + "/" + lastSegment + "/index.html"); + registry.addViewController(rootContextPath + "/" + lastSegment + "/").setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html"); registry.setOrder(Ordered.HIGHEST_PRECEDENCE); } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 13d85fd978a..c90f37ead04 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -64,7 +64,8 @@ hapi: ### forces the use of the https:// protocol for the returned server address. ### alternatively, it may be set using the X-Forwarded-Proto header. # use_apache_address_strategy_https: false - ### enables the server to host content like HTML, css, etc. under the url pattern of /static/** + ### enables the server to host content like HTML, css, etc. under the url pattern of eg. /static/** + # staticLocationPrefix: /static ### the deepest folder level will be used. E.g. - if you put file:/foo/bar/bazz as value then the files are resolved under /static/bazz/** #staticLocation: file:/foo/bar/bazz ### enable to set the Server URL From 776afdee5606c19458bebd47baf27bd471055842 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Sun, 25 Jun 2023 23:55:48 +0200 Subject: [PATCH 175/192] no message --- .../jpa/starter/common/FhirTesterConfig.java | 2 ++ .../common/FhirTesterConfigCondition.java | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfigCondition.java diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java index cb28659d52c..863e2695ffc 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java @@ -4,6 +4,7 @@ import ca.uhn.fhir.to.FhirTesterMvcConfig; import ca.uhn.fhir.to.TesterConfig; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -18,6 +19,7 @@ */ @Configuration @Import(FhirTesterMvcConfig.class) +@Conditional(FhirTesterConfigCondition.class) public class FhirTesterConfig { /** diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfigCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfigCondition.java new file mode 100644 index 00000000000..f5670d9c528 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfigCondition.java @@ -0,0 +1,16 @@ +package ca.uhn.fhir.jpa.starter.common; + +import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class FhirTesterConfigCondition implements Condition { + @Override + public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) { + + var properties = EnvironmentHelper.getPropertiesStartingWith((ConfigurableEnvironment) conditionContext.getEnvironment(), "hapi.fhir.tester"); + return !properties.isEmpty(); + } +} From fdcd021e6614bd995dc8a70e31bd9edc1d4857e9 Mon Sep 17 00:00:00 2001 From: chgl Date: Sun, 25 Jun 2023 23:59:09 +0200 Subject: [PATCH 176/192] Updated helm chart and dockerfile dependencies (#540) * Updated Helm chart to use hapi fhir image v6.6.0 * Updated maven base image due to openjdk deprecation * Removed superfluous app/main.war in entrypoint * Update curlimages/curl to 8.1.2 --- .github/ct/config.yaml | 2 -- .github/workflows/chart-release.yaml | 13 +++++----- .github/workflows/chart-test.yaml | 26 ++++++++++--------- Dockerfile | 6 ++--- charts/hapi-fhir-jpaserver/Chart.lock | 8 +++--- charts/hapi-fhir-jpaserver/Chart.yaml | 14 +++++----- charts/hapi-fhir-jpaserver/README.md | 13 ++++++---- charts/hapi-fhir-jpaserver/README.md.gotmpl | 5 ++-- .../templates/deployment.yaml | 2 +- .../templates/tests/test-endpoints.yaml | 6 ++--- charts/hapi-fhir-jpaserver/values.yaml | 2 +- 11 files changed, 51 insertions(+), 46 deletions(-) diff --git a/.github/ct/config.yaml b/.github/ct/config.yaml index 484e994cd51..9d1ae820466 100644 --- a/.github/ct/config.yaml +++ b/.github/ct/config.yaml @@ -11,6 +11,4 @@ helm-extra-args: --timeout 300s upgrade: true skip-missing-values: true release-label: release -chart-repos: - - bitnami=https://charts.bitnami.com/bitnami release-name-template: "helm-v{{ .Version }}" diff --git a/.github/workflows/chart-release.yaml b/.github/workflows/chart-release.yaml index ae2045ceb05..38c4fd2f56e 100644 --- a/.github/workflows/chart-release.yaml +++ b/.github/workflows/chart-release.yaml @@ -9,10 +9,14 @@ on: jobs: release: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: + - name: Add workspace as safe directory + run: | + git config --global --add safe.directory /__w/hapi-fhir-jpaserver-starter/hapi-fhir-jpaserver-starter + - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 with: fetch-depth: 0 @@ -21,14 +25,11 @@ jobs: git config user.name "$GITHUB_ACTOR" git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - - name: Add bitnami repo - run: helm repo add bitnami https://charts.bitnami.com/bitnami - - name: Update dependencies run: find charts/ ! -path charts/ -maxdepth 1 -type d -exec helm dependency update {} \; - name: Run chart-releaser - uses: helm/chart-releaser-action@v1.2.0 + uses: helm/chart-releaser-action@be16258da8010256c6e82849661221415f031968 # v1.5.0 with: config: .github/ct/config.yaml env: diff --git a/.github/workflows/chart-test.yaml b/.github/workflows/chart-test.yaml index f4357fb35cc..30d29329dd7 100644 --- a/.github/workflows/chart-test.yaml +++ b/.github/workflows/chart-test.yaml @@ -9,8 +9,8 @@ on: jobs: lint: - runs-on: ubuntu-20.04 - container: quay.io/helmpack/chart-testing:v3.4.0 + runs-on: ubuntu-22.04 + container: quay.io/helmpack/chart-testing:v3.8.0@sha256:f058c660a28d99a9394ae081d98921efe068079531f247c86b8054e3c9d407aa steps: - name: Install helm-docs working-directory: /tmp @@ -22,11 +22,14 @@ jobs: chmod +x /usr/local/bin/helm-docs && \ helm-docs --version + - name: Add workspace as safe directory + run: | + git config --global --add safe.directory /__w/hapi-fhir-jpaserver-starter/hapi-fhir-jpaserver-starter + - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 with: fetch-depth: 0 - - name: Check if documentation is up-to-date run: helm-docs && git diff --exit-code HEAD @@ -34,20 +37,20 @@ jobs: run: ct lint --config .github/ct/config.yaml test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: matrix: - k8s-version: [1.22.9, 1.23.6, 1.24.1] + k8s-version: [1.25.9, 1.26.4, 1.27.2] needs: - lint steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 with: fetch-depth: 0 - name: Set up chart-testing - uses: helm/chart-testing-action@v2.2.1 + uses: helm/chart-testing-action@e8788873172cb653a90ca2e819d79d65a66d4e76 # v2.4.0 - name: Run chart-testing (list-changed) id: list-changed @@ -58,13 +61,12 @@ jobs: fi - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.2.0 - if: steps.list-changed.outputs.changed == 'true' + uses: helm/kind-action@fa81e57adff234b2908110485695db0f181f3c67 # v1.7.0 + if: ${{ steps.list-changed.outputs.changed == 'true' }} with: - version: v0.14.0 cluster_name: kind-cluster-k8s-${{ matrix.k8s-version }} node_image: kindest/node:v${{ matrix.k8s-version }} - name: Run chart-testing (install) run: ct install --config .github/ct/config.yaml - if: steps.list-changed.outputs.changed == 'true' + if: ${{ steps.list-changed.outputs.changed == 'true' }} diff --git a/Dockerfile b/Dockerfile index 263fe9c52da..7c44d37998d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ -FROM maven:3.8-openjdk-17-slim as build-hapi +FROM docker.io/library/maven:3.9.2-eclipse-temurin-17 as build-hapi WORKDIR /tmp/hapi-fhir-jpaserver-starter -ARG OPENTELEMETRY_JAVA_AGENT_VERSION=1.17.0 +ARG OPENTELEMETRY_JAVA_AGENT_VERSION=1.26.0 RUN curl -LSsO https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${OPENTELEMETRY_JAVA_AGENT_VERSION}/opentelemetry-javaagent.jar COPY pom.xml . @@ -46,4 +46,4 @@ WORKDIR /app COPY --chown=nonroot:nonroot --from=build-distroless /app /app COPY --chown=nonroot:nonroot --from=build-hapi /tmp/hapi-fhir-jpaserver-starter/opentelemetry-javaagent.jar /app -ENTRYPOINT ["java", "--class-path", "/app/main.war", "-Dloader.path=main.war!/WEB-INF/classes/,main.war!/WEB-INF/,/app/extra-classes", "org.springframework.boot.loader.PropertiesLauncher", "app/main.war"] +ENTRYPOINT ["java", "--class-path", "/app/main.war", "-Dloader.path=main.war!/WEB-INF/classes/,main.war!/WEB-INF/,/app/extra-classes", "org.springframework.boot.loader.PropertiesLauncher"] diff --git a/charts/hapi-fhir-jpaserver/Chart.lock b/charts/hapi-fhir-jpaserver/Chart.lock index 5c8ec4a2289..98ba8480d43 100644 --- a/charts/hapi-fhir-jpaserver/Chart.lock +++ b/charts/hapi-fhir-jpaserver/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: postgresql - repository: https://charts.bitnami.com/bitnami - version: 12.1.2 -digest: sha256:525689611a29f90b0bc8cd674df5d97024c99eda8104216390f6747904fd0208 -generated: "2022-11-21T22:55:45.1699395+01:00" + repository: oci://registry-1.docker.io/bitnamicharts + version: 12.5.6 +digest: sha256:4d21dbc02bbdb55b957b0093e37376853727de82396abfadfaf1d738bd51b8e6 +generated: "2023-06-03T20:58:45.922102213+02:00" diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index 91580077790..9fcd56463f6 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -7,17 +7,19 @@ sources: - https://github.com/hapifhir/hapi-fhir-jpaserver-starter dependencies: - name: postgresql - version: 12.1.2 - repository: https://charts.bitnami.com/bitnami + version: 12.5.6 + repository: oci://registry-1.docker.io/bitnamicharts condition: postgresql.enabled -appVersion: 6.2.2 -version: 0.11.1 +appVersion: 6.6.0 +version: 0.12.0 annotations: artifacthub.io/license: Apache-2.0 artifacthub.io/changes: | # When using the list of objects option the valid supported kinds are # added, changed, deprecated, removed, fixed, and security. - kind: changed - description: updated HAPI FHIR JPA Server app image version to v6.2.2 + description: updated HAPI FHIR JPA Server app image version to v6.6.0 - kind: changed - description: updated curl used by helm tests to version to v7.87.0 + description: updated curl used by helm tests to version to v8.1.1 + - kind: changed + description: updated postgresql sub-chart to v12.5.6 diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index 8b4b4619d43..179f68e7199 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -1,6 +1,6 @@ # HAPI FHIR JPA Server Starter Helm Chart -![Version: 0.11.1](https://img.shields.io/badge/Version-0.11.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.2.2](https://img.shields.io/badge/AppVersion-6.2.2-informational?style=flat-square) +![Version: 0.12.0](https://img.shields.io/badge/Version-0.12.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.6.0](https://img.shields.io/badge/AppVersion-6.6.0-informational?style=flat-square) This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment. @@ -8,11 +8,14 @@ This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes e ```sh helm repo add hapifhir https://hapifhir.github.io/hapi-fhir-jpaserver-starter/ -helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver +helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver ``` -> ⚠ By default, the included [PostgreSQL Helm chart](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrading) -> auto-generates a random password for the database which may cause problems when upgrading the chart (see [here for details](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrading)). +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| oci://registry-1.docker.io/bitnamicharts | postgresql | 12.5.6 | ## Values @@ -32,7 +35,7 @@ helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpas | image.pullPolicy | string | `"IfNotPresent"` | image pullPolicy to use | | image.registry | string | `"docker.io"` | registry where the HAPI FHIR server image is hosted | | image.repository | string | `"hapiproject/hapi"` | the path inside the repository | -| image.tag | string | `"v6.2.2@sha256:9c4e8af94d81ac0049dbb589e4cd855bf78c9c13be6f6844e814c63d63545b44"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. | +| image.tag | string | `"v6.6.0@sha256:c00367865ae5dad4e171cbb68bfc1c39818854079d1565bee4c86a45e78335d0"` | the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. | | imagePullSecrets | list | `[]` | image pull secrets to use when pulling the image | | ingress.annotations | object | `{}` | provide any additional annotations which may be required. Evaluated as a template. | | ingress.enabled | bool | `false` | whether to create an Ingress to expose the FHIR server HTTP endpoint | diff --git a/charts/hapi-fhir-jpaserver/README.md.gotmpl b/charts/hapi-fhir-jpaserver/README.md.gotmpl index bfea0325fe1..bfe51464b00 100644 --- a/charts/hapi-fhir-jpaserver/README.md.gotmpl +++ b/charts/hapi-fhir-jpaserver/README.md.gotmpl @@ -8,11 +8,10 @@ This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes e ```sh helm repo add hapifhir https://hapifhir.github.io/hapi-fhir-jpaserver-starter/ -helm install --render-subchart-notes hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver +helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver ``` -> ⚠ By default, the included [PostgreSQL Helm chart](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrading) -> auto-generates a random password for the database which may cause problems when upgrading the chart (see [here for details](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#upgrading)). +{{ template "chart.requirementsSection" . }} {{ template "chart.valuesSection" . }} diff --git a/charts/hapi-fhir-jpaserver/templates/deployment.yaml b/charts/hapi-fhir-jpaserver/templates/deployment.yaml index 8f3c65e3137..227ac4f25ca 100644 --- a/charts/hapi-fhir-jpaserver/templates/deployment.yaml +++ b/charts/hapi-fhir-jpaserver/templates/deployment.yaml @@ -30,7 +30,7 @@ spec: {{- toYaml .Values.podSecurityContext | nindent 8 }} initContainers: - name: wait-for-db-to-be-ready - image: docker.io/bitnami/postgresql:15.1.0-debian-11-r0@sha256:27915588d5203a10a1c23624d9c81644437f33b7c224e25f79bcd9bd09bbb8e2 + image: docker.io/bitnami/postgresql:15.3.0-debian-11-r7@sha256:cc301eef743685f4f69d1d719853988e8a9650c90fd9521f4742ce400b3fdf6a imagePullPolicy: IfNotPresent {{- with .Values.restrictedContainerSecurityContext }} securityContext: diff --git a/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml index 034efb12e02..71711505da7 100644 --- a/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml +++ b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml @@ -11,7 +11,7 @@ spec: restartPolicy: Never containers: - name: test-metadata-endpoint - image: docker.io/curlimages/curl:7.87.0@sha256:f7f265d5c64eb4463a43a99b6bf773f9e61a50aaa7cefaf564f43e42549a01dd + image: docker.io/curlimages/curl:8.1.2@sha256:ef501f5efa67be41da985b441bd63130ef39d4d6a4f9c035d737884357438b6c command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/metadata?_summary=true"] {{- with .Values.restrictedContainerSecurityContext }} @@ -32,7 +32,7 @@ spec: exec: command: ["true"] - name: test-patient-endpoint - image: docker.io/curlimages/curl:7.87.0@sha256:f7f265d5c64eb4463a43a99b6bf773f9e61a50aaa7cefaf564f43e42549a01dd + image: docker.io/curlimages/curl:8.1.2@sha256:ef501f5efa67be41da985b441bd63130ef39d4d6a4f9c035d737884357438b6c command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/Patient?_count=1&_summary=true"] {{- with .Values.restrictedContainerSecurityContext }} @@ -53,7 +53,7 @@ spec: exec: command: ["true"] - name: test-metrics-endpoint - image: docker.io/curlimages/curl:7.87.0@sha256:f7f265d5c64eb4463a43a99b6bf773f9e61a50aaa7cefaf564f43e42549a01dd + image: docker.io/curlimages/curl:8.1.2@sha256:ef501f5efa67be41da985b441bd63130ef39d4d6a4f9c035d737884357438b6c command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.metrics.service.port }}/actuator/prometheus"] {{- with .Values.restrictedContainerSecurityContext }} diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index be02b18983b..3349e1d87ac 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -7,7 +7,7 @@ image: # -- the path inside the repository repository: hapiproject/hapi # -- the image tag. As of v5.7.0, this is the `distroless` flavor by default, add `-tomcat` to use the Tomcat-based image. - tag: "v6.2.2@sha256:9c4e8af94d81ac0049dbb589e4cd855bf78c9c13be6f6844e814c63d63545b44" + tag: "v6.6.0@sha256:c00367865ae5dad4e171cbb68bfc1c39818854079d1565bee4c86a45e78335d0" # -- image pullPolicy to use pullPolicy: IfNotPresent From 484aa9deb5c184ef47569b8bb1d2c523b2a969ea Mon Sep 17 00:00:00 2001 From: winne42 Date: Tue, 11 Jul 2023 23:53:18 +0200 Subject: [PATCH 177/192] Boyscouting (#558) * Boyscouting: Docker conventions * Boyscouting: JUnit 5 conventions ("It is generally recommended to omit the public modifier for test classes, test methods, and lifecycle methods unless there is a technical reason for doing so)" * Boyscouting: typo in RepositoryValidationInterceptorFactoryDstu3 * Boyscouting: use List.of instead of Guava; use StandardCharsets instead of Guava; remove unused imports --------- Co-authored-by: Gerlach, Winfried --- Dockerfile | 6 +++--- src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java | 3 +-- .../fhir/jpa/starter/common/FhirServerConfigCommon.java | 4 +--- .../ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java | 6 +----- .../RepositoryValidationInterceptorFactoryDstu3.java | 4 ++-- .../ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java | 6 +++--- src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java | 4 ++-- .../ca/uhn/fhir/jpa/starter/util/EnvironmentHelper.java | 1 - src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java | 2 +- .../ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java | 2 +- .../ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java | 2 +- .../ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java | 8 ++++---- .../java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java | 2 +- .../java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java | 2 +- .../java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java | 8 ++++---- .../ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java | 6 +++--- .../ca/uhn/fhir/jpa/starter/SocketImplementation.java | 2 +- 17 files changed, 30 insertions(+), 38 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7c44d37998d..8e6c8b065c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/library/maven:3.9.2-eclipse-temurin-17 as build-hapi +FROM docker.io/library/maven:3.9.2-eclipse-temurin-17 AS build-hapi WORKDIR /tmp/hapi-fhir-jpaserver-starter ARG OPENTELEMETRY_JAVA_AGENT_VERSION=1.26.0 @@ -18,7 +18,7 @@ RUN mkdir /app && cp /tmp/hapi-fhir-jpaserver-starter/target/ROOT.war /app/main. ########### bitnami tomcat version is suitable for debugging and comes with a shell ########### it can be built using eg. `docker build --target tomcat .` -FROM bitnami/tomcat:9.0 as tomcat +FROM bitnami/tomcat:9.0 AS tomcat RUN rm -rf /opt/bitnami/tomcat/webapps/ROOT && \ mkdir -p /opt/bitnami/hapi/data/hapi/lucenefiles && \ @@ -36,7 +36,7 @@ COPY --from=build-hapi --chown=1001:1001 /tmp/hapi-fhir-jpaserver-starter/opente ENV ALLOW_EMPTY_PASSWORD=yes ########### distroless brings focus on security and runs on plain spring boot - this is the default image -FROM gcr.io/distroless/java17-debian11:nonroot as default +FROM gcr.io/distroless/java17-debian11:nonroot AS default # 65532 is the nonroot user's uid # used here instead of the name to allow Kubernetes to easily detect that the container # is running as a non-root (uid != 0) user. 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 b48d4e1550f..50e501c7ac0 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -5,7 +5,6 @@ import ca.uhn.fhir.jpa.api.config.JpaStorageSettings.ClientIdStrategyEnum; import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel; import ca.uhn.fhir.rest.api.EncodingEnum; -import com.google.common.collect.ImmutableList; import org.hl7.fhir.r4.model.Bundle; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -577,7 +576,7 @@ public List getLocal_base_urls() { public static class Cors { private Boolean allow_Credentials = true; - private List allowed_origin = ImmutableList.of("*"); + private List allowed_origin = List.of("*"); public List getAllowed_origin() { return allowed_origin; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java index 9751ba70f8d..12d7a8a6345 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java @@ -9,7 +9,6 @@ import ca.uhn.fhir.jpa.model.entity.StorageSettings; import ca.uhn.fhir.jpa.starter.AppProperties; import ca.uhn.fhir.jpa.starter.util.JpaHibernatePropertiesProvider; -import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory; import ca.uhn.fhir.jpa.subscription.match.deliver.email.EmailSenderImpl; import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender; import ca.uhn.fhir.rest.server.mail.IMailSvc; @@ -27,7 +26,6 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; import java.util.HashSet; -import java.util.Optional; import java.util.stream.Collectors; /** @@ -84,7 +82,7 @@ public FhirServerConfigCommon(AppProperties appProperties) { public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) { JpaStorageSettings jpaStorageSettings = new JpaStorageSettings(); - jpaStorageSettings.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? JpaStorageSettings.IndexEnabledEnum.ENABLED : JpaStorageSettings.IndexEnabledEnum.DISABLED); + jpaStorageSettings.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? StorageSettings.IndexEnabledEnum.ENABLED : StorageSettings.IndexEnabledEnum.DISABLED); jpaStorageSettings.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets()); jpaStorageSettings.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write()); jpaStorageSettings.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete()); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index c095e27cd05..77af694d71f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -24,7 +24,6 @@ import ca.uhn.fhir.jpa.config.util.ValidationSupportConfigUtil; import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl; import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc; -import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDaoJpaImpl; import ca.uhn.fhir.jpa.dao.search.HSearchSortHelperImpl; import ca.uhn.fhir.jpa.dao.search.IHSearchSortHelper; import ca.uhn.fhir.jpa.delete.ThreadSafeResourceDeleterSvc; @@ -44,12 +43,10 @@ import ca.uhn.fhir.jpa.starter.annotations.OnCorsPresent; import ca.uhn.fhir.jpa.starter.annotations.OnImplementationGuidesPresent; import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory; -import ca.uhn.fhir.jpa.starter.ips.IpsConfigCondition; import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper; import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor; import ca.uhn.fhir.jpa.util.ResourceCountCache; import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain; -import ca.uhn.fhir.mdm.dao.IMdmLinkDao; import ca.uhn.fhir.mdm.provider.MdmProviderLoader; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.narrative2.NullNarrativeGenerator; @@ -64,7 +61,6 @@ import ca.uhn.fhir.validation.IValidatorModule; import ca.uhn.fhir.validation.ResultSeverityEnum; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; @@ -205,7 +201,7 @@ public IPackageInstallerSvc packageInstaller(AppProperties appProperties, JobDef packageInstallationSpec.setReloadExisting(appProperties.getReload_existing_implementationguides()); if (appProperties.getInstall_transitive_ig_dependencies()) { packageInstallationSpec.setFetchDependencies(true); - packageInstallationSpec.setDependencyExcludes(ImmutableList.of("hl7.fhir.r2.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core", "hl7.fhir.r5.core")); + packageInstallationSpec.setDependencyExcludes(List.of("hl7.fhir.r2.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core", "hl7.fhir.r5.core")); } packageInstallerSvc.install(packageInstallationSpec); } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java index f8874b31a50..edaade773a3 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java @@ -47,12 +47,12 @@ public RepositoryValidationInterceptorFactoryDstu3(RepositoryValidatingRuleBuild public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() { IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource"))); - Map> structureDefintions = results.getResources(0, results.size()) + Map> structureDefinitions = results.getResources(0, results.size()) .stream() .map(StructureDefinition.class::cast) .collect(Collectors.groupingBy(StructureDefinition::getType)); - structureDefintions.forEach((key, value) -> { + structureDefinitions.forEach((key, value) -> { String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new); repositoryValidatingRuleBuilder.forResourcesOfType(key).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); }); diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java index e777879a580..308a3aafaf0 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/ips/StarterIpsConfig.java @@ -15,18 +15,18 @@ @Conditional(IpsConfigCondition.class) public class StarterIpsConfig { @Bean - IIpsGenerationStrategy IpsGenerationStrategy() + IIpsGenerationStrategy ipsGenerationStrategy() { return new DefaultIpsGenerationStrategy(); } @Bean - public IpsOperationProvider IpsOperationProvider(IIpsGeneratorSvc theIpsGeneratorSvc){ + public IpsOperationProvider ipsOperationProvider(IIpsGeneratorSvc theIpsGeneratorSvc){ return new IpsOperationProvider(theIpsGeneratorSvc); } @Bean - public IIpsGeneratorSvc IpsGeneratorSvcImpl(FhirContext theFhirContext, IIpsGenerationStrategy theGenerationStrategy, DaoRegistry theDaoRegistry) + public IIpsGeneratorSvc ipsGeneratorSvcImpl(FhirContext theFhirContext, IIpsGenerationStrategy theGenerationStrategy, DaoRegistry theDaoRegistry) { return new IpsGeneratorSvcImpl(theFhirContext, theGenerationStrategy, theDaoRegistry); } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java index 50dfe9e0489..7f0ee4c314f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/mdm/MdmConfig.java @@ -6,7 +6,6 @@ import ca.uhn.fhir.mdm.api.IMdmSettings; import ca.uhn.fhir.mdm.rules.config.MdmRuleValidator; import ca.uhn.fhir.mdm.rules.config.MdmSettings; -import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -17,6 +16,7 @@ import org.springframework.core.io.Resource; import java.io.IOException; +import java.nio.charset.StandardCharsets; @Configuration @Conditional(MdmConfigCondition.class) @@ -27,7 +27,7 @@ public class MdmConfig { IMdmSettings mdmSettings(@Autowired MdmRuleValidator theMdmRuleValidator, AppProperties appProperties) throws IOException { DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); Resource resource = resourceLoader.getResource("mdm-rules.json"); - String json = IOUtils.toString(resource.getInputStream(), Charsets.UTF_8); + String json = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8); return new MdmSettings(theMdmRuleValidator).setEnabled(appProperties.getMdm_enabled()).setScriptText(json); } } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/util/EnvironmentHelper.java b/src/main/java/ca/uhn/fhir/jpa/starter/util/EnvironmentHelper.java index 41bb556c4c3..71d947ac410 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/util/EnvironmentHelper.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/util/EnvironmentHelper.java @@ -17,7 +17,6 @@ import org.hibernate.search.mapper.orm.schema.management.SchemaManagementStrategyName; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy; -import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.EnumerablePropertySource; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java index 07e7f581a30..fe3fba474dc 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java @@ -11,7 +11,7 @@ // "hapi.fhir.enable_repository_validating_interceptor=true", "hapi.fhir.fhir_version=r4" }) -public class CustomBeanTest { +class CustomBeanTest { @Autowired some.custom.pkg1.CustomBean customBean1; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java index 367857b7009..248bfe3600b 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java @@ -21,7 +21,7 @@ "hapi.fhir.fhir_version=r4" }) -public class CustomInterceptorTest { +class CustomInterceptorTest { @LocalServerPort private int port; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java index 4369086733f..25776cc666a 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -21,7 +21,7 @@ "hapi.fhir.fhir_version=dstu2", "spring.datasource.url=jdbc:h2:mem:dbr2", }) -public class ExampleServerDstu2IT { +class ExampleServerDstu2IT { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); private IGenericClient ourClient; diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index 850bdb36c98..0d20bab4e62 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -49,7 +49,7 @@ }) -public class ExampleServerDstu3IT implements IServerSupport { +class ExampleServerDstu3IT implements IServerSupport { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); private IGenericClient ourClient; @@ -71,8 +71,8 @@ void beforeEach() { ourClient.registerInterceptor(new LoggingInterceptor(true)); } - @Test - public void testCreateAndRead() { + @Test + void testCreateAndRead() { String methodName = "testCreateResourceConditional"; @@ -154,7 +154,7 @@ private Bundle loadBundle(String theLocation, FhirContext theCtx, IGenericClient } @Test - public void testWebsocketSubscription() throws Exception { + void testWebsocketSubscription() throws Exception { /* * Create subscription */ diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java index 9f19fcb74de..f6942c6848c 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java @@ -52,7 +52,7 @@ void testCreateAndRead() { @Test - public void testBatchPutWithIdenticalTags() { + void testBatchPutWithIdenticalTags() { String batchPuts = "{\n" + "\t\"resourceType\": \"Bundle\",\n" + "\t\"id\": \"patients\",\n" + diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 319ed1cd7a2..d08770a8ba1 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -87,7 +87,7 @@ private Patient getGoldenResourcePatient() { } @Test - public void testBatchPutWithIdenticalTags() { + void testBatchPutWithIdenticalTags() { String batchPuts = "{\n" + "\t\"resourceType\": \"Bundle\",\n" + "\t\"id\": \"patients\",\n" + diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index 8ecfb737462..349d883387b 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -45,15 +45,15 @@ public class ExampleServerR5IT { private IGenericClient ourClient; private FhirContext ourCtx; - public static final String SUBSCRIPTION_TOPIC_TEST_URL = "http://example.com/topic/test"; + public static final String SUBSCRIPTION_TOPIC_TEST_URL = "http://example.com/topic/test"; - @LocalServerPort + @LocalServerPort private int port; @Test - public void testCreateAndRead() { + void testCreateAndRead() { String methodName = "testCreateResourceConditional"; @@ -66,7 +66,7 @@ public void testCreateAndRead() { } @Test - public void testWebsocketSubscription() throws Exception { + void testWebsocketSubscription() throws Exception { String endpoint = "ws://localhost:" + port + "/websocket"; /* * Create topic diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java index 463a1c6c0ad..cf85478db9c 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -26,7 +26,7 @@ "hapi.fhir.partitioning.partitioning_include_in_search_hashes=false", }) -public class MultitenantServerR4IT { +class MultitenantServerR4IT { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerDstu2IT.class); @@ -40,7 +40,7 @@ public class MultitenantServerR4IT { @Test - public void testCreateAndReadInTenantA() { + void testCreateAndReadInTenantA() { // Create tenant A @@ -66,7 +66,7 @@ public void testCreateAndReadInTenantA() { } @Test - public void testCreateAndReadInTenantB() { + void testCreateAndReadInTenantB() { // Create tenant A diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java b/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java index 7734a23c6f2..4a536f0f2a1 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java @@ -18,7 +18,7 @@ public class SocketImplementation { private final String myCriteria; protected String myError; protected boolean myGotBound; - private final List myMessages = new ArrayList(); + private final List myMessages = new ArrayList<>(); protected int myPingCount; protected String mySubsId; private Session session; From 9d8fc4d2e59d7af4166113325f3e663d77024a09 Mon Sep 17 00:00:00 2001 From: "Gerlach, Winfried" Date: Wed, 12 Jul 2023 17:53:58 +0200 Subject: [PATCH 178/192] #563 Add configuration for auto-versioning references --- .../java/ca/uhn/fhir/jpa/starter/AppProperties.java | 11 +++++++++-- .../jpa/starter/common/FhirServerConfigCommon.java | 7 ++++--- .../uhn/fhir/jpa/starter/common/FhirTesterConfig.java | 2 +- src/main/resources/application.yaml | 2 ++ 4 files changed, 16 insertions(+), 6 deletions(-) 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 50e501c7ac0..3ed76791251 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -11,9 +11,11 @@ import org.springframework.context.annotation.Configuration; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; @ConfigurationProperties(prefix = "hapi.fhir") @Configuration @@ -32,6 +34,7 @@ public class AppProperties { private Boolean allow_multiple_delete = false; private Boolean allow_override_default_search_params = true; private Boolean auto_create_placeholder_reference_targets = false; + private final Set auto_version_reference_at_paths = new HashSet<>(); private Boolean dao_scheduling_enabled = true; private Boolean delete_expunge_enabled = false; private Boolean enable_index_missing_fields = false; @@ -84,7 +87,7 @@ public class AppProperties { private Integer bundle_batch_pool_size = 20; private Integer bundle_batch_pool_max_size = 100; - private final List local_base_urls = new ArrayList<>(); + private final Set local_base_urls = new HashSet<>(); private final List custom_interceptor_classes = new ArrayList<>(); @@ -306,6 +309,10 @@ public void setAuto_create_placeholder_reference_targets( this.auto_create_placeholder_reference_targets = auto_create_placeholder_reference_targets; } + public Set getAuto_version_reference_at_paths() { + return auto_version_reference_at_paths; + } + public Integer getDefault_page_size() { return default_page_size; } @@ -570,7 +577,7 @@ public void setBundle_batch_pool_max_size(Integer bundle_batch_pool_max_size) { this.bundle_batch_pool_max_size = bundle_batch_pool_max_size; } - public List getLocal_base_urls() { + public Set getLocal_base_urls() { return local_base_urls; } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java index 12d7a8a6345..6a931614cfe 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java @@ -25,7 +25,6 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; -import java.util.HashSet; import java.util.stream.Collectors; /** @@ -47,6 +46,7 @@ public FhirServerConfigCommon(AppProperties appProperties) { ourLog.info("Server configured to " + (appProperties.getExpunge_enabled() ? "enable" : "disable") + " expunges"); ourLog.info("Server configured to " + (appProperties.getAllow_override_default_search_params() ? "allow" : "deny") + " overriding default search params"); ourLog.info("Server configured to " + (appProperties.getAuto_create_placeholder_reference_targets() ? "allow" : "disable") + " auto-creating placeholder references"); + ourLog.info("Server configured to auto-version references at paths {}", appProperties.getAuto_version_reference_at_paths()); if (appProperties.getSubscription().getEmail() != null) { AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail(); @@ -84,6 +84,7 @@ public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) { jpaStorageSettings.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? StorageSettings.IndexEnabledEnum.ENABLED : StorageSettings.IndexEnabledEnum.DISABLED); jpaStorageSettings.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets()); + jpaStorageSettings.setAutoVersionReferenceAtPaths(appProperties.getAuto_version_reference_at_paths()); jpaStorageSettings.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write()); jpaStorageSettings.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete()); jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches()); @@ -125,9 +126,9 @@ public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) { jpaStorageSettings.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); jpaStorageSettings.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing()); - jpaStorageSettings.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls())); + jpaStorageSettings.setTreatBaseUrlsAsLocal(appProperties.getLocal_base_urls()); - if (appProperties.getLastn_enabled()) { + if (appProperties.getLastn_enabled()) { jpaStorageSettings.setLastNEnabled(true); } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java index cb28659d52c..2bc9aa2da1f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java @@ -26,7 +26,7 @@ public class FhirTesterConfig { * server, as well as one public server. If you are creating a project to * deploy somewhere else, you might choose to only put your own server's * address here. - * + *

* Note the use of the ${serverBase} variable below. This will be replaced with * the base URL as reported by the server itself. Often for a simple Tomcat * (or other container) installation, this will end up being something diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 9b1e11872a5..cd2dbb0eb1e 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -99,6 +99,8 @@ hapi: # allow_multiple_delete: true # allow_override_default_search_params: true # auto_create_placeholder_reference_targets: false + ### tells the server to automatically append the current version of the target to references at these paths + # auto_version_reference_at_paths: Device.patient, Device.location, Device.parent, DeviceMetric.parent, DeviceMetric.source, Observation.device, Observation.subject # cr_enabled: true # ips_enabled: false # default_encoding: JSON From 98165e848ff9cfba415d8d8098efdeaf7302664a Mon Sep 17 00:00:00 2001 From: "Gerlach, Winfried" Date: Thu, 13 Jul 2023 09:06:42 +0200 Subject: [PATCH 179/192] #563 fix indentation --- .../ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java | 2 +- src/main/resources/application.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java index 6a931614cfe..f040ab77491 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java @@ -84,7 +84,7 @@ public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) { jpaStorageSettings.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? StorageSettings.IndexEnabledEnum.ENABLED : StorageSettings.IndexEnabledEnum.DISABLED); jpaStorageSettings.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets()); - jpaStorageSettings.setAutoVersionReferenceAtPaths(appProperties.getAuto_version_reference_at_paths()); + jpaStorageSettings.setAutoVersionReferenceAtPaths(appProperties.getAuto_version_reference_at_paths()); jpaStorageSettings.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write()); jpaStorageSettings.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete()); jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches()); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index cd2dbb0eb1e..557654cd781 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -99,7 +99,7 @@ hapi: # allow_multiple_delete: true # allow_override_default_search_params: true # auto_create_placeholder_reference_targets: false - ### tells the server to automatically append the current version of the target to references at these paths + ### tells the server to automatically append the current version of the target resource to references at these paths # auto_version_reference_at_paths: Device.patient, Device.location, Device.parent, DeviceMetric.parent, DeviceMetric.source, Observation.device, Observation.subject # cr_enabled: true # ips_enabled: false From 8ef50832d3459d4eb35ecb4f116c580475acb59d Mon Sep 17 00:00:00 2001 From: chgl Date: Fri, 21 Jul 2023 16:26:10 +0200 Subject: [PATCH 180/192] Updated helm chart with additional config settings (#566) --- charts/hapi-fhir-jpaserver/Chart.yaml | 12 ++-- charts/hapi-fhir-jpaserver/README.md | 21 ++----- charts/hapi-fhir-jpaserver/README.md.gotmpl | 2 +- .../ci/extra-config-values.yaml | 17 ++++++ .../templates/application-config.yaml | 11 ++++ .../templates/deployment.yaml | 52 ++++++++--------- .../templates/tests/test-endpoints.yaml | 33 ++++------- charts/hapi-fhir-jpaserver/values.yaml | 56 +++++++++++++++++-- 8 files changed, 125 insertions(+), 79 deletions(-) create mode 100644 charts/hapi-fhir-jpaserver/ci/extra-config-values.yaml create mode 100644 charts/hapi-fhir-jpaserver/templates/application-config.yaml diff --git a/charts/hapi-fhir-jpaserver/Chart.yaml b/charts/hapi-fhir-jpaserver/Chart.yaml index 9fcd56463f6..a81e1082a60 100644 --- a/charts/hapi-fhir-jpaserver/Chart.yaml +++ b/charts/hapi-fhir-jpaserver/Chart.yaml @@ -11,15 +11,17 @@ dependencies: repository: oci://registry-1.docker.io/bitnamicharts condition: postgresql.enabled appVersion: 6.6.0 -version: 0.12.0 +version: 0.13.0 annotations: artifacthub.io/license: Apache-2.0 artifacthub.io/changes: | # When using the list of objects option the valid supported kinds are # added, changed, deprecated, removed, fixed, and security. + - kind: added + description: allow specifying application properties via yaml config + - kind: added + description: allow setting resource limits and requests for the Helm test pods - kind: changed - description: updated HAPI FHIR JPA Server app image version to v6.6.0 + description: updated curl used by helm tests to version to v8.2.0 - kind: changed - description: updated curl used by helm tests to version to v8.1.1 - - kind: changed - description: updated postgresql sub-chart to v12.5.6 + description: allow disabling the liveness-, readiness-, and startup-probes entirely diff --git a/charts/hapi-fhir-jpaserver/README.md b/charts/hapi-fhir-jpaserver/README.md index 179f68e7199..7d4d338db4d 100644 --- a/charts/hapi-fhir-jpaserver/README.md +++ b/charts/hapi-fhir-jpaserver/README.md @@ -1,6 +1,6 @@ # HAPI FHIR JPA Server Starter Helm Chart -![Version: 0.12.0](https://img.shields.io/badge/Version-0.12.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.6.0](https://img.shields.io/badge/AppVersion-6.6.0-informational?style=flat-square) +![Version: 0.13.0](https://img.shields.io/badge/Version-0.13.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.6.0](https://img.shields.io/badge/AppVersion-6.6.0-informational?style=flat-square) This helm chart will help you install the HAPI FHIR JPA Server in a Kubernetes environment. @@ -30,6 +30,7 @@ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver | externalDatabase.password | string | `""` | database password | | externalDatabase.port | int | `5432` | database port number | | externalDatabase.user | string | `"fhir"` | username for the external database | +| extraConfig | string | `""` | additional Spring Boot application config. Mounted as a file and automatically loaded by the application. | | extraEnv | list | `[]` | extra environment variables to set on the server container | | fullnameOverride | string | `""` | override the chart fullname | | image.pullPolicy | string | `"IfNotPresent"` | image pullPolicy to use | @@ -43,11 +44,6 @@ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver | ingress.hosts[0].pathType | string | `"ImplementationSpecific"` | | | ingress.hosts[0].paths[0] | string | `"/"` | | | ingress.tls | list | `[]` | ingress TLS config | -| livenessProbe.failureThreshold | int | `5` | | -| livenessProbe.initialDelaySeconds | int | `30` | | -| livenessProbe.periodSeconds | int | `20` | | -| livenessProbe.successThreshold | int | `1` | | -| livenessProbe.timeoutSeconds | int | `30` | | | metrics.service.port | int | `8081` | | | metrics.serviceMonitor.additionalLabels | object | `{}` | additional labels to apply to the ServiceMonitor object, e.g. `release: prometheus` | | metrics.serviceMonitor.enabled | bool | `false` | if enabled, creates a ServiceMonitor instance for Prometheus Operator-based monitoring | @@ -65,11 +61,6 @@ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver | postgresql.primary.containerSecurityContext.capabilities.drop[0] | string | `"ALL"` | | | postgresql.primary.containerSecurityContext.runAsNonRoot | bool | `true` | | | postgresql.primary.containerSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | | -| readinessProbe.failureThreshold | int | `5` | | -| readinessProbe.initialDelaySeconds | int | `30` | | -| readinessProbe.periodSeconds | int | `20` | | -| readinessProbe.successThreshold | int | `1` | | -| readinessProbe.timeoutSeconds | int | `20` | | | replicaCount | int | `1` | number of replicas to deploy | | resources | object | `{}` | configure the FHIR server's resource requests and limits | | securityContext.allowPrivilegeEscalation | bool | `false` | | @@ -82,18 +73,14 @@ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver | securityContext.seccompProfile.type | string | `"RuntimeDefault"` | | | service.port | int | `8080` | port where the server will be exposed at | | service.type | string | `"ClusterIP"` | service type | -| startupProbe.failureThreshold | int | `10` | | -| startupProbe.initialDelaySeconds | int | `30` | | -| startupProbe.periodSeconds | int | `30` | | -| startupProbe.successThreshold | int | `1` | | -| startupProbe.timeoutSeconds | int | `30` | | +| tests.resources | object | `{}` | configure the test pods resource requests and limits | | tolerations | list | `[]` | pod tolerations | | topologySpreadConstraints | list | `[]` | pod topology spread configuration see: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#api | ## Development To update the Helm chart when a new version of the `hapiproject/hapi` image is released, [values.yaml](values.yaml) `image.tag` and the [Chart.yaml](Chart.yaml)'s -`version` and optionally the `appVersion` field on major releases need to be updated. Afterwards, re-generate the [README.md](README.md) +`version` and optionally the `appVersion` field need to be updated. Afterwards, re-generate the [README.md](README.md) by running: ```sh diff --git a/charts/hapi-fhir-jpaserver/README.md.gotmpl b/charts/hapi-fhir-jpaserver/README.md.gotmpl index bfe51464b00..46473954b59 100644 --- a/charts/hapi-fhir-jpaserver/README.md.gotmpl +++ b/charts/hapi-fhir-jpaserver/README.md.gotmpl @@ -18,7 +18,7 @@ helm install hapi-fhir-jpaserver hapifhir/hapi-fhir-jpaserver ## Development To update the Helm chart when a new version of the `hapiproject/hapi` image is released, [values.yaml](values.yaml) `image.tag` and the [Chart.yaml](Chart.yaml)'s -`version` and optionally the `appVersion` field on major releases need to be updated. Afterwards, re-generate the [README.md](README.md) +`version` and optionally the `appVersion` field need to be updated. Afterwards, re-generate the [README.md](README.md) by running: ```sh diff --git a/charts/hapi-fhir-jpaserver/ci/extra-config-values.yaml b/charts/hapi-fhir-jpaserver/ci/extra-config-values.yaml new file mode 100644 index 00000000000..d2406ac2142 --- /dev/null +++ b/charts/hapi-fhir-jpaserver/ci/extra-config-values.yaml @@ -0,0 +1,17 @@ +extraConfig: | + hapi: + fhir: + cr_enabled: true + tester: + home: + name: Hello HAPI FHIR + server_address: "http://fhir-server.127.0.0.1.nip.io/fhir" + refuse_to_fetch_third_party_urls: true + fhir_version: R4 + +ingress: + enabled: true + hosts: + - host: fhir-server.127.0.0.1.nip.io + pathType: ImplementationSpecific + paths: ["/"] diff --git a/charts/hapi-fhir-jpaserver/templates/application-config.yaml b/charts/hapi-fhir-jpaserver/templates/application-config.yaml new file mode 100644 index 00000000000..e4df9cea30f --- /dev/null +++ b/charts/hapi-fhir-jpaserver/templates/application-config.yaml @@ -0,0 +1,11 @@ +{{- if .Values.extraConfig -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "hapi-fhir-jpaserver.fullname" . }}-application-config + labels: + {{- include "hapi-fhir-jpaserver.labels" . | nindent 4 }} +data: + application-extra.yaml: |- + {{ .Values.extraConfig | nindent 4 }} +{{- end }} diff --git a/charts/hapi-fhir-jpaserver/templates/deployment.yaml b/charts/hapi-fhir-jpaserver/templates/deployment.yaml index 227ac4f25ca..c15609f443d 100644 --- a/charts/hapi-fhir-jpaserver/templates/deployment.yaml +++ b/charts/hapi-fhir-jpaserver/templates/deployment.yaml @@ -63,38 +63,17 @@ spec: - name: http-metrics containerPort: 8081 protocol: TCP - startupProbe: - httpGet: - path: /readyz - port: http {{- with .Values.startupProbe }} - initialDelaySeconds: {{ .initialDelaySeconds }} - periodSeconds: {{ .periodSeconds }} - timeoutSeconds: {{ .timeoutSeconds }} - successThreshold: {{ .successThreshold }} - failureThreshold: {{ .failureThreshold }} - {{- end }} - readinessProbe: - httpGet: - path: /readyz - port: http - {{- with .Values.readinessProbe }} - initialDelaySeconds: {{ .initialDelaySeconds }} - periodSeconds: {{ .periodSeconds }} - timeoutSeconds: {{ .timeoutSeconds }} - successThreshold: {{ .successThreshold }} - failureThreshold: {{ .failureThreshold }} + startupProbe: + {{- toYaml . | nindent 12 }} {{- end }} - livenessProbe: - httpGet: - path: /livez - port: http {{- with .Values.livenessProbe }} - initialDelaySeconds: {{ .initialDelaySeconds }} - periodSeconds: {{ .periodSeconds }} - timeoutSeconds: {{ .timeoutSeconds }} - successThreshold: {{ .successThreshold }} - failureThreshold: {{ .failureThreshold }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} @@ -118,6 +97,10 @@ spec: value: "true" - name: MANAGEMENT_SERVER_PORT value: "8081" + {{- if .Values.extraConfig }} + - name: SPRING_CONFIG_IMPORT + value: "/app/config/application-extra.yaml" + {{- end }} {{- if .Values.extraEnv }} {{ toYaml .Values.extraEnv | nindent 12 }} {{- end }} @@ -126,6 +109,12 @@ spec: name: tmp-volume - mountPath: /app/target name: lucenefiles-volume + {{- if .Values.extraConfig }} + - name: application-extra-config + mountPath: /app/config/application-extra.yaml + readOnly: true + subPath: application-extra.yaml + {{- end }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} @@ -147,3 +136,8 @@ spec: emptyDir: {} - name: lucenefiles-volume emptyDir: {} + {{- if .Values.extraConfig }} + - name: application-extra-config + configMap: + name: {{ include "hapi-fhir-jpaserver.fullname" . }}-application-config + {{- end }} diff --git a/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml index 71711505da7..bd81c4aa450 100644 --- a/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml +++ b/charts/hapi-fhir-jpaserver/templates/tests/test-endpoints.yaml @@ -11,20 +11,17 @@ spec: restartPolicy: Never containers: - name: test-metadata-endpoint - image: docker.io/curlimages/curl:8.1.2@sha256:ef501f5efa67be41da985b441bd63130ef39d4d6a4f9c035d737884357438b6c + image: "{{ .Values.curl.image.registry }}/{{ .Values.curl.image.repository }}:{{ .Values.curl.image.tag }}" command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/metadata?_summary=true"] {{- with .Values.restrictedContainerSecurityContext }} securityContext: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.tests.resources }} resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi + {{- toYaml . | nindent 8 }} + {{- end }} livenessProbe: exec: command: ["true"] @@ -32,20 +29,17 @@ spec: exec: command: ["true"] - name: test-patient-endpoint - image: docker.io/curlimages/curl:8.1.2@sha256:ef501f5efa67be41da985b441bd63130ef39d4d6a4f9c035d737884357438b6c + image: "{{ .Values.curl.image.registry }}/{{ .Values.curl.image.repository }}:{{ .Values.curl.image.tag }}" command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.service.port }}/fhir/Patient?_count=1&_summary=true"] {{- with .Values.restrictedContainerSecurityContext }} securityContext: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.tests.resources }} resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi + {{- toYaml . | nindent 8 }} + {{- end }} livenessProbe: exec: command: ["true"] @@ -53,20 +47,17 @@ spec: exec: command: ["true"] - name: test-metrics-endpoint - image: docker.io/curlimages/curl:8.1.2@sha256:ef501f5efa67be41da985b441bd63130ef39d4d6a4f9c035d737884357438b6c + image: "{{ .Values.curl.image.registry }}/{{ .Values.curl.image.repository }}:{{ .Values.curl.image.tag }}" command: ["curl", "--fail-with-body"] args: ["http://{{ include "hapi-fhir-jpaserver.fullname" . }}:{{ .Values.metrics.service.port }}/actuator/prometheus"] {{- with .Values.restrictedContainerSecurityContext }} securityContext: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.tests.resources }} resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi + {{- toYaml . | nindent 8 }} + {{- end }} livenessProbe: exec: command: ["true"] diff --git a/charts/hapi-fhir-jpaserver/values.yaml b/charts/hapi-fhir-jpaserver/values.yaml index 3349e1d87ac..9e9c18746b3 100644 --- a/charts/hapi-fhir-jpaserver/values.yaml +++ b/charts/hapi-fhir-jpaserver/values.yaml @@ -131,24 +131,39 @@ postgresql: seccompProfile: type: RuntimeDefault +# -- readiness probe +# @ignored readinessProbe: + httpGet: + path: /readyz + port: http failureThreshold: 5 initialDelaySeconds: 30 periodSeconds: 20 successThreshold: 1 timeoutSeconds: 20 -startupProbe: - failureThreshold: 10 +# -- liveness probe +# @ignored +livenessProbe: + httpGet: + path: /livez + port: http + failureThreshold: 5 initialDelaySeconds: 30 - periodSeconds: 30 + periodSeconds: 20 successThreshold: 1 timeoutSeconds: 30 -livenessProbe: - failureThreshold: 5 +# -- startup probe +# @ignored +startupProbe: + httpGet: + path: /readyz + port: http + failureThreshold: 10 initialDelaySeconds: 30 - periodSeconds: 20 + periodSeconds: 30 successThreshold: 1 timeoutSeconds: 30 @@ -208,3 +223,32 @@ restrictedContainerSecurityContext: runAsGroup: 65534 seccompProfile: type: RuntimeDefault + +# @ignored +curl: + image: + registry: docker.io + repository: curlimages/curl + tag: 8.2.0@sha256:daf3f46a2639c1613b25e85c9ee4193af8a1d538f92483d67f9a3d7f21721827 + +tests: + # -- configure the test pods resource requests and limits + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +# -- additional Spring Boot application config. Mounted as a file and automatically loaded by the application. +extraConfig: "" + # # For example: + # | + # hapi: + # fhir: + # implementationguides: + # gh_0_1_0: + # url: https://build.fhir.org/ig/hl7-eu/gravitate-health/package.tgz + # name: hl7.eu.fhir.gh + # version: 0.1.0 From e9f29af1aac64f9a0453bd95b602e6b019a7388f Mon Sep 17 00:00:00 2001 From: dotasek Date: Mon, 31 Jul 2023 14:34:47 -0400 Subject: [PATCH 181/192] Bump to hapi 6.8.0-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1fc9a25f8ad..67495dfb39e 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.6.0 + 6.8.0-SNAPSHOT hapi-fhir-jpaserver-starter From aafd4fa0d9484214ffd49f6e68ef665551ccc117 Mon Sep 17 00:00:00 2001 From: dotasek Date: Mon, 31 Jul 2023 14:43:58 -0400 Subject: [PATCH 182/192] Switch to new ca.uhn.fhir.batch2.jobs.export to fix StarterJpaConfig --- .../java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index c095e27cd05..4788d59c9e2 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -18,7 +18,7 @@ import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor; import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider; -import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider; +import ca.uhn.fhir.batch2.jobs.export.BulkDataExportProvider; import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil; import ca.uhn.fhir.jpa.config.util.ResourceCountCacheUtil; import ca.uhn.fhir.jpa.config.util.ValidationSupportConfigUtil; From 3c395e9dbe23ee7de43869f3e2ad8dfc3ad06521 Mon Sep 17 00:00:00 2001 From: dotasek Date: Thu, 10 Aug 2023 12:08:57 -0400 Subject: [PATCH 183/192] WIP try to expand default max_result_window --- .../jpa/starter/ElasticsearchLastNR4IT.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 5cb0a4e7072..f8728bb493a 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -8,6 +8,10 @@ import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Date; @@ -43,6 +47,9 @@ "hapi.fhir.lastn_enabled=true", "hapi.fhir.store_resource_in_lucene_index_enabled=true", "hapi.fhir.advanced_lucene_indexing=true", + "hapi.fhir.subscription.websocket_enabled=false", + "hapi.fhir.subscription.resthook_enabled=false", + "hapi.fhir.subscription.email_enabled=false", "elasticsearch.enabled=true", // Because the port is set randomly, we will set the rest_url using the Initializer. // "elasticsearch.rest_url='http://localhost:9200'", @@ -69,9 +76,21 @@ public class ElasticsearchLastNR4IT { private ElasticsearchSvcImpl myElasticsearchSvc; @BeforeAll - public static void beforeClass() { + public static void beforeClass() throws IOException { embeddedElastic = new ElasticsearchContainer(ELASTIC_IMAGE).withStartupTimeout(Duration.of(300, ChronoUnit.SECONDS)); embeddedElastic.start(); + + URL url = new URL("http://" + embeddedElastic.getHost() + ":9200/_settings"); + HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); + httpCon.setDoOutput(true); + httpCon.setRequestMethod("PUT"); + OutputStreamWriter out = new OutputStreamWriter( + httpCon.getOutputStream()); + out.write("{\n" + + " \"index.max_result_window\": 50000\n" + + "}"); + out.close(); + httpCon.getInputStream(); } @PreDestroy From f7853f5e19afd1f16854c3fd352fe1fc423ef04e Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 10 Aug 2023 09:30:01 -0700 Subject: [PATCH 184/192] Fix up test --- pom.xml | 6 +++ .../jpa/starter/ElasticsearchLastNR4IT.java | 47 ++++++++++++------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index 67495dfb39e..e84aeed6d12 100644 --- a/pom.xml +++ b/pom.xml @@ -247,6 +247,12 @@ + + ca.uhn.hapi.fhir + hapi-fhir-jpaserver-test-utilities + ${project.version} + test + org.eclipse.jetty jetty-servlets diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index f8728bb493a..240cd29869b 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -3,20 +3,28 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.search.lastn.ElasticsearchRestClientFactory; import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl; +import ca.uhn.fhir.jpa.test.config.TestElasticsearchContainerHelper; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; -import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.GregorianCalendar; +import java.util.List; import javax.annotation.PreDestroy; + +import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.client.indices.PutIndexTemplateRequest; +import org.elasticsearch.common.settings.Settings; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.DateTimeType; @@ -38,8 +46,11 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; @ExtendWith(SpringExtension.class) +@Testcontainers @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr4", @@ -70,29 +81,28 @@ public class ElasticsearchLastNR4IT { private static final String ELASTIC_VERSION = "7.16.3"; private static final String ELASTIC_IMAGE = "docker.elastic.co/elasticsearch/elasticsearch:" + ELASTIC_VERSION; - private static ElasticsearchContainer embeddedElastic; + + @Container + public static ElasticsearchContainer embeddedElastic = TestElasticsearchContainerHelper.getEmbeddedElasticSearch(); @Autowired private ElasticsearchSvcImpl myElasticsearchSvc; @BeforeAll public static void beforeClass() throws IOException { - embeddedElastic = new ElasticsearchContainer(ELASTIC_IMAGE).withStartupTimeout(Duration.of(300, ChronoUnit.SECONDS)); - embeddedElastic.start(); - - URL url = new URL("http://" + embeddedElastic.getHost() + ":9200/_settings"); - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - httpCon.setDoOutput(true); - httpCon.setRequestMethod("PUT"); - OutputStreamWriter out = new OutputStreamWriter( - httpCon.getOutputStream()); - out.write("{\n" + - " \"index.max_result_window\": 50000\n" + - "}"); - out.close(); - httpCon.getInputStream(); + //Given + RestHighLevelClient elasticsearchHighLevelRestClient = ElasticsearchRestClientFactory.createElasticsearchHighLevelRestClient( + "http", embeddedElastic.getHost() + ":" + embeddedElastic.getMappedPort(9200), "", ""); + + PutIndexTemplateRequest putIndexTemplateRequest = new PutIndexTemplateRequest("hapi_fhir_template"); + putIndexTemplateRequest.patterns(List.of("*")); + Settings settings = Settings.builder().put("index.max_result_window", 50000).build(); + putIndexTemplateRequest.settings(settings); + elasticsearchHighLevelRestClient.indices().putTemplate(putIndexTemplateRequest, RequestOptions.DEFAULT); + + } - + @PreDestroy public void stop() { embeddedElastic.stop(); @@ -134,7 +144,7 @@ void testLastN() throws IOException, InterruptedException { } @BeforeEach - void beforeEach() { + void beforeEach() throws IOException { ourCtx = FhirContext.forR4(); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); @@ -142,6 +152,7 @@ void beforeEach() { String ourServerBase = "http://localhost:" + port + "/fhir/"; ourClient = ourCtx.newRestfulGenericClient(ourServerBase); ourClient.registerInterceptor(new LoggingInterceptor(true)); + } static class Initializer From bdf593f151e9210d0c7736f022fa4fe9ae7ab335 Mon Sep 17 00:00:00 2001 From: dotasek Date: Thu, 10 Aug 2023 12:34:45 -0400 Subject: [PATCH 185/192] Clean up code --- .../fhir/jpa/starter/ElasticsearchLastNR4IT.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 240cd29869b..f65a5725121 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -10,17 +10,12 @@ import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import java.io.IOException; -import java.io.OutputStreamWriter; -import java.net.HttpURLConnection; -import java.net.URL; -import java.time.Duration; -import java.time.temporal.ChronoUnit; + import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import javax.annotation.PreDestroy; -import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.indices.PutIndexTemplateRequest; @@ -58,9 +53,7 @@ "hapi.fhir.lastn_enabled=true", "hapi.fhir.store_resource_in_lucene_index_enabled=true", "hapi.fhir.advanced_lucene_indexing=true", - "hapi.fhir.subscription.websocket_enabled=false", - "hapi.fhir.subscription.resthook_enabled=false", - "hapi.fhir.subscription.email_enabled=false", + "elasticsearch.enabled=true", // Because the port is set randomly, we will set the rest_url using the Initializer. // "elasticsearch.rest_url='http://localhost:9200'", @@ -79,10 +72,7 @@ public class ElasticsearchLastNR4IT { private IGenericClient ourClient; private FhirContext ourCtx; - private static final String ELASTIC_VERSION = "7.16.3"; - private static final String ELASTIC_IMAGE = "docker.elastic.co/elasticsearch/elasticsearch:" + ELASTIC_VERSION; - - @Container + @Container public static ElasticsearchContainer embeddedElastic = TestElasticsearchContainerHelper.getEmbeddedElasticSearch(); @Autowired From 1907536d28ec527cc57a6f9536f1742af0fa6e60 Mon Sep 17 00:00:00 2001 From: dotasek Date: Thu, 10 Aug 2023 12:51:34 -0400 Subject: [PATCH 186/192] Fix one more failing IT config --- src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index d08770a8ba1..26f27f660b1 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -1,6 +1,7 @@ package ca.uhn.fhir.jpa.starter; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.searchparam.config.NicknameServiceConfig; import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.MethodOutcome; @@ -30,7 +31,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class, NicknameServiceConfig.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr4", "hapi.fhir.enable_repository_validating_interceptor=true", "hapi.fhir.fhir_version=r4", From 7265b115dd83664d972235f677d898e89a1d3c48 Mon Sep 17 00:00:00 2001 From: dotasek Date: Thu, 10 Aug 2023 12:55:30 -0400 Subject: [PATCH 187/192] Leave comment in case of updates --- .../java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index f65a5725121..6f358d49ed1 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -84,6 +84,10 @@ public static void beforeClass() throws IOException { RestHighLevelClient elasticsearchHighLevelRestClient = ElasticsearchRestClientFactory.createElasticsearchHighLevelRestClient( "http", embeddedElastic.getHost() + ":" + embeddedElastic.getMappedPort(9200), "", ""); + /* As of 2023-08-10, HAPI FHIR sets SubscriptionConstants.MAX_SUBSCRIPTION_RESULTS to 50000 + which is in excess of elastic's default max_result_window. If MAX_SUBSCRIPTION_RESULTS is changed + to a value <= 10000, the following will no longer be necessary. - dotasek + */ PutIndexTemplateRequest putIndexTemplateRequest = new PutIndexTemplateRequest("hapi_fhir_template"); putIndexTemplateRequest.patterns(List.of("*")); Settings settings = Settings.builder().put("index.max_result_window", 50000).build(); From 69ff8c4d0675ba88521b6050e0975634381de7f4 Mon Sep 17 00:00:00 2001 From: dotasek Date: Thu, 17 Aug 2023 09:54:46 -0400 Subject: [PATCH 188/192] Bump to HAPI 6.8.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e84aeed6d12..3b382774444 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.8.0-SNAPSHOT + 6.8.0 hapi-fhir-jpaserver-starter From b88ffdada00cb16d19e9dad68289cd07d1473f88 Mon Sep 17 00:00:00 2001 From: dotasek Date: Thu, 17 Aug 2023 13:02:02 -0400 Subject: [PATCH 189/192] Fix breakages due to https://github.com/hapifhir/hapi-fhir/pull/5180 --- .../ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java | 5 ++--- .../ca/uhn/fhir/jpa/starter/cr/StarterCrDstu3Config.java | 2 +- .../java/ca/uhn/fhir/jpa/starter/cr/StarterCrR4Config.java | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 33b498b8507..7a1934fdfef 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -9,7 +9,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.support.IValidationSupport; -import ca.uhn.fhir.cr.config.CrProviderLoader; + import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.jpa.api.IDaoRegistry; import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; @@ -111,8 +111,7 @@ public CachingValidationSupport validationSupportChain(JpaValidationSupportChain @Autowired private ConfigurableEnvironment configurableEnvironment; - @Autowired(required=false) - private CrProviderLoader crProviderLoader; + /** * Customize the default/max page sizes for search results. You can set these however diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrDstu3Config.java b/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrDstu3Config.java index 9efc08645b9..06d95f4dd1e 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrDstu3Config.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrDstu3Config.java @@ -1,6 +1,6 @@ package ca.uhn.fhir.jpa.starter.cr; -import ca.uhn.fhir.cr.config.CrDstu3Config; +import ca.uhn.fhir.cr.config.dstu3.CrDstu3Config; import ca.uhn.fhir.jpa.starter.annotations.OnDSTU3Condition; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrR4Config.java b/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrR4Config.java index a97cea7835f..586a32499e5 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrR4Config.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/cr/StarterCrR4Config.java @@ -1,6 +1,6 @@ package ca.uhn.fhir.jpa.starter.cr; -import ca.uhn.fhir.cr.config.CrR4Config; +import ca.uhn.fhir.cr.config.r4.CrR4Config; import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Import; From 37a9317355a96fb438d6d9ba027bd34ada3d9db6 Mon Sep 17 00:00:00 2001 From: Jens Kristian Villadsen Date: Tue, 22 Aug 2023 20:14:43 +0200 Subject: [PATCH 190/192] Feature/using package installer spec (#577) * Adjusting to HAPI core classes * Added example as default * Commented the example IG out again --- .../uhn/fhir/jpa/starter/AppProperties.java | 37 ++----------------- .../jpa/starter/common/StarterJpaConfig.java | 15 ++++---- src/main/resources/application.yaml | 11 +++--- src/test/resources/application.yaml | 3 +- 4 files changed, 20 insertions(+), 46 deletions(-) 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 ec922de22ce..c8a9f639c9e 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -4,6 +4,7 @@ import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.jpa.api.config.JpaStorageSettings.ClientIdStrategyEnum; import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel; +import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; import ca.uhn.fhir.rest.api.EncodingEnum; import org.hl7.fhir.r4.model.Bundle; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -74,7 +75,7 @@ public class AppProperties { private Partitioning partitioning = null; private Boolean install_transitive_ig_dependencies = true; private Boolean reload_existing_implementationguides = false; - private Map implementationGuides = null; + private Map implementationGuides = null; private String staticLocation = null; @@ -148,11 +149,11 @@ public void setDefer_indexing_for_codesystems_of_size(Integer defer_indexing_for this.defer_indexing_for_codesystems_of_size = defer_indexing_for_codesystems_of_size; } - public Map getImplementationGuides() { + public Map getImplementationGuides() { return implementationGuides; } - public void setImplementationGuides(Map implementationGuides) { + public void setImplementationGuides(Map implementationGuides) { this.implementationGuides = implementationGuides; } @@ -696,36 +697,6 @@ public void setRefuse_to_fetch_third_party_urls(Boolean refuse_to_fetch_third_pa } } - public static class ImplementationGuide - { - private String url; - private String name; - private String version; - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - } public static class Validation { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 7a1934fdfef..7276777b13d 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -76,7 +76,6 @@ import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; - import java.util.*; import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR; @@ -194,13 +193,15 @@ public IPackageInstallerSvc packageInstaller(AppProperties appProperties, JobDef jobDefinitionRegistry.addJobDefinitionIfNotRegistered(reindexJobParametersJobDefinition); if (appProperties.getImplementationGuides() != null) { - Map guides = appProperties.getImplementationGuides(); - for (Map.Entry guide : guides.entrySet()) { - PackageInstallationSpec packageInstallationSpec = new PackageInstallationSpec().setPackageUrl(guide.getValue().getUrl()).setName(guide.getValue().getName()).setVersion(guide.getValue().getVersion()).setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL); - packageInstallationSpec.setReloadExisting(appProperties.getReload_existing_implementationguides()); + Map guides = appProperties.getImplementationGuides(); + for (Map.Entry guidesEntry : guides.entrySet()) { + PackageInstallationSpec packageInstallationSpec = guidesEntry.getValue(); if (appProperties.getInstall_transitive_ig_dependencies()) { - packageInstallationSpec.setFetchDependencies(true); - packageInstallationSpec.setDependencyExcludes(List.of("hl7.fhir.r2.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core", "hl7.fhir.r5.core")); + + packageInstallationSpec.addDependencyExclude("hl7.fhir.r2.core") + .addDependencyExclude("hl7.fhir.r3.core") + .addDependencyExclude("hl7.fhir.r4.core") + .addDependencyExclude("hl7.fhir.r5.core"); } packageInstallerSvc.install(packageInstallationSpec); } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index a38c9c2ef8b..018000821cc 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -77,14 +77,15 @@ hapi: # install_transitive_ig_dependencies: true ### tells the server whether to attempt to load IG resources that are already present # reload_existing_implementationGuides : false - # implementationguides: + #implementationguides: ### example from registry (packages.fhir.org) - # swiss: - # name: swiss.mednet.fhir - # version: 0.8.0 + # swiss: + # name: swiss.mednet.fhir + # version: 0.8.0 + # reloadExisting : false # example not from registry # ips_1_0_0: - # url: https://build.fhir.org/ig/HL7/fhir-ips/package.tgz + # packageUrl: https://build.fhir.org/ig/HL7/fhir-ips/package.tgz # name: hl7.fhir.uv.ips # version: 1.0.0 # supported_resource_types: diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml index 89229c9f0a1..9f473c574d8 100644 --- a/src/test/resources/application.yaml +++ b/src/test/resources/application.yaml @@ -64,9 +64,10 @@ hapi: # swiss: # name: swiss.mednet.fhir # version: 0.8.0 + # reloadExisting : false # example not from registry # ips_1_0_0: - # url: https://build.fhir.org/ig/HL7/fhir-ips/package.tgz + # packageUrl: https://build.fhir.org/ig/HL7/fhir-ips/package.tgz # name: hl7.fhir.uv.ips # version: 1.0.0 # supported_resource_types: From 63c4825d569b070ae2f47b8fb5cb96a647c2391a Mon Sep 17 00:00:00 2001 From: Husam Nujaim <60360833+HussamNujaim@users.noreply.github.com> Date: Sun, 3 Sep 2023 01:15:10 +0200 Subject: [PATCH 191/192] Fixing some typos in README.md --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index dbb57406e64..0184cc5b271 100644 --- a/README.md +++ b/README.md @@ -235,7 +235,7 @@ Server will then be accessible at http://localhost:8080/ and eg. http://localhos ```bash mvn clean package spring-boot:repackage -Pboot && java -jar target/ROOT.war ``` -Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg. +Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust your overlay configuration in the application.yaml to eg. ```yaml tester: @@ -250,7 +250,7 @@ Server will then be accessible at http://localhost:8080/ and eg. http://localhos ```bash mvn clean package com.google.cloud.tools:jib-maven-plugin:dockerBuild -Dimage=distroless-hapi && docker run -p 8080:8080 distroless-hapi ``` -Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg. +Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust your overlay configuration in the application.yaml to eg. ```yaml tester: @@ -266,7 +266,7 @@ Server will then be accessible at http://localhost:8080/ and eg. http://localhos ```bash ./build-docker-image.sh && docker run -p 8080:8080 hapi-fhir/hapi-fhir-jpaserver-starter:latest ``` -Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust you overlay configuration in the application.yaml to eg. +Server will then be accessible at http://localhost:8080/ and eg. http://localhost:8080/fhir/metadata. Remember to adjust your overlay configuration in the application.yaml to eg. ```yaml tester: @@ -307,7 +307,7 @@ spring: # Then comment all hibernate.search.backend.* ``` -Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. +Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicitly skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. ### Microsoft SQL Server configuration @@ -322,14 +322,14 @@ spring: driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver ``` -Also, make sure you are not setting the Hibernate dialect explicitly, in other words remove any lines similar to: +Also, make sure you are not setting the Hibernate dialect explicitly, in other words, remove any lines similar to: ``` hibernate.dialect: {some none Microsoft SQL dialect} ``` -Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicity skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. +Because the integration tests within the project rely on the default H2 database configuration, it is important to either explicitly skip the integration tests during the build process, i.e., `mvn install -DskipTests`, or delete the tests altogether. Failure to skip or delete the tests once you've configured PostgreSQL for the datasource.driver, datasource.url, and hibernate.dialect as outlined above will result in build errors and compilation failure. NOTE: MS SQL Server by default uses a case-insensitive codepage. This will cause errors with some operations - such as when expanding case-sensitive valuesets (UCUM) as there are unique indexes defined on the terminology tables for codes. @@ -373,7 +373,7 @@ Again, browse to the following link to use the server (note that the port 8080 m [http://localhost:8080/](http://localhost:8080/) -You will then be able access the JPA server e.g. using http://localhost:8080/fhir/metadata. +You will then be able to access the JPA server e.g. using http://localhost:8080/fhir/metadata. If you would like it to be hosted at eg. hapi-fhir-jpaserver, eg. http://localhost:8080/hapi-fhir-jpaserver/ or http://localhost:8080/hapi-fhir-jpaserver/fhir/metadata - then rename the WAR file to ```hapi-fhir-jpaserver.war``` and adjust the overlay configuration accordingly e.g. @@ -390,7 +390,7 @@ If you would like it to be hosted at eg. hapi-fhir-jpaserver, eg. http://localho ## Deploy with docker compose -Docker compose is a simple option to build and deploy container. To deploy with docker compose, you should build the project +Docker compose is a simple option to build and deploy containers. To deploy with docker compose, you should build the project with `mvn clean install` and then bring up the containers with `docker-compose up -d --build`. The server can be reached at http://localhost:8080/. From f7e2fb9a9e8830e9f245fea2eb35ab590de7b555 Mon Sep 17 00:00:00 2001 From: Hank Wallace Date: Sat, 20 Jan 2024 18:04:36 -0500 Subject: [PATCH 192/192] Adds our banner to the web UI --- src/main/webapp/WEB-INF/templates/tmpl-banner.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/WEB-INF/templates/tmpl-banner.html b/src/main/webapp/WEB-INF/templates/tmpl-banner.html index abbe718db63..cafc016f18f 100644 --- a/src/main/webapp/WEB-INF/templates/tmpl-banner.html +++ b/src/main/webapp/WEB-INF/templates/tmpl-banner.html @@ -3,18 +3,18 @@

- Sample Logo + Elimu Informatics
- - + +
Warning!

- +