Examples: FHIR Storage - Smile CDR Documentation

FHIR Storage Examples

This page contains example interceptors that can be registered with the FHIR Storage module.

Example: Response Attribute Enhancement

The following example shows an interceptor that can be used to enhance resources that are submitted for update by a client. In this example, for every time that a Patient resource is created or updated, we are calling a REST MDM service to fetch an EUID (an enterprise identifier for a Patient). We are then adding this EUID as an additional identifier on the list of patient identifiers.

/*-
 * #%L
 * Smile CDR - CDR
 * %%
 * Copyright (C) 2016 - 2026 Smile CDR, Inc.
 * %%
 * All rights reserved.
 * #L%
 */
package com.smilecdr.demo.fhirstorage;

import ca.uhn.fhir.interceptor.api.Hook;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Patient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.util.Collections;
import java.util.HashMap;
import java.util.Objects;

/**
 * This example interceptor fetches a set of attributes from a third-party
 * REST service and uses them to enhance the resource being submitted.
 */
@SuppressWarnings("unchecked")
public class ExampleAttributeEnhancingInterceptor {

private static final Logger ourLog = LoggerFactory.getLogger(ExampleAttributeEnhancingInterceptor.class);

/**
     * We are going to treat creates and updates the same way in this example, so the
     * create method redirects to the update method.
     */
    @Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED)
    public void resourcePreCreate(RequestDetails theRequest, IBaseResource theResource) {
        handleResource(theResource);
    }

/**
     * For this example we are overriding the <code>resourcePreUpdate</code>
     * method, which will be called when a resource is being updated. There
     * are many other methods that can be overridden, but this one is
     * appropriate for the desired functionality.
     *
     * @param theRequest     Contains details about the incoming request. You may wish to cast this
     *                       object to a {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails},
     *                       which is always possible when running interceptors inside Smile CDR.
     * @param theOldResource The previous version of the resource, before this update was
     *                       requested by the client.
     * @param theNewResource The new version of the resource as submitted by the client. This
     *                       object can be modified.
     */
    @Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED)
    public void resourcePreUpdate(
            RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource) {
        handleResource(theNewResource);
    }

private void handleResource(IBaseResource theResource) {
        // This interceptor only cares about Patient resources
        if (!(theResource instanceof Patient)) {
            return;
        }

Patient patient = (Patient) theResource;

/*
         * We want to know the primary identifier, which is the first instance of
         * Patient.identifier where identifier.system = "http://example.com/mrn". If the
         * client has submitted a resource that does not have such an identifier, this
         * is an error, and we will throw a PreconditionFailedException (HTTP 412)
         */
        String primaryIdentifier = patient.getIdentifier().stream()
                .filter(t -> t.getSystem().equals("http://example.com/mrn"))
                .map(Identifier::getValue)
                .findFirst()
                .orElseThrow(() -> new PreconditionFailedException("No MRN supplied with request"));

// We'll use a system property to pull the port number for this example. If the port
        // number won't change across deployments you don't need to do this.
        int port = Integer.parseInt(System.getProperty("mqm_query_port"));

// We're going to make a web service call to a simple web service that
        // returns a JSON response. There are lots of ways of doing this, but
        // in our example we'll make a call using the Spring RestTemplate
        RestTemplate restTempate = new RestTemplate();
        restTempate.setMessageConverters(Collections.singletonList(new GsonHttpMessageConverter()));
        HashMap<String, Object> response = restTempate.getForObject(
                "http://localhost:" + port + "/mdmquery?mrn=" + primaryIdentifier, HashMap.class);
        Objects.requireNonNull(response);

// We'll log the response. Generally this isn't a good idea in a real
        // production system, but it's handy for debugging at first.
        ourLog.info("Response: {}", response);

// Grab the existing EUID (identifier with a system of "http://example.com/euid")
        // and create one if it doesn't exist
        Identifier euidIdentifier = patient.getIdentifier().stream()
                .filter(t -> t.getSystem().equals("http://example.com/euid"))
                .findFirst()
                .orElseGet(patient::addIdentifier);

// Set the identifier value using the web service response
        euidIdentifier.setSystem("http://example.com/euid");
        euidIdentifier.setValue((String) response.get("euid"));
    }
}

Copy

Example: Server-Reserved Tags

The following example shows an interceptor that implements reserved tags. For this example, a reserved tag is a tag that can only be set or removed by the server itself. These tags can not be added or removed by a client, and are hidden from the client as well.

import ca.uhn.fhir.interceptor.api.Hook; import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.rest.api.server.IPreResourceShowDetails; import ca.uhn.fhir.rest.api.server.RequestDetails; import com.google.common.collect.Sets; import org.apache.commons.lang3.tuple.Pair; import org.hl7.fhir.instance.model.api.IBaseCoding; import org.hl7.fhir.instance.model.api.IBaseResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

import java.util.Collections; import java.util.Iterator; import java.util.Set;

/**

private static final Logger ourLog = LoggerFactory.getLogger(TagPreservingInterceptor.class);

private Set myTagsToPreserve;

/** * Constructor */ public TagPreservingInterceptor() { // This is the list of tags we want to preserve myTagsToPreserve = Collections.unmodifiableSet( Sets.newHashSet(Pair.of("http://my-tags", "tag1"), Pair.of("http://my-tags", "tag2"))); }

/** * When a new resource is being created, don't allow the client to include any reserved tags * * @param theRequest Contains details about the incoming request. You may wish to cast this * object to a {@link ca.uhn.fhir.rest.server.servlet.ServletRequestDetails}, * which is always possible when running interceptors inside Smile CDR. * @param theResource The previous resource being created */ @Hook(value = Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED, order = 100) public void resourcePreCreate(RequestDetails theRequest, IBaseResource theResource) { removeReservedTags(theResource); }

// Filter out any reserved tags removeReservedTags(theNewResource);

// Copy tags forward theOldResource.getMeta().getTag().stream() .filter(t -> myTagsToPreserve.contains(Pair.of(t.getSystem(), t.getCode()))) .forEach(t -> theNewResource .getMeta() .addTag() .setSystem(t.getSystem()) .setCode(t.getCode()) .setDisplay(t.getDisplay())); }

/** * Before returning any resource to the client, strip the reserved tags */ @Hook(value = Pointcut.STORAGE_PRESHOW_RESOURCES) public void preShow(IPreResourceShowDetails thePreShowDetails) { for (IBaseResource nextResource : thePreShowDetails) { removeReservedTags(nextResource); } }

private void removeReservedTags(IBaseResource theResource) { for (Iterator<? extends IBaseCoding> iter = theResource.getMeta().getTag().iterator(); iter.hasNext(); ) { IBaseCoding nextTag = iter.next(); String system = nextTag.getSystem(); String code = nextTag.getCode(); if (myTagsToPreserve.contains(Pair.of(system, code))) { iter.remove(); } } } }


Copy

# Example: JavaScript Storage Interceptor

```javascript
function fhirResourcePreCreate(theRequestDetails, theResource) {
   if (theResource.name[0].family === "initial-family-name") {
      theResource.name[0].family = "after-pre-create";
   }
}

function fhirResourceCreated(theRequestDetails, theResource) {
   if (theResource.name[0].family === "after-pre-create") {
      throw "the resource was created";
   }
}

function fhirResourcePreUpdate(theRequestDetails, theOldResource, theNewResource) {
   if (theNewResource.resourceType === 'Patient') {
      if (theOldResource.name[0].family === 'old-name' && theNewResource.name[0].family === 'new-name') {
         theNewResource.name[0].given[0] = 'a-given-name';
      }
   } else {
      Log.info("Unknown resource type " + theNewResource.resourceType);
   }
}

function fhirResourceUpdated(theRequestDetails, theOldResource, theNewResource) {
   if (theOldResource.name[0].family === 'old-name' && theNewResource.name[0].given[0].toString() === "a-given-name") {
      throw "the resource was updated";
   }
}

function fhirResourcePreDelete(theRequestDetails, theResource) {
   if (theResource.name[0].family === 'removed-family-name') {
      theResource.name[0].given[0] = 'b-given-name';
   }
}

function fhirResourceDeleted(theRequestDetails, theResource) {
   if (theResource.resourceType === 'Patient') {
      throw "This patient was deleted";
   }
}

Copy

Example: MegaScale Connection Provider

The following example shows an interceptor that is used to provide connection details for a FHIR Storage module configured in MegaScale mode.

import ca.cdr.api.fhir.interceptor.CdrHook; import ca.cdr.api.fhir.interceptor.CdrPointcut; import ca.cdr.api.persistence.megascale.MegaScaleCredentialRequestJson; import ca.cdr.api.persistence.megascale.MegaScaleCredentialResponseJson; import ca.uhn.fhir.interceptor.api.Interceptor; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import org.apache.commons.lang3.StringUtils;

/**

@CdrHook(CdrPointcut.STORAGE_MEGASCALE_PROVIDE_DB_INFO) public MegaScaleCredentialResponseJson provideMegaScaleCredentials(MegaScaleCredentialRequestJson theRequest) {

MegaScaleCredentialResponseJson response; if (theRequest.getPartitionId() != 0) { response = determinePartitionById(theRequest.getPartitionId()); } else if (!StringUtils.isBlank(theRequest.getPartitionName())) { response = determinePartitionByName(theRequest.getPartitionName()); } else { throw new InvalidRequestException("No way to identify this partition!"); } /* * If any additional SQL should be executed in the database when it is * first initialized, it may be added here. The example below shows a * no-op query which does not do anything (and this should be removed * in a real deployment), but you could replace this with a script that * sets permissions or adds placeholders. */ response.addDatabaseInitializationStatement("SELECT 1"); return response; }

/** * You can elect to determine data source selection by tenant name, instead of by partition ID, if you so desire. / private MegaScaleCredentialResponseJson determinePartitionByName(String partitionName) { / * In this example, we'll use one connection URL for tenants "TENANT-A" & "TENANT-C", and * a different connection URL for partitions "TENANT-B" & "TENANT-D". You can group partitions * any way you would like. */ MegaScaleCredentialResponseJson retVal = new MegaScaleCredentialResponseJson(); switch (partitionName) { case "TENANT-A": case "TENANT-C": setConnectionToFirstDatabase(retVal); break; case "TENANT-B": case "TENANT-D": setConnectionToSecondDatabase(retVal); break; default: // Shouldn't happen, and will cause an error if it does } return retVal; }

private void setConnectionToSecondDatabase(MegaScaleCredentialResponseJson retVal) { retVal.setDatabaseUrl("jdbc:h2:mem:ds2"); retVal.setDatabaseUsername("SA"); retVal.setDatabasePassword("SA"); }

private void setConnectionToFirstDatabase(MegaScaleCredentialResponseJson retVal) { retVal.setDatabaseUrl("jdbc:h2:mem:ds1"); retVal.setDatabaseUsername("SA"); retVal.setDatabasePassword("SA"); }

private MegaScaleCredentialResponseJson determinePartitionById(int partitionId) { /* * In this example, we'll use one connection URL for partitions 1 & 3, and * a different connection URL for partitions 2 & 4. You can group partitions * any way you would like. / MegaScaleCredentialResponseJson retVal = new MegaScaleCredentialResponseJson(); switch (partitionId) { case 1: case 3: setConnectionToFirstDatabase(retVal); break; case 2: case 4: setConnectionToSecondDatabase(retVal); break; default: // Shouldn't happen, and will cause an error if it does } / * If any additional SQL should be executed in the database when it is * first initialized, it may be added here. The example below shows a * no-op query which does not do anything (and this should be removed * in a real deployment), but you could replace this with a script that * sets permissions or adds placeholders. */ retVal.addDatabaseInitializationStatement("SELECT 1");

return retVal; } }


Copy

# Example: Starter Storage interceptor for all STORAGE\_xxx pointcuts

The following example shows an interceptor that can be used as a starter Storage interceptor, implementing a hook method for each available pointcut.

import ca.cdr.api.broker.IPublicBrokerSender;
import ca.cdr.api.i18n.ILocalizer;
import ca.cdr.api.transactionlog.ITransactionLogFetchingSvc;
import ca.cdr.api.transactionlog.ITransactionLogStoringSvc;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.interceptor.api.Hook;
import ca.uhn.fhir.interceptor.api.Interceptor;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.interceptor.model.TransactionWriteOperationsDetails;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.model.DeleteConflictList;
import ca.uhn.fhir.jpa.api.model.ResourceVersionConflictResolutionStrategy;
import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.InterceptorInvocationTimingEnum;
import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
import ca.uhn.fhir.rest.api.server.IPreResourceShowDetails;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.bulk.BulkExportJobParameters;
import ca.uhn.fhir.rest.api.server.storage.DeferredInterceptorBroadcasts;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.rest.server.util.ICachedSearchDetails;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.validation.ValidationResult;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Sample Storage Interceptor implementing all STORAGE_XXX pointcuts.
 * It is indented to be used in FHIR Storage Persistence module 'Interceptor Bean Types'.
 * Can be used as a starting point for your storage interceptor.
 *
 * NOTE ON USING THIS TEMPLATE:
 * You should cut and paste whichever parts of this interceptor you need into a
 * new class, or remove all the methods and fields you do not need. It is
 * inefficient to actually deploy this interceptor with every pointcut declared
 * and not actually used.
 */
@SuppressWarnings({"unused", "EmptyTryBlock"})
@Interceptor
public class StorageInterceptorTemplate {

private static final Logger ourLog = LoggerFactory.getLogger(StorageInterceptorTemplate.class);

@Autowired
    private IPublicBrokerSender myBrokerSender;

@Autowired
    private ITransactionLogFetchingSvc myTransactionLogFetchingSvc;

@Autowired
    private ITransactionLogStoringSvc myTransactionLogStoringSvc;

@Autowired
    private ILocalizer myLocalizer;

@Autowired
    private FhirContext myFhirContext;

@Autowired
    private DaoRegistry myDaoRegistry;

@Autowired
    private RepositoryValidatingRuleBuilder myRuleBuilder;

@Autowired
    private JpaStorageSettings myStorageSettings;

@Autowired
    private PlatformTransactionManager myTransactionManager;

@Hook(Pointcut.STORAGE_PRESEARCH_REGISTERED)
    public void storagePreSearchRegistered(
            ICachedSearchDetails theCachedSearchDetails,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            SearchParameterMap theSearchParameterMap) {

ourLog.info("Interceptor STORAGE_PRESEARCH_REGISTERED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRESEARCH_REGISTERED - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRECHECK_FOR_CACHED_SEARCH)
    public boolean storagePreCheckForCachedSearch(
            SearchParameterMap theSearchParameterMap,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails) {

ourLog.info("Interceptor STORAGE_PRECHECK_FOR_CACHED_SEARCH - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRECHECK_FOR_CACHED_SEARCH - ended, execution took {}", stopWatch);
        }
        return true;
    }

@Hook(Pointcut.STORAGE_PREACCESS_RESOURCES)
    public void storagePreAccessResources(
            IPreResourceAccessDetails thePreResourceAccessDetails,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails) {

ourLog.info("Interceptor STORAGE_PREACCESS_RESOURCES - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PREACCESS_RESOURCES - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRESHOW_RESOURCES)
    public void storagePreShowResources(
            IPreResourceShowDetails thePreResourceShowDetails,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails) {

ourLog.info("Interceptor STORAGE_PRESHOW_RESOURCES - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRESHOW_RESOURCES - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED)
    public void storagePreStorageResourceCreated(
            IBaseResource theBaseResource,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            TransactionDetails theTransactionDetails,
            RequestPartitionId theRequestPartitionId) {

ourLog.info("Interceptor STORAGE_PRESTORAGE_RESOURCE_CREATED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRESTORAGE_RESOURCE_CREATED - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED)
    public void storagePreStorageResourceUpdated(
            IBaseResource theBaseResource,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            TransactionDetails theTransactionDetails) {

ourLog.info("Interceptor STORAGE_PRESTORAGE_RESOURCE_UPDATED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRESTORAGE_RESOURCE_UPDATED - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_DELETED)
    public void storagePreStorageResourceDeleted(
            IBaseResource theBaseResource,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            TransactionDetails theTransactionDetails) {

ourLog.info("Interceptor STORAGE_PRESTORAGE_RESOURCE_DELETED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRESTORAGE_RESOURCE_DELETED - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED)
    public void storagePreCommitResourceCreated(
            IBaseResource theBaseResource,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            TransactionDetails theTransactionDetails,
            InterceptorInvocationTimingEnum theInterceptorInvocationTimingEnum) {

ourLog.info("Interceptor STORAGE_PRECOMMIT_RESOURCE_CREATED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRECOMMIT_RESOURCE_CREATED - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED)
    public void storagePreCommitResourceUpdated(
            IBaseResource thePreviousContentBaseResource,
            IBaseResource theProposedBaseResource,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            TransactionDetails theTransactionDetails,
            InterceptorInvocationTimingEnum theInterceptorInvocationTimingEnum) {

ourLog.info("Interceptor STORAGE_PRECOMMIT_RESOURCE_UPDATED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRECOMMIT_RESOURCE_UPDATED - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED)
    public void storagePreCommitResourceDeleted(
            IBaseResource theBaseResource,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            TransactionDetails theTransactionDetails,
            InterceptorInvocationTimingEnum theInterceptorInvocationTimingEnum) {

ourLog.info("Interceptor STORAGE_PRECOMMIT_RESOURCE_DELETED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRECOMMIT_RESOURCE_DELETED - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRESTORAGE_EXPUNGE_RESOURCE)
    public void storagePreStorageExpungeResource(
            AtomicInteger theAtomicInteger,
            IIdType theIdType,
            IBaseResource theBaseResource,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails) {

ourLog.info("Interceptor STORAGE_PRESTORAGE_EXPUNGE_RESOURCE - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRESTORAGE_EXPUNGE_RESOURCE - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING)
    public void storagePartitionSelected(
            AtomicInteger theAtomicInteger,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails) {

ourLog.info("Interceptor STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRESTORAGE_EXPUNGE_EVERYTHING - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRE_DELETE_EXPUNGE_PID_LIST)
    public void storagePreDeleteExpungePidList(
            String theResourceType,
            List<Long> theResourcePidList,
            AtomicLong theAtomicLong,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails) {

ourLog.info("Interceptor STORAGE_PRE_DELETE_EXPUNGE_PID_LIST - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRE_DELETE_EXPUNGE_PID_LIST - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRE_DELETE_EXPUNGE)
    public void storagePreDeleteExpunge(
            RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails, String theUrl) {

ourLog.info("Interceptor STORAGE_PRE_DELETE_EXPUNGE - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRE_DELETE_EXPUNGE - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_CASCADE_DELETE)
    public void storageCascadeDelete(
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            DeleteConflictList theDeleteConflictList,
            IBaseResource theBaseResource) {

ourLog.info("Interceptor STORAGE_CASCADE_DELETE - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_CASCADE_DELETE - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_CREATE)
    public RequestPartitionId storagePartitionIdentifyCreate(
            IBaseResource theBaseResource,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails) {

ourLog.info("Interceptor STORAGE_PARTITION_IDENTIFY_CREATE - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PARTITION_IDENTIFY_CREATE - ended, execution took {}", stopWatch);
        }
        return null;
    }

@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_READ)
    public RequestPartitionId storagePartitionIdentifyRead(
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            ReadPartitionIdRequestDetails theReadPartitionIdRequestDetails) {

ourLog.info("Interceptor STORAGE_PARTITION_IDENTIFY_READ - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PARTITION_IDENTIFY_READ - ended, execution took {}", stopWatch);
        }
        return null;
    }

@Hook(Pointcut.STORAGE_PARTITION_SELECTED)
    public void storagePartitionSelected(
            RequestPartitionId theRequestPartitionId,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            RuntimeResourceDefinition theRuntimeResourceDefinition) {

ourLog.info("Interceptor STORAGE_PARTITION_SELECTED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PARTITION_SELECTED - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_TRANSACTION_PROCESSED)
    public void storageTransactionProcessed(
            IBaseBundle theBaseBundle,
            DeferredInterceptorBroadcasts theDeferredInterceptorBroadcasts,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails,
            TransactionDetails theTransactionDetails) {

ourLog.info("Interceptor STORAGE_TRANSACTION_PROCESSED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_TRANSACTION_PROCESSED - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_INITIATE_BULK_EXPORT)
    public void storageInitiateBulkExport(
            BulkExportJobParameters theBulkDataExportOptions,
            RequestDetails theRequestDetails,
            ServletRequestDetails theServletRequestDetails) {

ourLog.info("Interceptor STORAGE_INITIATE_BULK_EXPORT - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_INITIATE_BULK_EXPORT - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_PRESTORAGE_CLIENT_ASSIGNED_ID)
    public void storagePreStorageClientAssignedId(IBaseResource theBaseResource, RequestDetails theRequestDetails) {

ourLog.info("Interceptor STORAGE_PRESTORAGE_CLIENT_ASSIGNED_ID - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_PRESTORAGE_CLIENT_ASSIGNED_ID - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_TRANSACTION_WRITE_OPERATIONS_PRE)
    public void storageTransactionWriteOperationsPre(
            TransactionWriteOperationsDetails theTransactionWriteOperationsDetails,
            TransactionDetails theTransactionDetails) {

ourLog.info("Interceptor STORAGE_TRANSACTION_WRITE_OPERATIONS_PRE - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_TRANSACTION_WRITE_OPERATIONS_PRE - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_TRANSACTION_WRITE_OPERATIONS_POST)
    public void storageTransactionWriteOperationsPost(
            TransactionWriteOperationsDetails theTransactionWriteOperationsDetails,
            TransactionDetails theTransactionDetails) {

ourLog.info("Interceptor STORAGE_TRANSACTION_WRITE_OPERATIONS_POST - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_TRANSACTION_WRITE_OPERATIONS_POST - ended, execution took {}", stopWatch);
        }
    }

@Hook(Pointcut.STORAGE_VERSION_CONFLICT)
    public ResourceVersionConflictResolutionStrategy storageVersionConflict(
            RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) {

ourLog.info("Interceptor STORAGE_VERSION_CONFLICT - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor STORAGE_VERSION_CONFLICT - ended, execution took {}", stopWatch);
        }
        return null;
    }

// should be called when repository validation is enabled
    @Hook(Pointcut.VALIDATION_COMPLETED)
    public ValidationResult validationCompleted(
            IBaseResource theBaseResource, String theRawBaseResource, ValidationResult theValidationResult) {

ourLog.info("Interceptor VALIDATION_COMPLETED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor VALIDATION_COMPLETED - ended, execution took {}", stopWatch);
        }
        return null;
    }

@Hook(Pointcut.INTERCEPTOR_REGISTERED)
    public void interceptorRegistered() {

ourLog.info("Interceptor INTERCEPTOR_REGISTERED - started");
        StopWatch stopWatch = new StopWatch();
        try {
            // your implementation goes here
        } finally {
            ourLog.info("Interceptor INTERCEPTOR_REGISTERED - ended, execution took {}", stopWatch);
        }
    }
}

Copy

Examples: HL7v2 Endpoints

Examples: FHIR Storage

Interceptors

Interceptors Pointcuts Starter Project Examples: FHIR Endpoints Examples: HL7v2 Endpoints Examples: FHIR Storage Examples: FHIR Gateway Examples: FHIR Client Examples: MDM Examples: Subscription Examples: Channel Import Examples: Cluster Manager Examples: App Sphere Examples: System To System Data Exchange 2024.02.01 Migration Guide

Examples: FHIR Gateway