Examples: FHIR Endpoints - Smile CDR Documentation
FHIR Endpoint Examples
This page contains example interceptors that can be registered against a FHIR Endpoint module, including:
- FHIR Endpoint module that is paired with a FHIR Storage module
- Hybrid Providers Endpoint module
- FHIR Gateway module
Example: Override CapabilityStatement Generation
The following interceptor can be used to replace the built-in automatic CapabilityStatement generation provided by Smile CDR. This is useful if you are implementing a specific implementation guide that requires a static CapabilityStatement.
/*-
* #%L
* Smile CDR - CDR
* %%
* Copyright (C) 2016 - 2026 Smile CDR, Inc.
* %%
* All rights reserved.
* #L%
*/
package com.smilecdr.demo.fhirendpoint;
import ca.uhn.fhir.interceptor.api.Interceptor;
import ca.uhn.fhir.rest.server.interceptor.StaticCapabilityStatementInterceptor;
/**
* This interceptor overrides the built-in automatic CpaabilityStatement generator in
* Smile CDR and instead uses a static resource when a client invokes the
* "capabilities" operation (i.e. /metadata)
*/
@Interceptor
public class OverrideCapabilityStatementInterceptor extends StaticCapabilityStatementInterceptor {
/**
* Constructor
*
* Note that this class does not have any @Hook methods since the actual interceptor
* hook is defined in the superclass. We just use this constructor in our
* implementation to configure the interceptor.
*/
public OverrideCapabilityStatementInterceptor() {
// This interceptor uses a CapabilityStatement resource that is available
// on the classpath. This file can be built into the interceptor project by
// placing it in "src/main/resources/", or it can be placed in the Smile CDR
// installation in the "classes/" directory.
setCapabilityStatementResource("static-capabilitystatement.json");
// Alternately, you can build the CapabilityStatement programatically
/*
CapabilityStatement cs = new CapabilityStatement();
cs.setFhirVersion(Enumerations.FHIRVersion._4_0_1);
setCapabilityStatement(cs);
*/
}
}
Copy
Example: Starter Server interceptor for all SERVER_xxx pointcuts
The following example shows an interceptor that can be used as a starter Server interceptor, implementing a hook method for each available pointcut.
import ca.cdr.api.broker.IPublicBrokerSender; import ca.cdr.api.fhir.interceptor.CdrHook; import ca.cdr.api.fhir.interceptor.CdrPointcut; 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.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.ResponseDetails; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.validation.ValidationResult; import ca.uhn.hl7v2.model.Message; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.hl7.fhir.instance.model.api.IBaseConformance; import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; import org.hl7.fhir.instance.model.api.IBaseResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired;
import java.io.Writer; import java.security.KeyStore;
/**
- Sample Server Interceptor implementing all SERVER_XXX pointcuts.
- It is indented to be used in
- FHIR Endpoint module 'Interceptor Bean Types'
- or Hybrid Providers REST Endpoint module 'Interceptor Bean Types'
- or FHIR Gateway REST Endpoint module 'Interceptor Bean Types'.
- Can be used as a starting point for your server interceptor. */ @SuppressWarnings({"unused", "EmptyTryBlock"}) @Interceptor public class ServerInterceptorTemplate {
@Autowired private IPublicBrokerSender myBrokerSender;
private static final Logger ourLog = LoggerFactory.getLogger(ServerInterceptorTemplate.class);
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_PROCESSED) public boolean serverIncomingRequestPreProcessed( HttpServletRequest theHttpServletRequest, HttpServletResponse theHttpServletResponse) {
ourLog.info("Interceptor SERVER_INCOMING_REQUEST_PRE_PROCESSED - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_INCOMING_REQUEST_PRE_PROCESSED - ended, execution took {}", stopWatch); } return true; }
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLER_SELECTED) public boolean serverIncomingRequestPreHandlerSelected( RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails, HttpServletRequest theHttpServletRequest, HttpServletResponse theHttpServletResponse) {
ourLog.info("Interceptor SERVER_INCOMING_REQUEST_PRE_HANDLER_SELECTED - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info( "Interceptor SERVER_INCOMING_REQUEST_PRE_HANDLER_SELECTED - ended, execution took {}", stopWatch); } return true; }
@Hook(Pointcut.SERVER_INCOMING_REQUEST_POST_PROCESSED) public boolean serverIncomingRequestPostProcessed( RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails, HttpServletRequest theHttpServletRequest, HttpServletResponse theHttpServletResponse) {
ourLog.info("Interceptor SERVER_INCOMING_REQUEST_POST_PROCESSED - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_INCOMING_REQUEST_POST_PROCESSED - ended, execution took {}", stopWatch); } return true; }
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED) public void serverIncomingRequestPreHandled( RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails, RestOperationTypeEnum theRestOperationTypeEnum) {
ourLog.info("Interceptor SERVER_INCOMING_REQUEST_PRE_HANDLED - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_INCOMING_REQUEST_PRE_HANDLED - ended, execution took {}", stopWatch); } }
@Hook(Pointcut.SERVER_OUTGOING_RESPONSE) public boolean serverOutgoingResponse( RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails, IBaseResource theBaseResource, ResponseDetails theResponseDetails, HttpServletRequest theHttpServletRequest, HttpServletResponse theHttpServletResponse) {
ourLog.info("Interceptor SERVER_OUTGOING_RESPONSE - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_OUTGOING_RESPONSE - ended, execution took {}", stopWatch); } return true; }
@Hook(Pointcut.SERVER_OUTGOING_WRITER_CREATED) public Writer serverOutgoingWriterCreated( Writer theWriter, RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) {
ourLog.info("Interceptor SERVER_OUTGOING_WRITER_CREATED - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_OUTGOING_WRITER_CREATED - ended, execution took {}", stopWatch); } return theWriter; }
@Hook(Pointcut.SERVER_PROCESSING_COMPLETED_NORMALLY) public void serverProcessingCompletedNormally( RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) {
ourLog.info("Interceptor SERVER_PROCESSING_COMPLETED_NORMALLY - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_PROCESSING_COMPLETED_NORMALLY - ended, execution took {}", stopWatch); } }
@Hook(Pointcut.SERVER_PROCESSING_COMPLETED) public void serverProcessingCompleted( RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) {
ourLog.info("Interceptor SERVER_PROCESSING_COMPLETED - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_PROCESSING_COMPLETED - ended, execution took {}", stopWatch); } }
@Hook(Pointcut.SERVER_OUTGOING_GRAPHQL_RESPONSE) public boolean serverOutgoingGraphqlResponse( RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails, String theQuery, String theResponse, HttpServletRequest theHttpServletRequest, HttpServletResponse theHttpServletResponse) {
ourLog.info("Interceptor SERVER_OUTGOING_GRAPHQL_RESPONSE - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_OUTGOING_GRAPHQL_RESPONSE - ended, execution took {}", stopWatch); } return true; }
@Hook(Pointcut.SERVER_PRE_PROCESS_OUTGOING_EXCEPTION) public BaseServerResponseException serverPreProcessOutgoingException( RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails, Throwable theThrowable, HttpServletRequest theHttpServletRequest, HttpServletResponse theHttpServletResponse) {
ourLog.info("Interceptor SERVER_PRE_PROCESS_OUTGOING_EXCEPTION - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_PRE_PROCESS_OUTGOING_EXCEPTION - ended, execution took {}", stopWatch); } return null; }
@Hook(Pointcut.SERVER_HANDLE_EXCEPTION) public boolean serverHandleException( RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails, HttpServletRequest theHttpServletRequest, HttpServletResponse theHttpServletResponse, BaseServerResponseException theBaseServerResponseException) {
ourLog.info("Interceptor SERVER_HANDLE_EXCEPTION - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_HANDLE_EXCEPTION - ended, execution took {}", stopWatch); } return true; }
@Hook(Pointcut.SERVER_OUTGOING_FAILURE_OPERATIONOUTCOME) public void serverOutgoingFailureOperationOutcome( RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails, IBaseOperationOutcome theBaseOperationOutcome, ResponseDetails theResponseDetails) {
ourLog.info("Interceptor SERVER_OUTGOING_FAILURE_OPERATIONOUTCOME - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here // NOTE: As of HAPI-FHIR v8.6.1 you can Optionally override the HTTP Response Status Code using: // theResponseDetails.setResponseCode(HttpStatus.EXPECTATION_FAILED.value()) } finally { ourLog.info("Interceptor SERVER_OUTGOING_FAILURE_OPERATIONOUTCOME - ended, execution took {}", stopWatch); } }
@Hook(Pointcut.SERVER_CAPABILITY_STATEMENT_GENERATED) public IBaseConformance serverCapabilityStatementGenerated( IBaseConformance theBaseConformance, RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) {
ourLog.info("Interceptor SERVER_CAPABILITY_STATEMENT_GENERATED - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_CAPABILITY_STATEMENT_GENERATED - ended, execution took {}", stopWatch); } return theBaseConformance; }
@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; }
@CdrHook(CdrPointcut.SERVER_CONFIGURATION_KEYSTORE) public KeyStore serverConfigurationKeystore(String theKeyStorePassword) {
ourLog.info("Interceptor SERVER_CONFIGURATION_KEYSTORE - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info("Interceptor SERVER_CONFIGURATION_KEYSTORE - ended, execution took {}", stopWatch); } // should return a valid KeyStore return null; }
@CdrHook(CdrPointcut.HL7V2IN_PRE_HL7V2_TO_FHIR_MAPPING_PROCESSING) public Boolean serverPreHl7v2ToFhirMapping(Message theMessage) {
ourLog.info("Interceptor HL7V2IN_PRE_HL7V2_TO_FHIR_MAPPING_PROCESSING - started"); StopWatch stopWatch = new StopWatch(); try { // your implementation goes here } finally { ourLog.info( "Interceptor HL7V2IN_PRE_HL7V2_TO_FHIR_MAPPING_PROCESSING - ended, execution took {}", stopWatch); }
// return true if this message should keep on being processed. // return false to stop all further processing. return true; } }
Copy
[Starter Project](/content/docs/interceptors/starter_project.html)
Examples: FHIR Endpoints
Interceptors
[Interceptors](/content/docs/interceptors/interceptors.html)
[Pointcuts](/content/docs/interceptors/pointcuts.html)
[Starter Project](/content/docs/interceptors/starter_project.html)
[Examples: FHIR Endpoints](/content/docs/interceptors/examples_fhir_endpoint.html)
[Examples: HL7v2 Endpoints](/content/docs/interceptors/examples_hl7v2_endpoint.html)
[Examples: FHIR Storage](/content/docs/interceptors/examples_fhir_storage.html)
[Examples: FHIR Gateway](/content/docs/interceptors/examples_fhir_gateway.html)
[Examples: FHIR Client](/content/docs/interceptors/examples_fhir_client.html)
[Examples: MDM](/content/docs/interceptors/examples_mdm.html)
[Examples: Subscription](/content/docs/interceptors/examples_subscription.html)
[Examples: Channel Import](/content/docs/interceptors/examples_channel_import.html)
[Examples: Cluster Manager](/content/docs/interceptors/examples_cluster_manager.html)
[Examples: App Sphere](/content/docs/interceptors/examples_app_sphere.html)
[Examples: System To System Data Exchange](/content/docs/interceptors/examples_s2s_data_exchange.html)
[2024.02.01 Migration Guide](/content/docs/interceptors/jakarta_upgrade.html)
[Examples: HL7v2 Endpoints](/content/docs/interceptors/examples_hl7v2_endpoint.html)