Welcome to Smile CDR

Getting Started

Tutorial and Tour

FHIR Storage

FHIR Hybrid Providers

FHIR Gateway

Security

Clustering

HL7 v2.x Support

CDA Exchange Module

Bulk Operations

Monitoring

JSON Admin Endpoints

Product Configuration

Modules

JavaScript Execution Environment

Database Administration

Configuration Categories

Smile CDR CLI (smileutil)

Product Reference

Appendix

4.8 Subscription

 

The FHIR standard specifies a powerful mechanism for push-based notification of changes in the repository. This mechanism is called Subscription.

A Subscription is a publish-subscribe (pub/sub) mechanism built into the FHIR specification. Subscriptions are defined using the Subscription resource, which specifies what type of data is being subscribed to and how the recipient should be notified.

The Subscription Resource

A simple example of a Subscription resource follows:

{
  "resourceType": "Subscription",
  "status": "requested",
  "criteria": "Patient?name=smith",
  "channel": {
    "type": "rest-hook",
    "endpoint": "http://example.com:8080/fhir",
    "payload": "application/json"
  }
}

The Subscription resource contains several important fields:

  • status – When a Subscription is created by a client, it should have a status of requested. Smile CDR will process this Subscription, and if it is valid, the status will automatically be changed to active, meaning that the Subscription is now being processed.
  • criteria – This is a FHIR search query URL that will be used to determine which resources apply to the Subscription. These resources will trigger a notification when they change. See Criteria below for more information.
  • channel.type – This is the mechanism for delivery, such as rest-hook, websocket, email, sms, or message. See Channel Types below for more information.
  • channel.endpoint – For channel types that require the server to initiate a connection to the client, this is the URL of the endpoint to which the server should connect.
  • channel.payload – This is the mimetype encoding to use (e.g. application/fhir+json for JSON data).

4.8.1 Smile CDR Subscription Architecture

 

An overview of the Smile CDR Subscription architecture is illustrated in the following diagram:

Subscription Overview

Note that subscription processing is not enabled by default. If you wish to use subscription processing in your system, you must enable it by using specific configuration properties for the types of subscriptions you wish to enable. For example, the subscription.rest_hook.enabled configuration property may be used to enable REST Hook subscriptions (see below).

4.8.2 Criteria

 

When any resources that match Subscription.criteria are created or updated, the specified notification will occur. For example, if the Subscription specifies a criteria of Patient?name=smith then a notification will occur any time a Patient named “smith” is created or updated.

4.8.3 Channel Types

 

The following sections outline the various channel types (delivery mechanisms) that are supported by Smile CDR.

4.8.4 Channel Type: rest-hook

 

The rest-hook channel type specifies that Smile CDR should create an HTTP REST request to a FHIR endpoint any time that a resource changes that matches the given subscription.

For example, suppose a Subscription is created with the following values:

{
  "resourceType": "Subscription",
  "status": "active",
  "criteria": "Patient?name=smith",
  "channel": {
    "type": "rest-hook",
    "endpoint": "http://example.com:8080/fhir",
    "payload": "application/json"
  }
}

In this case, if a new Patient is created with the name “Smith”, and the FHIR Storage module assigns it an ID of 123, an HTTP PUT will be performed to the address http://example.com:8080/fhir/Patient/123 with the resource body as the payload.

REST Hook Extensions

Smile CDR supports several extensions to the Subscription mechanism.

Replication Mode

In replication mode, Smile CDR assumes that it is replicating all matching resources from one Smile CDR instance to another Smile CDR instance. This allows the server to make assumptions about how operations may be batched and sequenced. The following Subscription example shows a replication subscription:

{
  "resourceType": "Subscription",
  "status": "active",
  "reason": "Monitor new neonatal function (note, age will be determined by the monitor)",
  "criteria": "Observation?code=SNOMED-CT|1000000050",
  "channel": {
    "extension": [
      {
        "url": "https://smilecdr.com/fhir/ns/StructureDefinition/subscription-channel-rest-replicate-mode",
        "valueBoolean": true
      },
      {
        "url": "https://smilecdr.com/fhir/ns/StructureDefinition/subscription-channel-rest-replicate-id-prefix",
        "valueString": "CDR1-"
      }
    ],
    "type": "rest-hook",
    "endpoint": "http://localhost:40243/fhir/context",
    "payload": "application/json"
  }
}

Note the following two extensions:

URLTypeDescription
https://smilecdr.com/fhir/ns/StructureDefinition/subscription-channel-rest-replicate-mode boolean If set to true, this subscription will be delivered in replication mode.
https://smilecdr.com/fhir/ns/StructureDefinition/subscription-channel-rest-replicate-id_prefix string If specified, all resource IDs will be prefixed with the given prefix (both in IDs, and in references to those IDs from other resources). This is useful in situations where you want to be able to replicate data from several source CDR instances to one target CDR instance, or in cases where the source CDR instance is using numeric IDs (since Smile CDR will not allow client-provided numeric IDs).

If the replication is being sent to a second Smile CDR instance, you may wish to enable the dao_config.auto_create_placeholder_reference_targets.enabled configuration property on the replication target persistence module. This means that if payloads are received out-of-order by the receiving system, no payload will be rejected simply because it contains a reference to a resource that has not yet been received.

Strip Version IDs

By default, the resource version ID is included when delivering a resource to the REST HOOK receiving endpoint. This can be disabled using an extension on the REST HOOK channel.

{
  "resourceType": "Subscription",
  "status": "active",
  "reason": "Monitor new neonatal function (note, age will be determined by the monitor)",
  "criteria": "Observation?code=SNOMED-CT|1000000050",
  "channel": {
    "extension": [
      {
        "url": "http://hapifhir.io/fhir/StructureDefinition/subscription-resthook-strip-version-ids",
        "valueBoolean": true
      }
    ],
    "type": "rest-hook",
    "endpoint": "http://localhost:40243/fhir/context",
    "payload": "application/json"
  }
}

Note the following extension:

URLTypeDescription
http://hapifhir.io/fhir/StructureDefinition/subscription-resthook-strip-version-ids boolean If set to true, the deliverer will strip the resource version ID before sending the resource

Delivering Latest Version

By default if a resource is created and then updated in rapid succession, the deliverer will deliver versions 1 and 2 to the REST HOOK target.

This can be adjusted so that if the resource gets updated before the deliverer manages to transmit the resource, only the latest version will be transmitted (and it may be delivered more than once).

{
  "resourceType": "Subscription",
  "status": "active",
  "reason": "Monitor new neonatal function (note, age will be determined by the monitor)",
  "criteria": "Observation?code=SNOMED-CT|1000000050",
  "channel": {
    "extension": [
      {
        "url": "http://hapifhir.io/fhir/StructureDefinition/subscription-resthook-deliver-latest-version",
        "valueBoolean": true
      }
    ],
    "type": "rest-hook",
    "endpoint": "http://localhost:40243/fhir/context",
    "payload": "application/json"
  }
}

Note the following extension:

URLTypeDescription
http://hapifhir.io/fhir/StructureDefinition/subscription-resthook-deliver-latest-version boolean If set to true, the deliverer will attempt to send only the latest version of a resource.

Custom Delivery Class

Users may also supply a custom Java class that will be used to deliver the resource instead of the built-in FHIR client. This is useful in cases where you want to customize the delivery (e.g. by adding special attributes or filters, or by using another protocol altogether instead of FHIR/REST).

The following example shows a subscription that uses a custom delivery class:

{
  "resourceType": "Subscription",
  "id": "1",
  "meta": {
    "versionId": "1",
    "lastUpdated": "2017-08-19T16:52:11.041-04:00"
  },
  "status": "active",
  "reason": "Monitor new neonatal function (note, age will be determined by the monitor)",
  "criteria": "Observation?code=SNOMED-CT|1000000050&_format=xml",
  "channel": {
    "extension": [
      {
        "url": "https://smilecdr.com/fhir/ns/StructureDefinition/subscription-channel-rest-delivery-class",
        "valueString": "org.example.MyDeliverer"
      }
    ],
    "type": "rest-hook",
    "endpoint": "http://localhost:40243/fhir/context",
    "payload": "application/json",
    "header": [
      "Authorization: Bearer 123"
    ]
  }
}

Note the following extension:

URLTypeDescription
https://smilecdr.com/fhir/ns/StructureDefinition/subscription-channel-rest-delivery-class string This is the class name for the Java class that implements the ISubscriptionDeliverer interface.

The following example shows a simple delivery class:

public class ExampleDeliverer implements ISubscriptionDeliverer {

	private Logger ourLog = LoggerFactory.getLogger(ExampleDeliverer.class);

	/**
	 * Deliver the resource
	 *
	 * @param theOperation    The operation triggering this delivery
	 * @param theSubscription The subscription
	 * @param theResource     The resource
	 */
	@Override
	public void deliver(RestOperationTypeEnum theOperation, IBaseResource theSubscription, IBaseResource theResource) {

		// We will just log the resource; however, we would probably send it somewhere in a real scenario
		String id = theResource.getIdElement().getValue();
		ourLog.info("REST delivery type {} for resource {}", theOperation, id);

	}

}

4.8.5 Channel Type: email

 

The email channel type uses an SMTP relay to deliver notification about changed resources to the recipient. The contents, recipient, and body of the transmitted email may be specified using properties in the Subscription.

For example, the following example shows a simple email subscription:

{
  "resourceType": "Subscription",
  "status": "requested",
  "reason": "Monitor new emergency department encounters",
  "criteria": "Encounter?class=http://hl7.org/fhir/v3/ActCode|EMER",
  "channel": {
    "type": "email",
    "endpoint": "mailto:foo@example.com",
    "payload": "An Emergency Department encounter has been created or updated."
  }
}

Note the following fields:

  • endpoint – The endpoint must be set to a `mailto:` URI that will be treated as the recipient email address. Additional recipients may be specified by using comma-separated values (e.g. mailto:recipient1@example.com,recipient2@example.com).
  • payload – The payload is used as the body of the email.

Email Extensions

HAPI FHIR and Smile CDR provide several extensions that may be placed on the Subscription.channel element:

URLTypeDescription
http://hapifhir.io/fhir/StructureDefinition/subscription-email-from uri If specified, this extension contains the "from" address that the email will show as the sender.
http://hapifhir.io/fhir/StructureDefinition/subscription-email-subject-template string If specified, this extension contains the subject of the email being sent.

An example resource including these extensions is shown below.

{
  "resourceType": "Subscription",
  "status": "requested",
  "reason": "Monitor new emergency department encounters",
  "criteria": "Encounter?class=http://hl7.org/fhir/v3/ActCode|EMER",
  "channel": {
    "extension": [
      {
        "url": "http://hapifhir.io/fhir/StructureDefinition/subscription-email-from",
        "valueUri": "mailto:myfrom@from.com"
      },
      {
        "url": "http://hapifhir.io/fhir/StructureDefinition/subscription-email-subject-template",
        "valueString": "This is a subject."
      }
    ],
    "type": "email",
    "endpoint": "mailto:foo@example.com",
    "payload": "This is the body."
  }
}

4.8.6 Other Channel Types

 

Other channel types (e.g. sms) are not yet supported. Please let us know if you would like to use one of them.

4.8.7 Manually Triggering Subscriptions

 
Re-Triggering Subscriptions requires the FHIR_TRIGGER_SUBSCRIPTION permission.

It is sometimes desirable to have a Subscription “trigger” for a specific resource. This concept is easiest to explain with an example:

Suppose a REST HOOK subscription Subscription/123 exists with criteria Observation?status=complete. When an Observation is created with the given status, the subscription will deliver a notification to its intended target. Now suppose you want to manually cause your Observation to be processed a second time (and ultimately re-delivered, assuming it still matches the Subscription criteria) without modifying the Observation.

The $trigger-subscription operation can be useful in order to cause this subsequent “triggering” to occur.

Triggering a Resource by ID

In order to cause Observation/6 to be triggered for Subscription/123, the following Parameters resource should be crafted as an operation parameter. Multiple IDs may be specified using multiple parameter repetitions.

{
  "resourceType": "Parameters",
  "parameter": [
    {
      "name": "resourceId",
      "valueUri": "Observation/6"
    }
  ]
}

Triggering a Larger Set of Resources

Instead of individual resource IDs, a search URL may be used to request a group of resources to be triggered.

{
  "resourceType": "Parameters",
  "parameter": [
    {
      "name": "searchUrl",
      "valueString": "Observation?date=2018-10-16"
    }
  ]
}

Executing

This Parameters resource is then POSTed to the FHIR endpoint via a URL such as the following (the following triggers the resource for the subscription Subscription/123):
http://localhost:8000/Subscription/123/$trigger-subscription

This Parameters resource may also be POSTed to the Subscription type (instead of an individual Subscription) in order to trigger the resource to all active Subscriptions for which it matches:
http://localhost:8000/Subscription/$trigger-subscription