From f4db064f92114112fb7526b9275ef4c5653b4e1b Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Mon, 16 Feb 2026 11:55:17 +0100 Subject: [PATCH 1/6] feat: add BinaryStorageInterceptorRegistrar for conditional interceptor registration, register against JPA interceptor service to also be triggered on dao level (e.g. bulk export) --- .../BinaryStorageInterceptorRegistrar.java | 41 +++++++++++++++++++ .../jpa/starter/common/StarterJpaConfig.java | 3 -- 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/common/BinaryStorageInterceptorRegistrar.java diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/BinaryStorageInterceptorRegistrar.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/BinaryStorageInterceptorRegistrar.java new file mode 100644 index 0000000..79b5134 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/BinaryStorageInterceptorRegistrar.java @@ -0,0 +1,41 @@ +package ca.uhn.fhir.jpa.starter.common; + +import ca.uhn.fhir.IHapiBootOrder; +import ca.uhn.fhir.interceptor.api.IInterceptorService; +import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor; +import ca.uhn.fhir.jpa.starter.AppProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@Component +public class BinaryStorageInterceptorRegistrar { + private static final Logger ourLog = LoggerFactory.getLogger(BinaryStorageInterceptorRegistrar.class); + + private final IInterceptorService myInterceptorService; + private final BinaryStorageInterceptor myBinaryStorageInterceptor; + private final AppProperties myAppProperties; + + public BinaryStorageInterceptorRegistrar( + IInterceptorService theInterceptorService, + BinaryStorageInterceptor theBinaryStorageInterceptor, + AppProperties theAppProperties) { + myInterceptorService = theInterceptorService; + myBinaryStorageInterceptor = theBinaryStorageInterceptor; + myAppProperties = theAppProperties; + } + + @EventListener(classes = {ContextRefreshedEvent.class}) + @Order(IHapiBootOrder.REGISTER_INTERCEPTORS) + public void register() { + if (!myAppProperties.getBinary_storage_enabled()) { + ourLog.debug("Binary storage disabled; skipping BinaryStorageInterceptor registration"); + return; + } + ourLog.info("Registering BinaryStorageInterceptor with JPA interceptor service"); + myInterceptorService.registerInterceptor(myBinaryStorageInterceptor); + } +} 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 1e3bc6a..86e4793 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 @@ -15,7 +15,6 @@ 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; -import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor; import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider; import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil; import ca.uhn.fhir.jpa.config.util.ResourceCountCacheUtil; @@ -323,7 +322,6 @@ public class StarterJpaConfig { Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, - BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, @@ -455,7 +453,6 @@ public class StarterJpaConfig { // Binary Storage if (appProperties.getBinary_storage_enabled() && binaryAccessProvider.isPresent()) { fhirServer.registerProvider(binaryAccessProvider.get()); - fhirServer.registerInterceptor(binaryStorageInterceptor); } // Validation From a1fc68b4f07d5b863fc14af331e5c86f4254b8c9 Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Mon, 16 Feb 2026 11:58:57 +0100 Subject: [PATCH 2/6] removed deprecated setting of setInlineResourceTextBelowSize --- .../fhir/jpa/starter/common/FhirServerConfigCommon.java | 7 +------ 1 file changed, 1 insertion(+), 6 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 88c5874..0c5bb58 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 @@ -227,11 +227,6 @@ public class FhirServerConfigCommon { jpaStorageSettings.setLastNEnabled(true); } - Integer inlineResourceThreshold = resolveInlineResourceThreshold(appProperties); - if (inlineResourceThreshold != null && inlineResourceThreshold != 0) { - jpaStorageSettings.setInlineResourceTextBelowSize(inlineResourceThreshold); - } - jpaStorageSettings.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled()); jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource()); @@ -397,7 +392,7 @@ public class FhirServerConfigCommon { } private Integer resolveInlineResourceThreshold(AppProperties appProperties) { - Integer inlineResourceThreshold = appProperties.getInline_resource_storage_below_size(); + Integer inlineResourceThreshold = appProperties.getBinary_storage_minimum_binary_size(); if (inlineResourceThreshold == null && appProperties.getBinary_storage_mode() == AppProperties.BinaryStorageMode.FILESYSTEM) { return DEFAULT_FILESYSTEM_INLINE_THRESHOLD; From 7d482e30c954bcbdd8bdecfd8f6a74269b851896 Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Mon, 16 Feb 2026 11:59:08 +0100 Subject: [PATCH 3/6] refactor: rename inline_resource_storage_below_size to binary_storage_minimum_binary_size in AppProperties and application.yaml --- .../java/ca/uhn/fhir/jpa/starter/AppProperties.java | 10 +++++----- src/main/resources/application.yaml | 8 ++++---- 2 files changed, 9 insertions(+), 9 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 085b15f..31e7828 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java @@ -69,7 +69,7 @@ public class AppProperties { private BinaryStorageMode binary_storage_mode = BinaryStorageMode.DATABASE; private String binary_storage_filesystem_base_directory; - private Integer inline_resource_storage_below_size; + private Integer binary_storage_minimum_binary_size; private Boolean bulk_export_enabled = false; private Boolean bulk_import_enabled = false; private Boolean default_pretty_print = true; @@ -511,12 +511,12 @@ public class AppProperties { this.binary_storage_filesystem_base_directory = binary_storage_filesystem_base_directory; } - public Integer getInline_resource_storage_below_size() { - return inline_resource_storage_below_size; + public Integer getBinary_storage_minimum_binary_size() { + return binary_storage_minimum_binary_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 void setBinary_storage_minimum_binary_size(Integer binary_storage_minimum_binary_size) { + this.binary_storage_minimum_binary_size = binary_storage_minimum_binary_size; } public Boolean getBulk_export_enabled() { diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 07e3961..32aa6fa 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -424,12 +424,12 @@ hapi: # validation: # requests_enabled: true # responses_enabled: true - # binary_storage_enabled: true - # binary_storage_mode: FILESYSTEM - # binary_storage_filesystem_base_directory: /binstore + binary_storage_enabled: true + binary_storage_mode: FILESYSTEM + binary_storage_filesystem_base_directory: /binstore # When binary_storage_mode is FILESYSTEM and this value is not set, # the starter defaults to 102400 bytes so smaller binaries stay inline. - inline_resource_storage_below_size: 4000 + binary_storage_minimum_binary_size: 4000 # ------------------------------------------------------------------------------- # P. Remote Terminology Service (disabled by default) From f01b86e6c0c3e7d9c3911a6c8fad43dd5aa4e1bd Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Mon, 16 Feb 2026 11:59:13 +0100 Subject: [PATCH 4/6] refactor: rename inline_resource_storage_below_size to binary_storage_minimum_binary_size in AppProperties and application.yaml --- .../common/FhirServerConfigCommonBinaryStorageTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommonBinaryStorageTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommonBinaryStorageTest.java index bad6417..58dad82 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommonBinaryStorageTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommonBinaryStorageTest.java @@ -48,7 +48,7 @@ class FhirServerConfigCommonBinaryStorageTest { void filesystemModeHonoursExplicitMinimum() throws Exception { AppProperties props = new AppProperties(); props.setBinary_storage_mode(AppProperties.BinaryStorageMode.FILESYSTEM); - props.setInline_resource_storage_below_size(4096); + props.setBinary_storage_minimum_binary_size(4096); Path baseDir = tempDir.resolve("fs-min-explicit"); Files.createDirectories(baseDir); props.setBinary_storage_filesystem_base_directory(baseDir.toString()); @@ -62,7 +62,7 @@ class FhirServerConfigCommonBinaryStorageTest { void filesystemModeSupportsZeroMinimumWhenExplicit() throws Exception { AppProperties props = new AppProperties(); props.setBinary_storage_mode(AppProperties.BinaryStorageMode.FILESYSTEM); - props.setInline_resource_storage_below_size(0); + props.setBinary_storage_minimum_binary_size(0); Path baseDir = tempDir.resolve("fs-zero"); Files.createDirectories(baseDir); props.setBinary_storage_filesystem_base_directory(baseDir.toString()); From d45bf8027e995e3f1982dbedd9bba599be2fda63 Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Mon, 16 Feb 2026 12:17:14 +0100 Subject: [PATCH 5/6] removed testing config --- 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 32aa6fa..3e30ade 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -424,9 +424,9 @@ hapi: # validation: # requests_enabled: true # responses_enabled: true - binary_storage_enabled: true - binary_storage_mode: FILESYSTEM - binary_storage_filesystem_base_directory: /binstore + # binary_storage_enabled: true + # binary_storage_mode: FILESYSTEM + # binary_storage_filesystem_base_directory: /binstore # When binary_storage_mode is FILESYSTEM and this value is not set, # the starter defaults to 102400 bytes so smaller binaries stay inline. binary_storage_minimum_binary_size: 4000 From eaabef8be02556be85606be9850cb89457a31bd0 Mon Sep 17 00:00:00 2001 From: Patrick Werner Date: Mon, 16 Feb 2026 12:27:26 +0100 Subject: [PATCH 6/6] refactor: update inline_resource_storage_below_size to binary_storage_minimum_binary_size in BinaryStorageIntegrationTest --- .../ca/uhn/fhir/jpa/starter/BinaryStorageIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/BinaryStorageIntegrationTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/BinaryStorageIntegrationTest.java index 54ab520..da21a14 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/BinaryStorageIntegrationTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/BinaryStorageIntegrationTest.java @@ -294,7 +294,7 @@ class BinaryStorageFilesystemDefaultIT extends BaseBinaryStorageIntegrationTest "hapi.fhir.binary_storage_enabled=true", "hapi.fhir.binary_storage_mode=FILESYSTEM", "hapi.fhir.binary_storage_filesystem_base_directory=target/test-binary-storage/filesystem-custom", - "hapi.fhir.inline_resource_storage_below_size=32768" + "hapi.fhir.binary_storage_minimum_binary_size=32768" } ) class BinaryStorageFilesystemCustomThresholdIT extends BaseBinaryStorageIntegrationTest {