From 4bca6c7e84d1f2c1b965278cea30870dbd199929 Mon Sep 17 00:00:00 2001 From: elavy-harris <102183351+elavy-harris@users.noreply.github.com> Date: Wed, 29 Oct 2025 13:22:47 -0500 Subject: [PATCH 1/9] Include-TransactionDetails-in-STORAGE_TRANSACTION_PROCESSING --- .../ca/uhn/fhir/interceptor/api/Pointcut.java | 12 ++++++++-- .../TransactionPartitionProcessorTest.java | 4 +++- .../jpa/dao/BaseTransactionProcessor.java | 22 +++++++++---------- .../dao/TransactionPartitionProcessor.java | 11 ++++++---- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java index 4173bad4d0d..b838d05cb0c 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java @@ -1878,6 +1878,9 @@ public enum Pointcut implements IPointcut { * pulled out of the servlet request. This parameter is identical to the RequestDetails parameter above but will * only be populated when operating in a RestfulServer implementation. It is provided as a convenience. * + *
  • + * ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 8.6) + *
  • * *

    * Hooks must return an instance of ca.uhn.fhir.jpa.dao.TransactionPrePartitionResponse. @@ -1889,7 +1892,8 @@ public enum Pointcut implements IPointcut { "ca.uhn.fhir.jpa.dao.TransactionPrePartitionResponse", "ca.uhn.fhir.rest.api.server.RequestDetails", "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails", - "org.hl7.fhir.instance.model.api.IBaseBundle"), + "org.hl7.fhir.instance.model.api.IBaseBundle", + "ca.uhn.fhir.rest.api.server.storage.TransactionDetails"), /** * Storage Hook: @@ -1913,6 +1917,9 @@ public enum Pointcut implements IPointcut { * pulled out of the servlet request. This parameter is identical to the RequestDetails parameter above but will * only be populated when operating in a RestfulServer implementation. It is provided as a convenience. * + *

  • + * ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 8.6) + *
  • * *

    * Hooks should return void. @@ -1925,7 +1932,8 @@ public enum Pointcut implements IPointcut { void.class, "org.hl7.fhir.instance.model.api.IBaseBundle", "ca.uhn.fhir.rest.api.server.RequestDetails", - "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails"), + "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails", + "ca.uhn.fhir.rest.api.server.storage.TransactionDetails"), /** * Storage Hook: diff --git a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessorTest.java b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessorTest.java index 20e6a0f3b15..9bb93bb72ba 100644 --- a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessorTest.java +++ b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessorTest.java @@ -4,6 +4,7 @@ import ca.uhn.fhir.interceptor.executor.InterceptorService; import ca.uhn.fhir.jpa.dao.r5.FhirSystemDaoTransactionPartitionR5Test; import ca.uhn.fhir.model.api.StorageResponseCodeEnum; +import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.test.utilities.ITestDataBuilder; import ca.uhn.fhir.util.BundleBuilder; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -46,7 +47,8 @@ public class TransactionPartitionProcessorTest implements ITestDataBuilder { @BeforeEach public void beforeEach() { myInterceptorBroadcaster.registerInterceptor(myInterceptor); - mySvc = new TransactionPartitionProcessor<>(myTransactionProcessor, myFhirContext, newSrd(), false, myInterceptorBroadcaster, "transaction"); + mySvc = new TransactionPartitionProcessor<>(myTransactionProcessor, myFhirContext, newSrd(), false, myInterceptorBroadcaster, + "transaction", new TransactionDetails()); } @Test diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java index 0c6daafa1b6..93c4bc344db 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java @@ -240,6 +240,8 @@ public BUNDLE transaction( RequestDetails theRequestDetails, BUNDLE theRequest, boolean theNestedMode) { String actionName = "Transaction"; + TransactionDetails transactionDetails = new TransactionDetails(); + IInterceptorBroadcaster compositeBroadcaster = CompositeInterceptorBroadcaster.newCompositeBroadcaster(myInterceptorBroadcaster, theRequestDetails); @@ -248,7 +250,8 @@ public BUNDLE transaction( HookParams params = new HookParams() .add(RequestDetails.class, theRequestDetails) .addIfMatchesType(ServletRequestDetails.class, theRequest) - .add(IBaseBundle.class, theRequest); + .add(IBaseBundle.class, theRequest) + .add(TransactionDetails.class, transactionDetails); compositeBroadcaster.callHooks(Pointcut.STORAGE_TRANSACTION_PROCESSING, params); } @@ -256,10 +259,10 @@ public BUNDLE transaction( // Interceptor call: STORAGE_TRANSACTION_PRE_PARTITION if (compositeBroadcaster.hasHooks(Pointcut.STORAGE_TRANSACTION_PRE_PARTITION)) { response = new TransactionPartitionProcessor( - this, myContext, theRequestDetails, theNestedMode, compositeBroadcaster, actionName) + this, myContext, theRequestDetails, theNestedMode, compositeBroadcaster, actionName, transactionDetails) .execute(theRequest); } else { - response = processTransactionAsSubRequest(theRequestDetails, theRequest, actionName, theNestedMode); + response = processTransactionAsSubRequest(theRequestDetails, transactionDetails, theRequest, actionName, theNestedMode); } List entries = myVersionAdapter.getEntries(response); @@ -398,12 +401,6 @@ private Date getLastModified(IBaseResource theRes) { return theRes.getMeta().getLastUpdated(); } - IBaseBundle processTransactionAsSubRequest( - RequestDetails theRequestDetails, IBaseBundle theRequest, String theActionName, boolean theNestedMode) { - return processTransactionAsSubRequest( - theRequestDetails, new TransactionDetails(), theRequest, theActionName, theNestedMode); - } - IBaseBundle processTransactionAsSubRequest( RequestDetails theRequestDetails, TransactionDetails theTransactionDetails, @@ -2615,17 +2612,20 @@ private void processBatchEntry() { IInterceptorBroadcaster compositeBroadcaster = CompositeInterceptorBroadcaster.newCompositeBroadcaster(myInterceptorBroadcaster, myRequestDetails); + TransactionDetails transactionDetails = new TransactionDetails(); + // Interceptor call: STORAGE_TRANSACTION_PROCESSING if (compositeBroadcaster.hasHooks(Pointcut.STORAGE_TRANSACTION_PROCESSING)) { HookParams params = new HookParams() .add(RequestDetails.class, myRequestDetails) .addIfMatchesType(ServletRequestDetails.class, myRequestDetails) - .add(IBaseBundle.class, subRequestBundle); + .add(IBaseBundle.class, subRequestBundle) + .add(TransactionDetails.class, transactionDetails); compositeBroadcaster.callHooks(Pointcut.STORAGE_TRANSACTION_PROCESSING, params); } IBaseBundle nextResponseBundle = processTransactionAsSubRequest( - myRequestDetails, subRequestBundle, "Batch sub-request", myNestedMode); + myRequestDetails, transactionDetails, subRequestBundle, "Batch sub-request", myNestedMode); IBase subResponseEntry = (IBase) myVersionAdapter.getEntries(nextResponseBundle).get(0); diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessor.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessor.java index 7ce462d927c..32cfdf12555 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessor.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessor.java @@ -67,6 +67,7 @@ public class TransactionPartitionProcessor { private final String myActionName; private final FhirContext myFhirContext; private final BaseTransactionProcessor myTransactionProcessor; + private final TransactionDetails myTransactionDetails; /** * Constructor @@ -77,13 +78,15 @@ public TransactionPartitionProcessor( RequestDetails theRequestDetails, boolean theNestedMode, IInterceptorBroadcaster theCompositeBroadcaster, - String theActionName) { + String theActionName, + TransactionDetails theTransactionDetails) { myTransactionProcessor = theTransactionProcessor; myFhirContext = theFhirContext; myRequestDetails = theRequestDetails; myNestedMode = theNestedMode; myInterceptorBroadcaster = theCompositeBroadcaster; myActionName = theActionName; + myTransactionDetails = theTransactionDetails; } /** @@ -105,7 +108,8 @@ public BUNDLE execute(BUNDLE theRequest) { HookParams hookParams = new HookParams() .add(RequestDetails.class, myRequestDetails) .addIfMatchesType(ServletRequestDetails.class, myRequestDetails) - .add(IBaseBundle.class, theRequest); + .add(IBaseBundle.class, theRequest) + .add(TransactionDetails.class, myTransactionDetails); TransactionPrePartitionResponse partitionResponse = (TransactionPrePartitionResponse) myInterceptorBroadcaster.callHooksAndReturnObject( Pointcut.STORAGE_TRANSACTION_PRE_PARTITION, hookParams); @@ -173,7 +177,6 @@ private BUNDLE processPartitionedBundles(BUNDLE theOriginalBundle, List idSubstitutions = new HashMap<>(); for (IBaseBundle singlePartitionRequest : partitionedRequests) { @@ -190,7 +193,7 @@ private BUNDLE processPartitionedBundles(BUNDLE theOriginalBundle, List Date: Wed, 29 Oct 2025 13:29:25 -0500 Subject: [PATCH 2/9] Update BaseTransactionProcessor.java --- .../main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java index 93c4bc344db..8affb67e840 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java @@ -259,7 +259,7 @@ public BUNDLE transaction( // Interceptor call: STORAGE_TRANSACTION_PRE_PARTITION if (compositeBroadcaster.hasHooks(Pointcut.STORAGE_TRANSACTION_PRE_PARTITION)) { response = new TransactionPartitionProcessor( - this, myContext, theRequestDetails, theNestedMode, compositeBroadcaster, actionName, transactionDetails) + this, myContext, theRequestDetails, theNestedMode, compositeBroadcaster, actionName, transactionDetails) .execute(theRequest); } else { response = processTransactionAsSubRequest(theRequestDetails, transactionDetails, theRequest, actionName, theNestedMode); From dd4ce6c82342d129df603b61dc229fb9df8d2770 Mon Sep 17 00:00:00 2001 From: elavy-harris <102183351+elavy-harris@users.noreply.github.com> Date: Wed, 29 Oct 2025 13:35:51 -0500 Subject: [PATCH 3/9] Update BaseTransactionProcessor.java --- .../ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java index 8affb67e840..154bc13950b 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java @@ -259,10 +259,17 @@ public BUNDLE transaction( // Interceptor call: STORAGE_TRANSACTION_PRE_PARTITION if (compositeBroadcaster.hasHooks(Pointcut.STORAGE_TRANSACTION_PRE_PARTITION)) { response = new TransactionPartitionProcessor( - this, myContext, theRequestDetails, theNestedMode, compositeBroadcaster, actionName, transactionDetails) + this, + myContext, + theRequestDetails, + theNestedMode, + compositeBroadcaster, + actionName, + transactionDetails) .execute(theRequest); } else { - response = processTransactionAsSubRequest(theRequestDetails, transactionDetails, theRequest, actionName, theNestedMode); + response = processTransactionAsSubRequest( + theRequestDetails, transactionDetails, theRequest, actionName, theNestedMode); } List entries = myVersionAdapter.getEntries(response); From 9aff19f2ba877d444100a36258eda6194f5402db Mon Sep 17 00:00:00 2001 From: elavy-harris <102183351+elavy-harris@users.noreply.github.com> Date: Wed, 29 Oct 2025 13:22:47 -0500 Subject: [PATCH 4/9] Include-TransactionDetails-in-STORAGE_TRANSACTION_PROCESSING --- .../ca/uhn/fhir/interceptor/api/Pointcut.java | 12 ++++++++-- .../TransactionPartitionProcessorTest.java | 4 +++- .../jpa/dao/BaseTransactionProcessor.java | 22 +++++++++---------- .../dao/TransactionPartitionProcessor.java | 11 ++++++---- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java index 4173bad4d0d..b838d05cb0c 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java @@ -1878,6 +1878,9 @@ public enum Pointcut implements IPointcut { * pulled out of the servlet request. This parameter is identical to the RequestDetails parameter above but will * only be populated when operating in a RestfulServer implementation. It is provided as a convenience. * + *

  • + * ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 8.6) + *
  • * *

    * Hooks must return an instance of ca.uhn.fhir.jpa.dao.TransactionPrePartitionResponse. @@ -1889,7 +1892,8 @@ public enum Pointcut implements IPointcut { "ca.uhn.fhir.jpa.dao.TransactionPrePartitionResponse", "ca.uhn.fhir.rest.api.server.RequestDetails", "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails", - "org.hl7.fhir.instance.model.api.IBaseBundle"), + "org.hl7.fhir.instance.model.api.IBaseBundle", + "ca.uhn.fhir.rest.api.server.storage.TransactionDetails"), /** * Storage Hook: @@ -1913,6 +1917,9 @@ public enum Pointcut implements IPointcut { * pulled out of the servlet request. This parameter is identical to the RequestDetails parameter above but will * only be populated when operating in a RestfulServer implementation. It is provided as a convenience. * + *

  • + * ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 8.6) + *
  • * *

    * Hooks should return void. @@ -1925,7 +1932,8 @@ public enum Pointcut implements IPointcut { void.class, "org.hl7.fhir.instance.model.api.IBaseBundle", "ca.uhn.fhir.rest.api.server.RequestDetails", - "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails"), + "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails", + "ca.uhn.fhir.rest.api.server.storage.TransactionDetails"), /** * Storage Hook: diff --git a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessorTest.java b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessorTest.java index 20e6a0f3b15..9bb93bb72ba 100644 --- a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessorTest.java +++ b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessorTest.java @@ -4,6 +4,7 @@ import ca.uhn.fhir.interceptor.executor.InterceptorService; import ca.uhn.fhir.jpa.dao.r5.FhirSystemDaoTransactionPartitionR5Test; import ca.uhn.fhir.model.api.StorageResponseCodeEnum; +import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.test.utilities.ITestDataBuilder; import ca.uhn.fhir.util.BundleBuilder; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -46,7 +47,8 @@ public class TransactionPartitionProcessorTest implements ITestDataBuilder { @BeforeEach public void beforeEach() { myInterceptorBroadcaster.registerInterceptor(myInterceptor); - mySvc = new TransactionPartitionProcessor<>(myTransactionProcessor, myFhirContext, newSrd(), false, myInterceptorBroadcaster, "transaction"); + mySvc = new TransactionPartitionProcessor<>(myTransactionProcessor, myFhirContext, newSrd(), false, myInterceptorBroadcaster, + "transaction", new TransactionDetails()); } @Test diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java index 0c6daafa1b6..93c4bc344db 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java @@ -240,6 +240,8 @@ public BUNDLE transaction( RequestDetails theRequestDetails, BUNDLE theRequest, boolean theNestedMode) { String actionName = "Transaction"; + TransactionDetails transactionDetails = new TransactionDetails(); + IInterceptorBroadcaster compositeBroadcaster = CompositeInterceptorBroadcaster.newCompositeBroadcaster(myInterceptorBroadcaster, theRequestDetails); @@ -248,7 +250,8 @@ public BUNDLE transaction( HookParams params = new HookParams() .add(RequestDetails.class, theRequestDetails) .addIfMatchesType(ServletRequestDetails.class, theRequest) - .add(IBaseBundle.class, theRequest); + .add(IBaseBundle.class, theRequest) + .add(TransactionDetails.class, transactionDetails); compositeBroadcaster.callHooks(Pointcut.STORAGE_TRANSACTION_PROCESSING, params); } @@ -256,10 +259,10 @@ public BUNDLE transaction( // Interceptor call: STORAGE_TRANSACTION_PRE_PARTITION if (compositeBroadcaster.hasHooks(Pointcut.STORAGE_TRANSACTION_PRE_PARTITION)) { response = new TransactionPartitionProcessor( - this, myContext, theRequestDetails, theNestedMode, compositeBroadcaster, actionName) + this, myContext, theRequestDetails, theNestedMode, compositeBroadcaster, actionName, transactionDetails) .execute(theRequest); } else { - response = processTransactionAsSubRequest(theRequestDetails, theRequest, actionName, theNestedMode); + response = processTransactionAsSubRequest(theRequestDetails, transactionDetails, theRequest, actionName, theNestedMode); } List entries = myVersionAdapter.getEntries(response); @@ -398,12 +401,6 @@ private Date getLastModified(IBaseResource theRes) { return theRes.getMeta().getLastUpdated(); } - IBaseBundle processTransactionAsSubRequest( - RequestDetails theRequestDetails, IBaseBundle theRequest, String theActionName, boolean theNestedMode) { - return processTransactionAsSubRequest( - theRequestDetails, new TransactionDetails(), theRequest, theActionName, theNestedMode); - } - IBaseBundle processTransactionAsSubRequest( RequestDetails theRequestDetails, TransactionDetails theTransactionDetails, @@ -2615,17 +2612,20 @@ private void processBatchEntry() { IInterceptorBroadcaster compositeBroadcaster = CompositeInterceptorBroadcaster.newCompositeBroadcaster(myInterceptorBroadcaster, myRequestDetails); + TransactionDetails transactionDetails = new TransactionDetails(); + // Interceptor call: STORAGE_TRANSACTION_PROCESSING if (compositeBroadcaster.hasHooks(Pointcut.STORAGE_TRANSACTION_PROCESSING)) { HookParams params = new HookParams() .add(RequestDetails.class, myRequestDetails) .addIfMatchesType(ServletRequestDetails.class, myRequestDetails) - .add(IBaseBundle.class, subRequestBundle); + .add(IBaseBundle.class, subRequestBundle) + .add(TransactionDetails.class, transactionDetails); compositeBroadcaster.callHooks(Pointcut.STORAGE_TRANSACTION_PROCESSING, params); } IBaseBundle nextResponseBundle = processTransactionAsSubRequest( - myRequestDetails, subRequestBundle, "Batch sub-request", myNestedMode); + myRequestDetails, transactionDetails, subRequestBundle, "Batch sub-request", myNestedMode); IBase subResponseEntry = (IBase) myVersionAdapter.getEntries(nextResponseBundle).get(0); diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessor.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessor.java index 7ce462d927c..32cfdf12555 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessor.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/TransactionPartitionProcessor.java @@ -67,6 +67,7 @@ public class TransactionPartitionProcessor { private final String myActionName; private final FhirContext myFhirContext; private final BaseTransactionProcessor myTransactionProcessor; + private final TransactionDetails myTransactionDetails; /** * Constructor @@ -77,13 +78,15 @@ public TransactionPartitionProcessor( RequestDetails theRequestDetails, boolean theNestedMode, IInterceptorBroadcaster theCompositeBroadcaster, - String theActionName) { + String theActionName, + TransactionDetails theTransactionDetails) { myTransactionProcessor = theTransactionProcessor; myFhirContext = theFhirContext; myRequestDetails = theRequestDetails; myNestedMode = theNestedMode; myInterceptorBroadcaster = theCompositeBroadcaster; myActionName = theActionName; + myTransactionDetails = theTransactionDetails; } /** @@ -105,7 +108,8 @@ public BUNDLE execute(BUNDLE theRequest) { HookParams hookParams = new HookParams() .add(RequestDetails.class, myRequestDetails) .addIfMatchesType(ServletRequestDetails.class, myRequestDetails) - .add(IBaseBundle.class, theRequest); + .add(IBaseBundle.class, theRequest) + .add(TransactionDetails.class, myTransactionDetails); TransactionPrePartitionResponse partitionResponse = (TransactionPrePartitionResponse) myInterceptorBroadcaster.callHooksAndReturnObject( Pointcut.STORAGE_TRANSACTION_PRE_PARTITION, hookParams); @@ -173,7 +177,6 @@ private BUNDLE processPartitionedBundles(BUNDLE theOriginalBundle, List idSubstitutions = new HashMap<>(); for (IBaseBundle singlePartitionRequest : partitionedRequests) { @@ -190,7 +193,7 @@ private BUNDLE processPartitionedBundles(BUNDLE theOriginalBundle, List Date: Wed, 29 Oct 2025 13:29:25 -0500 Subject: [PATCH 5/9] Update BaseTransactionProcessor.java --- .../main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java index 93c4bc344db..8affb67e840 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java @@ -259,7 +259,7 @@ public BUNDLE transaction( // Interceptor call: STORAGE_TRANSACTION_PRE_PARTITION if (compositeBroadcaster.hasHooks(Pointcut.STORAGE_TRANSACTION_PRE_PARTITION)) { response = new TransactionPartitionProcessor( - this, myContext, theRequestDetails, theNestedMode, compositeBroadcaster, actionName, transactionDetails) + this, myContext, theRequestDetails, theNestedMode, compositeBroadcaster, actionName, transactionDetails) .execute(theRequest); } else { response = processTransactionAsSubRequest(theRequestDetails, transactionDetails, theRequest, actionName, theNestedMode); From a154dbedaceb37ce4adae463dcfc1e0ac41102bd Mon Sep 17 00:00:00 2001 From: elavy-harris <102183351+elavy-harris@users.noreply.github.com> Date: Wed, 29 Oct 2025 13:35:51 -0500 Subject: [PATCH 6/9] Update BaseTransactionProcessor.java --- .../ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java index 8affb67e840..154bc13950b 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseTransactionProcessor.java @@ -259,10 +259,17 @@ public BUNDLE transaction( // Interceptor call: STORAGE_TRANSACTION_PRE_PARTITION if (compositeBroadcaster.hasHooks(Pointcut.STORAGE_TRANSACTION_PRE_PARTITION)) { response = new TransactionPartitionProcessor( - this, myContext, theRequestDetails, theNestedMode, compositeBroadcaster, actionName, transactionDetails) + this, + myContext, + theRequestDetails, + theNestedMode, + compositeBroadcaster, + actionName, + transactionDetails) .execute(theRequest); } else { - response = processTransactionAsSubRequest(theRequestDetails, transactionDetails, theRequest, actionName, theNestedMode); + response = processTransactionAsSubRequest( + theRequestDetails, transactionDetails, theRequest, actionName, theNestedMode); } List entries = myVersionAdapter.getEntries(response); From cf7c29c70bbca546ad71eb59e6135bdd87555536 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Thu, 6 Nov 2025 09:02:55 -0500 Subject: [PATCH 7/9] Add changelog --- ...341-make-transactiondetails-available-to-interceptor.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7341-make-transactiondetails-available-to-interceptor.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7341-make-transactiondetails-available-to-interceptor.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7341-make-transactiondetails-available-to-interceptor.yaml new file mode 100644 index 00000000000..d41bc7f243f --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7341-make-transactiondetails-available-to-interceptor.yaml @@ -0,0 +1,5 @@ +--- +type: add +issue: 7341 +title: "When processing a FHIR transaction, the TransactionDetails object + is now created earlier and made available to interceptor hooks." From ab38eadf687a67d8430e62f503b59922572427ef Mon Sep 17 00:00:00 2001 From: James Agnew Date: Thu, 20 Nov 2025 14:23:33 -0500 Subject: [PATCH 8/9] Cleanup --- .../src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java | 2 +- .../7341-make-transactiondetails-available-to-interceptor.yaml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java index 6a86030d4ec..9af6311571a 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java @@ -1886,7 +1886,7 @@ public enum Pointcut implements IPointcut { * only be populated when operating in a RestfulServer implementation. It is provided as a convenience. * *

  • - * ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 8.6) + * ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 8.8.0) *
  • * *

    diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7341-make-transactiondetails-available-to-interceptor.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7341-make-transactiondetails-available-to-interceptor.yaml index d41bc7f243f..1e83eaf01fa 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7341-make-transactiondetails-available-to-interceptor.yaml +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/8_8_0/7341-make-transactiondetails-available-to-interceptor.yaml @@ -2,4 +2,5 @@ type: add issue: 7341 title: "When processing a FHIR transaction, the TransactionDetails object - is now created earlier and made available to interceptor hooks." + is now created earlier and made available to interceptor hooks. Thanks + to Elliott Lavy for the contribution!" From 20644cbdf32865b6cf79be6d6980cb589bc538c9 Mon Sep 17 00:00:00 2001 From: elavy-harris <102183351+elavy-harris@users.noreply.github.com> Date: Thu, 20 Nov 2025 13:27:22 -0600 Subject: [PATCH 9/9] Update HAPI version in documentation --- .../src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java index 9af6311571a..277ff97ab41 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java @@ -1925,7 +1925,7 @@ public enum Pointcut implements IPointcut { * only be populated when operating in a RestfulServer implementation. It is provided as a convenience. * *

  • - * ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 8.6) + * ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 8.8.0) *
  • * *