Smile CDR v2024.02.PRE
On this page:

42.1.1Smile Processors Overview

 

Smile provides a number of custom processors that can be used to call Smile module services.

A list of Smile processors by module can be found below.

42.1.2Persistence Processors

 

Persistence processors require the FHIR Storage (PERSISTENCE_ALL) module.

42.1.2.1resourceOperationProcessor

  • Example URI: smile:persistence/resourceOperationProcessor
  • Description: Performs the operation represented by the input message. E.g. If the Resource Operation was a Patient CREATE, then it would create that patient in the specified Storage Module.

42.1.2.1.1Example Route

Resource Operations messages posted to the resource-operation-message-in-topic will get processed by the module with id persistence.

<routes xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="kafka:resource-operation-message-in-topic?brokers=localhost:9092"/>
        <to uri="smile:persistence/resourceOperationProcessor"/>
    </route>
</routes>

42.1.2.2bundleProcessor

  • Example URI: smile:persistence/bundleProcessor
  • Description: This is the same as resourceOperationProcessor except instead of performing a resource operation, it posts a bundle as a transaction to the specified Storage Module.

42.1.2.2.1Example Route

Bundles posted to the bundle-in-topic will get processed by the module with id persistence.

<routes xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="kafka:bundle-in-topic?brokers=localhost:9092"/>
        <to uri="smile:persistence/bundleProcessor"/>
    </route>
</routes>

42.1.3ETL Importer Processors

 

ETL Importer Processors require the ETL Importer (ETL_IMPORTER) module.

42.1.3.1csvProcessor

  • Example URI: smile:etl_import/csvProcessor
  • Description: This processor submits csv strings to an ETL Import Module for processing.

42.1.3.1.1Example Route

A multi-line CSV String posted to the etl-in-topic will get processed by the module with id etl_import.

<routes xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="kafka:etl-in-topic?brokers=localhost:9092"/>
        <to uri="smile:etl_import/csvProcessor"/>
    </route>
</routes>

42.1.4Camel Processors

 

Camel processors only require the Camel (CAMEL) module.

42.1.4.1channelImportProcessor

  • Example URI: smile:camel/channelImportProcessor
  • Description: Performs similar functionality to the Channel Import Module. Note that this processor assumes that retry and failure processing will be handled by the Camel route. This functionality assumes the JavaScript functions used by ChannelImport are defined in the Camel Module. Note that even though this processor is called channelImportProcessor, it does not interact with a Channel Import Module in any way. It is provided to give users an option to migrate from the Channel Import Module to the Camel Module.

42.1.4.1.1Example Route

The following routes fully replicate the functionality in the Channel Import Module when a ResourceOperationJsonMessage message is posted to the kafka topic called channel-import-in-topic.

<routes xmlns="http://camel.apache.org/schema/spring">
	<route id="channelImportProcessor">
		<from uri="kafka:channel-import-in-topic?brokers=localhost:9092"/>
		<to uri="direct:processMessage"/>
	</route>

	<route id="processResourceOperationMessage">
		<from uri="direct:processMessage"/>
		<onException>
			<exception>ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException</exception>
			<exception>ca.uhn.fhir.rest.server.exceptions.InvalidRequestException</exception>
			<exception>ca.uhn.fhir.rest.server.exceptions.InternalErrorException</exception>
			<handled>
				<constant>true</constant>
			</handled>
			<to uri="smile:camel/incrementRetryCountProcessor"/>
			<log logName="ca.cdr.camel" message="Error processing ${body}.  Sending to retry queue." loggingLevel="DEBUG"/>
			<to uri="kafka:test.retry?brokers=localhost:9092"/>
		</onException>
		<onException>
			<exception>java.lang.Exception</exception>
			<handled>
				<constant>true</constant>
			</handled>
			<to uri="direct:failureQueue"/>
		</onException>
		<log logName="ca.cdr.camel" message="Processing Resource Operation ${body}" loggingLevel="DEBUG"/>
		<to uri="smile:camel/channelImportProcessor"/>
	</route>

	<route id="retryResourceOperationMessage">
		<from uri="kafka:test.retry?brokers=localhost:9092"/>
		<when>
			<jsonpath>$.headers[?(@.retryCount &lt; 3)]</jsonpath>
			<delay>
				<constant>1000</constant>
			</delay>
			<log logName="ca.cdr.camel" message="Retrying ${body}" loggingLevel="DEBUG"/>
			<to uri="direct:processMessage"/>
		</when>
		<otherwise>
			<to uri="direct:failureQueue"/>
		</otherwise>
	</route>

	<route id="failureQueue">
		<from uri="direct:failureQueue"/>
		<log logName="ca.cdr.camel" message="Error processing ${body}.  Sending to Failure queue." loggingLevel="DEBUG"/>
		<to uri="kafka:test.failed?brokers=localhost:9092"/>
	</route>
</routes>

42.1.4.2incrementRetryCountProcessor

  • Example URI: smile:camel/incrementRetryCountProcessor
  • Description: This increments the retry count in a BaseJsonMessage (e.g. on a ResourceOperationJsonMessage).

See the Example Route in channelImportProcessor above for an example of how it can be used.

42.1.4.3script

  • Example URI: smile:camel/script?function=myFunction&input=bundle
  • Description: This calls an arbitrary JavaScript function with the input from the route. The optional input parameter will convert the input data before calling the function. If no input parameter is specified, the input will be passed to the function as a String. The following input formats are currently supported:
    • json the input message will be converted into a Json document before calling the function
    • bundle the input message will be converted into a FHIR bundle before calling the function
    • hl7v2 the input message will be converted into an HL7v2 message before calling the function
    • if no input parameter is provided, the input message will be converted into a String before calling the function.

The return value of the function will be passed to the next step in the route.

All functions called by this processor must be defined in the Camel Module.

42.1.4.3.1Example Routes

Below are example routes using the script processor with each of these input types:

<routes xmlns="http://camel.apache.org/schema/spring">
    <route id="string">
        <from uri="direct:stringStart"/>
        <to uri="smile:camel/script?function=processString"/>
        <to uri="mock:stringResult"/>
    </route>

    <route id="json">
        <from uri="direct:jsonStart"/>
        <to uri="smile:camel/script?function=processJson&amp;input=json"/>
        <to uri="mock:jsonResult"/>
    </route>

    <route id="bundle">
        <from uri="direct:bundleStart"/>
        <to uri="smile:camel/script?function=processBundle&amp;input=bundle"/>
        <to uri="mock:bundleResult"/>
    </route>

    <route id="hl7v2">
        <from uri="direct:hl7v2Start"/>
        <to uri="smile:camel/script?function=processHl7v2&amp;input=hl7v2"/>
        <to uri="mock:hl7v2Result"/>
    </route>
</routes>

Here are some example JavaScript functions that would work with the above routes:

function processString(string) {
   var parts = string.split(/\s+/)

   var patient = ResourceBuilder.build('Patient');
   patient.name[0].given[0] = parts[0];
   patient.name[0].family = parts[1];

   return patient;
}

function processJson(json) {
// Create a patient
   var parts = json.name.split(/\s+/)

   var patient = ResourceBuilder.build('Patient');
   patient.name[0].given[0] = parts[0];
   patient.name[0].family = parts[1];

// Add the patient to a transaction bundle
   var transaction = TransactionBuilder.newTransactionBuilder();
   transaction.create(patient);

   return transaction;
}

function processBundle(bundle) {
   var resources = bundle.entryResources();
   return resources[0].name[0].family;
}

function processHl7v2(message) {
   // Create a patient from an ORU_R01 message
   var patient = ResourceBuilder.build('Patient');
   patient.name[0].family = message['/PATIENT_RESULT[0]/PATIENT/PID-5[0]-1'];
   patient.name[0].given[0] = message['/PATIENT_RESULT[0]/PATIENT/PID-5[0]-2'];

   // Add the patient to a transaction bundle
   var transaction = TransactionBuilder.newTransactionBuilder();
   transaction.create(patient);

   return transaction;
}

42.1.5Hl7v2 Inbound Processors

 

Hl7v2 Inbound Processors require the HL7 v2.x Listening Endpoint (ENDPOINT_HL7V2_IN) module. These processors execute each message transformation step of the HL7 v2.x listening endpoint module.

Each Hl7v2 processor has the specifications below:

A description of each Hl7v2 processor is provided below:

42.1.5.1hl7v2ToFhirPreConvertScriptProcessor

Executes the logic inside the Javascript onPreConvertHl7V2ToFhir callback function.

42.1.5.2hl7v2ToFhirPreConvertMapperBeanProcessor

This processor is for backwards compatibility to support custom Mapper Bean Types.

For pre-convert and post-convert customizations, Javascript callbacks (onPreConvertHl7V2ToFhir, onPostConvertHl7V2ToFhir), or Java interceptors (HL7V2IN_PRE_HL7V2_TO_FHIR_MAPPING_PROCESSING, HL7V2IN_POST_HL7V2_TO_FHIR_MAPPING_PROCESSING) should be used instead.

Executes the logic inside the specified custom mapper bean class.

42.1.5.3hl7v2ToFhirPreConvertInterceptorProcessor

Executes the logic inside specified by HL7V2IN_PRE_HL7V2_TO_FHIR_MAPPING_PROCESSING interceptor.

42.1.5.4hl7v2ToFhirProcessor

Translates an incoming HL7V2 message into FHIR transaction Bundles using the Smile generic mapper. These Bundles are placed in the bundles field of the outputted Hl7v2ToFhirConversionResultJson.

42.1.5.5hl7v2ToFhirPostConvertScriptProcessor

Executes the logic inside the JavascriptonPostConvertHl7V2ToFhir callback function.

42.1.5.6hl7v2ToFhirPostConvertInterceptorProcessor

Executes the logic inside specified by theHL7V2IN_POST_HL7V2_TO_FHIR_MAPPING_PROCESSING interceptor.

42.1.5.6.1Sample Route

The following route receives an HL7v2 message from a kafka topic called in-topic and passes it to the pre-convert customization points, the generic Smile Hl7v2-to-FHIR mapper, and the post-convert customization points of the HL7 v2.x listening endpoint module.

After the last Hl7v2 processor has finished executing (i.e. hl7v2ToFhirPostConvertInterceptorProcessor) Camel is used check to make sure the doProcess flag is still true and no errors occurred during the conversion process.

If this check succeeds, the converted bundles of the Hl7v2ToFhirConversionResultJson are persisted using the bundleProcessor.

If the checks are not successful, the entire Hl7v2ToFhirConversionResultJson is posted to the kafka error-topic.

<routes xmlns="http://camel.apache.org/schema/spring">
   <route>
      <from uri="kafka:in-topic?brokers=localhost:9092"/>
      <to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirPreConvertScriptProcessor"/>
      <to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirPreConvertMapperBeanProcessor"/>
      <to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirPreConvertInterceptorProcessor"/>
      <to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirProcessor"/>
      <to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirPostConvertScriptProcessor"/>
      <to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirPostConvertInterceptorProcessor"/>
      <choice>
         <when>
            <spel>#{body.isDoProcess() and !body.hasErrorIssues()}</spel>
            <split>
               <spel>#{body.bundles}</spel>
               <to uri="smile:persistence/bundleProcessor"/>
            </split>
         </when>
         <otherwise>
            <to uri="kafka:error-topic?brokers=localhost:9092"/>
         </otherwise>
      </choice>
   </route>
</routes>

42.1.6Quick Reference

 
Module Type Processor Name Input
PERSISTENCE_ALL resourceoperationprocessor ResourceOperationJsonMessage
bundleProcessor IBaseBundle
ETL_IMPORTER csvProcessor String
CAMEL channelImportProcessor ResourceOperationJsonMessage
incrementRetryCountProcessor BaseJsonMessage
script JSON, IBaseBundle or Hl7v2 Message
ENDPOINT_HL7V2_IN hl7v2ToFhirPreConvertScriptProcessor Hl7v2 message as a String or Hl7v2ToFhirConversionResultJson
hl7v2ToFhirPreConvertMapperBeanProcessor
hl7v2ToFhirPreConvertInterceptorProcessor
hl7v2ToFhirProcessor
hl7v2ToFhirPostConvertScriptProcessor
hl7v2ToFhirPostConvertInterceptorProcessor