Examples: FHIR Storage
This page contains example interceptors that can be registered with the FHIR Storage module.
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.
/**
* 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 extends ServerOperationInterceptorAdapter {
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.
*/
@Override
public void resourcePreCreate(RequestDetails theRequest, IBaseResource theResource) {
resourcePreUpdate(theRequest, null, 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.
*/
@Override
public void resourcePreUpdate(RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource) {
// This interceptor only cares about Patient resources
if (!(theNewResource instanceof Patient)) {
return;
}
Patient newResource = (Patient) theNewResource;
/*
* We want to know the primary identifier, which is the first instance of
* Patient.identifier where identifer.system = "http://example.com/mrn". If the
* client has submitted a resourece that does not have such an identifier, this
* is an error and we will throw a PreconditionFailedException (HTTP 412)
*/
String primaryIdentifier = newResource
.getIdentifier()
.stream()
.filter(t <i class="fas fa-angle-double-right"></i> t.getSystem().equals("http://example.com/mrn"))
.map(t <i class="fas fa-angle-double-right"></i> t.getValue())
.findFirst()
.orElseThrow(() <i class="fas fa-angle-double-right"></i> new PreconditionFailedException("No MRN supplied with request"));
// 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:9999/mdmquery?mrn=" + primaryIdentifier, HashMap.class);
// 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 = newResource
.getIdentifier()
.stream()
.filter(t <i class="fas fa-angle-double-right"></i> t.getSystem().equals("http://example.com/euid"))
.findFirst()
.orElseGet(() <i class="fas fa-angle-double-right"></i> newResource.addIdentifier());
// Set the identifier value using the web service response
euidIdentifier.setSystem("http://example.com/euid");
euidIdentifier.setValue((String) response.get("euid"));
}
}