diff --git a/README.md b/README.md index 57cd00e..a377bf1 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/pom.xml b/pom.xml index f8e4aac..69aef16 100644 --- a/pom.xml +++ b/pom.xml @@ -21,11 +21,10 @@ 8 - 2.5.6 - 3.6.3 + 3.8.3 war @@ -57,30 +56,22 @@ mysql mysql-connector-java - 8.0.25 - org.postgresql postgresql - 42.2.23 - - - - - - - - - - - org.simplejavamail simple-java-mail + + + jakarta.annotation + jakarta.annotation-api + + @@ -89,6 +80,12 @@ hapi-fhir-base ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-jpaserver-subscription + ${project.version} + @@ -163,7 +160,7 @@ org.yaml snakeyaml - 1.29 + 1.30 @@ -196,7 +193,7 @@ org.webjars bootstrap - 3.4.1 + 5.1.3 org.webjars 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 87b4181..1118df7 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.ConfigurationProperties; 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 @@ -24,6 +21,7 @@ public class AppProperties { private Boolean cql_enabled = false; private Boolean openapi_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; @@ -68,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; @@ -76,6 +75,10 @@ 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; + private List local_base_urls = new ArrayList<>(); + public Boolean getOpenapi_enabled() { return openapi_enabled; } @@ -196,7 +199,11 @@ public class AppProperties { 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; } @@ -213,7 +220,15 @@ public class AppProperties { 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; } @@ -455,7 +470,15 @@ public class AppProperties { 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; } @@ -489,6 +512,26 @@ public class AppProperties { 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 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/BaseJpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java index 3e61743..a41e399 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -384,6 +384,9 @@ public class BaseJpaRestfulServer extends RestfulServer { 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(); @@ -410,8 +413,8 @@ public class BaseJpaRestfulServer extends RestfulServer { 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/ElasticsearchConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/ElasticsearchConfig.java new file mode 100644 index 0000000..fd27e84 --- /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/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java index b055252..fb99b7f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -14,6 +14,8 @@ 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 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; @@ -23,8 +25,6 @@ import org.springframework.context.annotation.Primary; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; -import java.util.Optional; - /** * This is the primary configuration file for the example server */ @@ -65,7 +65,7 @@ public class FhirServerConfigCommon { 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"); } @@ -119,6 +119,8 @@ public class FhirServerConfigCommon { } retVal.setFilterParameterEnabled(appProperties.getFilter_search_enabled()); + retVal.setAdvancedLuceneIndexing(appProperties.getAdvanced_lucene_indexing()); + retVal.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls())); return retVal; } @@ -139,7 +141,7 @@ public class FhirServerConfigCommon { if(appProperties.getPartitioning().getAllow_references_across_partitions()) { retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.ALLOWED_UNQUALIFIED); } else { - retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.NOT_ALLOWED); + retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.NOT_ALLOWED); } } @@ -154,8 +156,8 @@ public class FhirServerConfigCommon { } @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()); @@ -172,7 +174,7 @@ public class FhirServerConfigCommon { } modelConfig.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); - + modelConfig.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); return modelConfig; } @@ -222,7 +224,7 @@ public class FhirServerConfigCommon { IMailSvc mailSvc = new MailSvc(mailConfig); IEmailSender emailSender = new EmailSenderImpl(mailSvc); - subscriptionDeliveryHandlerFactory.get().setEmailSender(emailSender); + subscriptionDeliveryHandlerFactory.ifPresent(theSubscriptionDeliveryHandlerFactory -> theSubscriptionDeliveryHandlerFactory.setEmailSender(emailSender)); return emailSender; } 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 633dc14..074d5b7 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigDstu3.java @@ -2,9 +2,7 @@ package ca.uhn.fhir.jpa.starter; 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; import ca.uhn.fhir.jpa.starter.cql.StarterCqlDstu3Config; import javax.annotation.PostConstruct; @@ -23,7 +21,7 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @Configuration @Conditional(OnDSTU3Condition.class) -@Import(StarterCqlDstu3Config.class) +@Import({StarterCqlDstu3Config.class, ElasticsearchConfig.class}) public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { @Autowired @@ -77,6 +75,7 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, myConfigurableListableBeanFactory)); + return retVal; } @@ -87,26 +86,4 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { retVal.setEntityManagerFactory(entityManagerFactory); return retVal; } - - @Bean() - public ElasticsearchSvcImpl elasticsearchSvc(PartitionSettings thePartitionSetings) { - 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]; - }else { - elasticsearchProtocol = "http"; - elasticsearchHost = elasticsearchUrl; - } - String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); - String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(thePartitionSetings, 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 6b9e823..206ad80 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR4.java @@ -2,25 +2,26 @@ package ca.uhn.fhir.jpa.starter; 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; 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.*; +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; -import javax.annotation.PostConstruct; -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; - @Configuration @Conditional(OnR4Condition.class) -@Import(StarterCqlR4Config.class) +@Import({StarterCqlR4Config.class, ElasticsearchConfig.class}) public class FhirServerConfigR4 extends BaseJavaConfigR4 { @Autowired @@ -84,25 +85,4 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 { return retVal; } - @Bean() - public ElasticsearchSvcImpl elasticsearchSvc(PartitionSettings thePartitionSetings) { - 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]; - }else { - elasticsearchProtocol = "http"; - elasticsearchHost = elasticsearchUrl; - } - String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); - String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(thePartitionSetings, 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 6f4040b..6d6d64f 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigR5.java @@ -2,26 +2,25 @@ package ca.uhn.fhir.jpa.starter; 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; +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; -import javax.annotation.PostConstruct; -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; - @Configuration @Conditional(OnR5Condition.class) +@Import({ElasticsearchConfig.class}) public class FhirServerConfigR5 extends BaseJavaConfigR5 { @Autowired @@ -85,26 +84,4 @@ public class FhirServerConfigR5 extends BaseJavaConfigR5 { return retVal; } - @Bean() - public ElasticsearchSvcImpl elasticsearchSvc(PartitionSettings thePartitionSetings) { - if (Boolean.TRUE.equals(EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment))) { - String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment); - String elasticsearchHost; - String elasticsearchProtocol = EnvironmentHelper.getElasticsearchServerProtocol(configurableEnvironment); - if (elasticsearchUrl.startsWith("http")) { - elasticsearchProtocol = elasticsearchUrl.split("://")[0]; - elasticsearchHost = elasticsearchUrl.split("://")[1]; - } else { - elasticsearchProtocol = "http"; - elasticsearchHost = elasticsearchUrl; - } - String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment); - String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment); - return new ElasticsearchSvcImpl(thePartitionSetings, elasticsearchProtocol, elasticsearchHost, elasticsearchUsername, elasticsearchPassword); - } else { - return null; - } - } - - } diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 1ad5256..7ea0ccc 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,4 +1,10 @@ spring: + main: + allow-circular-references: true + flyway: + enabled: false + check-location: false + baselineOnMigrate: true datasource: url: 'jdbc:h2:file:./target/database/h2' #url: jdbc:h2:mem:test_mem @@ -10,13 +16,14 @@ spring: # database connection pool size hikari: maximum-pool-size: 10 - flyway: - check-location: false - baselineOnMigrate: true 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 @@ -77,7 +84,9 @@ hapi: # enable_repository_validating_interceptor: false # enable_index_missing_fields: false # enable_index_contained_resource: false - # enforce_referential_integrity_on_delete: 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 # expunge_enabled: true @@ -87,6 +96,9 @@ hapi: # filter_search_enabled: true # graphql_enabled: true # narrative_enabled: true + # mdm_enabled: true +# local_base_urls: +# - https://hapi.fhir.org/baseR4 mdm_enabled: true # partitioning: # allow_references_across_partitions: false @@ -102,7 +114,11 @@ hapi: search-coord-max-pool-size: 100 search-coord-queue-capacity: 200 - # logger: + # 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}] @@ -145,6 +161,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 24dfada..1387354 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 @@ import org.testcontainers.elasticsearch.ElasticsearchContainer; "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'", 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 0b408de..964fae2 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 @@ import static org.junit.jupiter.api.Assertions.assertEquals; "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 91cb4ba..b4ca6c3 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 @@ import static org.junit.jupiter.api.Assertions.assertEquals; "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/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index 6d99523..7b05487 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 @@ class ExampleServerR4IT { } } + @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 { 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 6a7fc52..055d1ab 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 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; "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 d8ae7cf..29af5e7 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 @@ import static org.junit.jupiter.api.Assertions.assertEquals; "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 { diff --git a/src/test/resources/application-integrationtest.yaml b/src/test/resources/application-integrationtest.yaml index f311891..3ab7240 100644 --- a/src/test/resources/application-integrationtest.yaml +++ b/src/test/resources/application-integrationtest.yaml @@ -35,6 +35,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