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.
Persistence processors require the FHIR Storage (PERSISTENCE_ALL
) module.
smile:persistence/resourceOperationProcessor
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>
smile:persistence/bundleProcessor
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>
ETL Importer Processors require the ETL Importer (ETL_IMPORTER
) module.
smile:etl_import/csvProcessor
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>
Camel processors only require the Camel (CAMEL
) module.
smile:camel/channelImportProcessor
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 < 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>
smile:camel/incrementRetryCountProcessor
See the Example Route in channelImportProcessor above for an example of how it can be used.
smile:camel/script?function=myFunction&input=bundle
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 functionbundle
the input message will be converted into a FHIR bundle before calling the functionhl7v2
the input message will be converted into an HL7v2 message before calling the functionThe 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.
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&input=json"/>
<to uri="mock:jsonResult"/>
</route>
<route id="bundle">
<from uri="direct:bundleStart"/>
<to uri="smile:camel/script?function=processBundle&input=bundle"/>
<to uri="mock:bundleResult"/>
</route>
<route id="hl7v2">
<from uri="direct:hl7v2Start"/>
<to uri="smile:camel/script?function=processHl7v2&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;
}
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:
String
, or an Hl7v2ToFhirConversionResultJsonA description of each Hl7v2 processor is provided below:
Executes the logic inside the Javascript onPreConvertHl7V2ToFhir
callback function.
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.
Executes the logic inside specified by HL7V2IN_PRE_HL7V2_TO_FHIR_MAPPING_PROCESSING
interceptor.
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.
Executes the logic inside the JavascriptonPostConvertHl7V2ToFhir
callback function.
Executes the logic inside specified by theHL7V2IN_POST_HL7V2_TO_FHIR_MAPPING_PROCESSING
interceptor.
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>
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 |