diff --git a/Dockerfile b/Dockerfile
index 806c542288a..7fefc679d3e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,7 @@
FROM docker.io/library/maven:3.9.9-eclipse-temurin-17 AS build-hapi
WORKDIR /tmp/hapi-fhir-jpaserver-starter
-ARG OPENTELEMETRY_JAVA_AGENT_VERSION=1.33.3
+ARG OPENTELEMETRY_JAVA_AGENT_VERSION=2.13.1
RUN curl -LSsO https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${OPENTELEMETRY_JAVA_AGENT_VERSION}/opentelemetry-javaagent.jar
COPY pom.xml .
diff --git a/pom.xml b/pom.xml
index 356ab2cf39a..44166e0e4dd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@
ca.uhn.hapi.fhir
hapi-fhir
- 8.2.0
+ 8.3.7-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 0095b538909..3f7e19b81f5 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
@@ -4,7 +4,7 @@
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings.ClientIdStrategyEnum;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings.IdStrategyEnum;
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
-import ca.uhn.fhir.jpa.packages.PackageInstallationSpec;
+import ca.uhn.fhir.jpa.starter.ig.ExtendedPackageInstallationSpec;
import ca.uhn.fhir.rest.api.EncodingEnum;
import org.hl7.fhir.r4.model.Bundle;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -83,7 +83,9 @@ public class AppProperties {
private Partitioning partitioning = null;
private Boolean validate_resource_status_for_package_upload = true;
private Boolean install_transitive_ig_dependencies = true;
- private Map implementationGuides = null;
+
+ private List install_additional_resources_from_ig_folders = new ArrayList<>();
+ private Map implementationGuides = null;
private String custom_content_path = null;
private String app_content_path = null;
private Boolean lastn_enabled = false;
@@ -148,11 +150,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;
}
@@ -685,6 +687,15 @@ public void setResource_dbhistory_enabled(Boolean resource_dbhistory_enabled) {
this.resource_dbhistory_enabled = resource_dbhistory_enabled;
}
+ public List getInstall_additional_resources_from_ig_folders() {
+ return install_additional_resources_from_ig_folders;
+ }
+
+ public void setInstall_additional_resources_from_ig_folders(
+ List install_additional_resources_from_ig_folders) {
+ this.install_additional_resources_from_ig_folders = install_additional_resources_from_ig_folders;
+ }
+
public Boolean getPre_expand_value_sets() {
return this.pre_expand_value_sets;
}
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 e9f3549c518..76fdb6dd937 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
@@ -291,11 +291,6 @@ public PartitionSettings partitionSettings(AppProperties appProperties) {
return retVal;
}
- @Bean
- public PartitionModeConfigurer partitionModeConfigurer() {
- return new PartitionModeConfigurer();
- }
-
@Primary
@Bean
public HibernatePropertiesProvider jpaStarterDialectProvider(
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/OnPartitionModeEnabled.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/OnPartitionModeEnabled.java
new file mode 100644
index 00000000000..b695babe544
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/OnPartitionModeEnabled.java
@@ -0,0 +1,18 @@
+package ca.uhn.fhir.jpa.starter.common;
+
+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 OnPartitionModeEnabled implements Condition {
+ @Override
+ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ var appProperties = Binder.get(context.getEnvironment())
+ .bind("hapi.fhir", AppProperties.class)
+ .orElse(null);
+ if (appProperties == null) return false;
+ return appProperties.getPartitioning() != null;
+ }
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/PartitionModeConfigurer.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/PartitionModeConfigurer.java
index c83e8fccb89..dbf5f0f0d49 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/PartitionModeConfigurer.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/PartitionModeConfigurer.java
@@ -1,6 +1,5 @@
package ca.uhn.fhir.jpa.starter.common;
-import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.interceptor.PatientIdPartitionInterceptor;
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.partition.PartitionManagementProvider;
@@ -9,48 +8,36 @@
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor;
import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy;
-import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.stereotype.Component;
+@Component
+@Conditional({OnPartitionModeEnabled.class})
public class PartitionModeConfigurer {
private static final Logger ourLog = LoggerFactory.getLogger(PartitionModeConfigurer.class);
- @Autowired
- private AppProperties myAppProperties;
-
- @Autowired
- private FhirContext myFhirContext;
-
- @Autowired
- private ISearchParamExtractor mySearchParamExtractor;
-
- @Autowired
- private PartitionSettings myPartitionSettings;
-
- @Autowired
- private RestfulServer myRestfulServer;
-
- @Autowired
- private PartitionManagementProvider myPartitionManagementProvider;
-
- @PostConstruct
- public void start() {
- if (myAppProperties.getPartitioning() != null) {
- if (myAppProperties.getPartitioning().getPatient_id_partitioning_mode() == Boolean.TRUE) {
- ourLog.info("Partitioning mode enabled in: Patient ID partitioning mode");
- PatientIdPartitionInterceptor patientIdInterceptor =
- new PatientIdPartitionInterceptor(myFhirContext, mySearchParamExtractor, myPartitionSettings);
- myRestfulServer.registerInterceptor(patientIdInterceptor);
- myPartitionSettings.setUnnamedPartitionMode(true);
- } else if (myAppProperties.getPartitioning().getRequest_tenant_partitioning_mode() == Boolean.TRUE) {
- ourLog.info("Partitioning mode enabled in: Request tenant partitioning mode");
- myRestfulServer.registerInterceptor(new RequestTenantPartitionInterceptor());
- myRestfulServer.setTenantIdentificationStrategy(new UrlBaseTenantIdentificationStrategy());
- }
-
- myRestfulServer.registerProviders(myPartitionManagementProvider);
+ public PartitionModeConfigurer(
+ AppProperties myAppProperties,
+ ISearchParamExtractor mySearchParamExtractor,
+ PartitionSettings myPartitionSettings,
+ RestfulServer myRestfulServer,
+ PartitionManagementProvider myPartitionManagementProvider) {
+
+ var partitioning = myAppProperties.getPartitioning();
+ if (partitioning.getPatient_id_partitioning_mode()) {
+ ourLog.info("Partitioning mode enabled in: Patient ID partitioning mode");
+ var patientIdInterceptor = new PatientIdPartitionInterceptor(
+ myRestfulServer.getFhirContext(), mySearchParamExtractor, myPartitionSettings);
+ myRestfulServer.registerInterceptor(patientIdInterceptor);
+ myPartitionSettings.setUnnamedPartitionMode(true);
+ } else if (partitioning.getRequest_tenant_partitioning_mode()) {
+ ourLog.info("Partitioning mode enabled in: Request tenant partitioning mode");
+ myRestfulServer.registerInterceptor(new RequestTenantPartitionInterceptor());
+ myRestfulServer.setTenantIdentificationStrategy(new UrlBaseTenantIdentificationStrategy());
}
+
+ myRestfulServer.registerProviders(myPartitionManagementProvider);
}
}
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 386c503504f..86b33f5334f 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.FhirVersionEnum;
import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
+import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.IDaoRegistry;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
import ca.uhn.fhir.jpa.api.config.ThreadPoolFactoryConfig;
@@ -20,6 +21,7 @@
import ca.uhn.fhir.jpa.config.util.ResourceCountCacheUtil;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
+import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.dao.search.HSearchSortHelperImpl;
import ca.uhn.fhir.jpa.dao.search.IHSearchSortHelper;
import ca.uhn.fhir.jpa.delete.ThreadSafeResourceDeleterSvc;
@@ -29,8 +31,9 @@
import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor;
import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider;
import ca.uhn.fhir.jpa.model.config.SubscriptionSettings;
+import ca.uhn.fhir.jpa.packages.AdditionalResourcesParser;
+import ca.uhn.fhir.jpa.packages.IHapiPackageCacheManager;
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
-import ca.uhn.fhir.jpa.packages.PackageInstallationSpec;
import ca.uhn.fhir.jpa.provider.DaoRegistryResourceSupportedSvc;
import ca.uhn.fhir.jpa.provider.DiffProvider;
import ca.uhn.fhir.jpa.provider.IJpaSystemProvider;
@@ -47,6 +50,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.ig.ExtendedPackageInstallationSpec;
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper;
import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor;
@@ -55,6 +59,7 @@
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.narrative2.NullNarrativeGenerator;
import ca.uhn.fhir.rest.api.IResourceSupportedSvc;
+import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import ca.uhn.fhir.rest.openapi.OpenApiInterceptor;
import ca.uhn.fhir.rest.server.ApacheProxyAddressStrategy;
import ca.uhn.fhir.rest.server.ETagSupportEnum;
@@ -74,6 +79,7 @@
import ca.uhn.fhir.validation.ResultSeverityEnum;
import com.google.common.base.Strings;
import jakarta.persistence.EntityManagerFactory;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@@ -93,11 +99,8 @@
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.web.cors.CorsConfiguration;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.io.IOException;
+import java.util.*;
import javax.sql.DataSource;
import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR;
@@ -207,14 +210,18 @@ public LoggingInterceptor loggingInterceptor(AppProperties appProperties) {
public IPackageInstallerSvc packageInstaller(
AppProperties appProperties,
IPackageInstallerSvc packageInstallerSvc,
- Batch2JobRegisterer batch2JobRegisterer) {
+ Batch2JobRegisterer batch2JobRegisterer,
+ FhirContext fhirContext,
+ TransactionProcessor transactionProcessor,
+ IHapiPackageCacheManager iHapiPackageCacheManager)
+ throws IOException {
batch2JobRegisterer.start();
if (appProperties.getImplementationGuides() != null) {
- Map guides = appProperties.getImplementationGuides();
- for (Map.Entry guidesEntry : guides.entrySet()) {
- PackageInstallationSpec packageInstallationSpec = guidesEntry.getValue();
+ Map guides = appProperties.getImplementationGuides();
+ for (Map.Entry guidesEntry : guides.entrySet()) {
+ ExtendedPackageInstallationSpec packageInstallationSpec = guidesEntry.getValue();
if (appProperties.getInstall_transitive_ig_dependencies()) {
packageInstallationSpec
@@ -223,7 +230,22 @@ public IPackageInstallerSvc packageInstaller(
.addDependencyExclude("hl7.fhir.r4.core")
.addDependencyExclude("hl7.fhir.r5.core");
}
+
packageInstallerSvc.install(packageInstallationSpec);
+
+ Set extraResources = packageInstallationSpec.getAdditionalResourceFolders();
+ packageInstallationSpec.setPackageContents(iHapiPackageCacheManager
+ .loadPackageContents(packageInstallationSpec.getName(), packageInstallationSpec.getVersion())
+ .getBytes());
+
+ if (extraResources != null && !extraResources.isEmpty()) {
+ IBaseBundle transaction = AdditionalResourcesParser.bundleAdditionalResources(
+ extraResources, packageInstallationSpec, fhirContext);
+ transactionProcessor.transaction(
+ new SystemRequestDetails().setRequestPartitionId(RequestPartitionId.defaultPartition()),
+ transaction,
+ false);
+ }
}
}
return packageInstallerSvc;
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ig/ExtendedPackageInstallationSpec.java b/src/main/java/ca/uhn/fhir/jpa/starter/ig/ExtendedPackageInstallationSpec.java
new file mode 100644
index 00000000000..73dc819779e
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/ig/ExtendedPackageInstallationSpec.java
@@ -0,0 +1,24 @@
+package ca.uhn.fhir.jpa.starter.ig;
+
+import ca.uhn.fhir.jpa.packages.PackageInstallationSpec;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import java.util.Set;
+
+public class ExtendedPackageInstallationSpec extends PackageInstallationSpec {
+
+ public Set getAdditionalResourceFolders() {
+ return additionalResourceFolders;
+ }
+
+ public void setAdditionalResourceFolders(Set additionalResourceFolders) {
+ this.additionalResourceFolders = additionalResourceFolders;
+ }
+
+ @Schema(
+ description =
+ "If resources are being installed individually, this is list provides the resource types to install. By default, all conformance resources will be installed.")
+ @JsonProperty("additionalResourceFolders")
+ private Set additionalResourceFolders;
+}
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
index d4df357603c..b96cbe4a9d1 100644
--- a/src/main/resources/application.yaml
+++ b/src/main/resources/application.yaml
@@ -166,10 +166,14 @@ hapi:
# reloadExisting: false
# installMode: STORE_AND_INSTALL
# example not from registry
- # ips_1_0_0:
- # packageUrl: https://build.fhir.org/ig/HL7/fhir-ips/package.tgz
- # name: hl7.fhir.uv.ips
- # version: 1.0.0
+ # ips_1_0_0:
+ # packageUrl: https://costateixeira.github.io/smart-ips-pilgrimage-fulltest/package.tgz
+ # name: smart.who.int.ips-pilgrimage-test
+ # version: 0.1.0
+ # installMode: STORE_AND_INSTALL
+ # additionalResourceFolders:
+ # - example
+ # - example2
# supported_resource_types:
# - Patient
# - Observation
@@ -236,11 +240,14 @@ hapi:
- https://unitsofmeasure.org/*
- http://loinc.org/*
- https://loinc.org/*
- # partitioning:
- # allow_references_across_partitions: false
- # partitioning_include_in_search_hashes: false
- # conditional_create_duplicate_identifiers_enabled: false
- # request_tenant_partitioning_mode: true
+ #partitioning:
+ # allow_references_across_partitions: true
+ # partitioning_include_in_search_hashes: true
+ # conditional_create_duplicate_identifiers_enabled: true
+ # patient-id-partitioning-mode: true
+ # request-tenant-partitioning-mode: true
+ # database-partition-mode-enabled: true
+ # default-partition-id: 0
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-