Examples: System To System Data Exchange - Smile CDR Documentation

System-to-System Data Exchange Examples

This page contains example interceptors that can be registered with System-to-System Data Exchange.

Example: Custom Member Match

The following interceptor can be used to implement custom patient matching algorithm for the $member-match operation.

/*-
 * #%L
 * Smile CDR - CDR
 * %%
 * Copyright (C) 2016 - 2026 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;
    }
}

Copy

Example: Client Auth Pre Token

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.

import ca.cdr.api.fhir.interceptor.CdrHook; import ca.cdr.api.fhir.interceptor.CdrPointcut; import ca.cdr.api.model.json.OpenIdTokenResponseJson; import ca.uhn.fhir.interceptor.api.Interceptor; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets; import java.util.List;

@Interceptor public class S2SClientAuthPreTokenInterceptorTemplate { private static final Logger ourLog = LoggerFactory.getLogger(S2SClientAuthPreTokenInterceptorTemplate.class);

@CdrHook(CdrPointcut.CLIENT_AUTH_PRE_TOKEN_REQUEST) public OpenIdTokenResponseJson 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 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 OpenIdTokenResponseJson tokenResponse = new OpenIdTokenResponseJson(); // 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; } }


Copy

[Examples: App Sphere](/content/docs/interceptors/examples_app_sphere.html)

Examples: System To System Data Exchange

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)

[2024.02.01 Migration Guide](/content/docs/interceptors/jakarta_upgrade.html)