Examples: System To System Data Exchange
This page contains example interceptors that can be registered with System-to-System Data Exchange.
The following interceptor can be used to implement custom patient matching algorithm for the $member-match operation.
/*-
* #%L
* Smile CDR - CDR
* %%
* Copyright (C) 2016 - 2025 Smile CDR, Inc.
* %%
* All rights reserved.
* #L%
*/
package com.smilecdr.demo.s2sdataexchange;
import ca.cdr.api.fhir.interceptor.CdrHook;
import ca.cdr.api.fhir.interceptor.CdrPointcut;
import ca.cdr.api.fhir.interceptor.MemberMatchRequest;
import ca.uhn.fhir.interceptor.api.Interceptor;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.util.StopWatch;
import org.hl7.fhir.r4.model.Patient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"unused", "EmptyTryBlock"})
@Interceptor
public class S2SDataExchangeInterceptorTemplate {
private static final Logger ourLog = LoggerFactory.getLogger(S2SDataExchangeInterceptorTemplate.class);
@CdrHook(CdrPointcut.MEMBER_MATCH)
public Patient channelImportMessagePreProcessed(
MemberMatchRequest theMemberMatchRequest, RequestDetails theRequestDetails) {
ourLog.info("Interceptor MEMBER_MATCH - started");
StopWatch stopWatch = new StopWatch();
try {
// your implementation goes here
} finally {
ourLog.info("Interceptor MEMBER_MATCH - ended, execution took {}", stopWatch);
}
// should return a Patient if matching patient is found or null otherwise
return null;
}
}
The following interceptor can be used to implement custom authentication for $invoke-export operation. It provides the request to be sent to the default authentication server and allows to return a custom token provided by the interceptor.
The request headers change between tokens to be retrieved from $member-match and $batch-export as the latter includes the member-id for the member that is to be exported.
@Interceptor
public class S2SClientAuthPreTokenInterceptorTemplate {
private static final Logger ourLog = LoggerFactory.getLogger(S2SClientAuthPreTokenInterceptorTemplate.class);
@CdrHook(CdrPointcut.CLIENT_AUTH_PRE_TOKEN_REQUEST)
public OpenIdTokenResponse getToken(HttpRequestBase requestBase) {
ourLog.info(
"------------------------------------------------- Interceptor CLIENT_AUTH_PRE_TOKEN_REQUEST - called with\n {}",
requestBase);
String myMemberId = "";
// request base will most likely be an HttpPost.
if (requestBase instanceof HttpEntityEnclosingRequestBase) {
HttpEntityEnclosingRequestBase entityRequest = (HttpEntityEnclosingRequestBase) requestBase;
HttpEntity entity = entityRequest.getEntity();
if (entity != null) {
try {
String body = EntityUtils.toString(entity);
ourLog.info(
"------------------------------------------------- Interceptor CLIENT_AUTH_PRE_TOKEN_REQUEST\nRequest form data: {}",
body);
List<NameValuePair> params = URLEncodedUtils.parse(body, StandardCharsets.UTF_8);
for (NameValuePair param : params) {
if ("member_id".equalsIgnoreCase(param.getName())) {
ourLog.info("Found member_id: {}", param.getValue());
myMemberId = param.getValue();
break;
}
}
} catch (Exception e) {
ourLog.error("Failed to read form data", e);
}
} else {
ourLog.warn("Request entity is null");
}
} else {
ourLog.warn("Request is not an instance of HttpEntityEnclosingRequestBase");
}
// Here is where logic for generating and signing assertions by calling custom OAuth servers should happen
OpenIdTokenResponse tokenResponse = new OpenIdTokenResponse();
// adjust input prams
// go get token
tokenResponse.setAccessToken("THIS_WOULD_BE_A_TOKEN with member id: '" + myMemberId + "'");
// returning null as tokenResponse would end up as an error in continuing execution
return tokenResponse;
}
}
You are about to leave the Smile Digital Health documentation and navigate to the Open Source HAPI-FHIR Documentation.