Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* </li>
* <li>
* ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 8.6)
* </li>
* </ul>
* <p>
* Hooks must return an instance of <code>ca.uhn.fhir.jpa.dao.TransactionPrePartitionResponse</code>.
Expand All @@ -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"),

/**
* <b>Storage Hook:</b>
Expand All @@ -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.
* </li>
* <li>
* ca.uhn.fhir.rest.api.server.storage.TransactionDetails - The outer transaction details object (since 8.6)
* </li>
* </ul>
* <p>
* Hooks should return <code>void</code>.
Expand All @@ -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"),

/**
* <b>Storage Hook:</b>
Expand Down
Original file line number Diff line number Diff line change
@@ -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."
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ public <BUNDLE extends IBaseBundle> BUNDLE transaction(
RequestDetails theRequestDetails, BUNDLE theRequest, boolean theNestedMode) {
String actionName = "Transaction";

TransactionDetails transactionDetails = new TransactionDetails();

IInterceptorBroadcaster compositeBroadcaster =
CompositeInterceptorBroadcaster.newCompositeBroadcaster(myInterceptorBroadcaster, theRequestDetails);

Expand All @@ -248,18 +250,26 @@ public <BUNDLE extends IBaseBundle> 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);
}

IBaseBundle response;
// Interceptor call: STORAGE_TRANSACTION_PRE_PARTITION
if (compositeBroadcaster.hasHooks(Pointcut.STORAGE_TRANSACTION_PRE_PARTITION)) {
response = new TransactionPartitionProcessor<BUNDLE>(
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<IBase> entries = myVersionAdapter.getEntries(response);
Expand Down Expand Up @@ -398,12 +408,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,
Expand Down Expand Up @@ -2615,17 +2619,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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public class TransactionPartitionProcessor<BUNDLE extends IBaseBundle> {
private final String myActionName;
private final FhirContext myFhirContext;
private final BaseTransactionProcessor myTransactionProcessor;
private final TransactionDetails myTransactionDetails;

/**
* Constructor
Expand All @@ -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;
}

/**
Expand All @@ -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);
Expand Down Expand Up @@ -173,7 +177,6 @@ private BUNDLE processPartitionedBundles(BUNDLE theOriginalBundle, List<IBaseBun
}
}

TransactionDetails transactionDetails = new TransactionDetails();
Map<String, IIdType> idSubstitutions = new HashMap<>();
for (IBaseBundle singlePartitionRequest : partitionedRequests) {

Expand All @@ -190,7 +193,7 @@ private BUNDLE processPartitionedBundles(BUNDLE theOriginalBundle, List<IBaseBun
}

IBaseBundle singlePartitionResponse = myTransactionProcessor.processTransactionAsSubRequest(
myRequestDetails, transactionDetails, singlePartitionRequest, myActionName, myNestedMode);
myRequestDetails, myTransactionDetails, singlePartitionRequest, myActionName, myNestedMode);

// Capture any placeholder ID substitutions from this partition
TransactionUtil.TransactionResponse singlePartitionResponseParsed =
Expand Down
Loading