Call to External Service
Introduction
There is a need to be able to call out for data in an external system. A couple of examples:
-
enrich a claimLine with a value such as a Service Category, that is derived externally .
-
distribute a claim level amount between its claim lines for Coordination of Benefits.
The call to an external service can be called anywhere in dynamic logic and from each type of dynamic logic. It is a synchronous call to an external webservice and follows patterns for other synchronous calls, like a time-out. The schema is owned by the external service. The XML message that complies with the schema definition is constructed in the dynamic logic.
The callout functionality described here is not to be confused with the functionality of claim callout rules. Claim callout rules also allow for asynchronous callouts. Also, callouts as a consequence of claim callout rules are tracked in the claim status history. Refer to the text in the "Claim Callouts" pages in the Process Rules chapter of the Configuration Guide. |
Concepts
Using MarkupBuilder
Use the groovy MarkupBuilder to construct the XML message in a way that follows the structure of the XML message. The root element and the attributes of the root element are specified when invoking the MarkupBuilder
def writer = new StringWriter() def xml = new groovy.xml.MarkupBuilder(writer) xml.RootElement(attribute1: "value1"){} writer.toString()
yields
<RootElement attribute1="value1" />
See also the use cases at the end.
For invoking the web service, a utility class is used: ohiWebService.
This class:
-
wraps the XML message in a SOAP envelope
-
delivers the message to the endpoint as configured in the configuration file
-
extracts the XML response from the envelope
-
logs requests/responses
-
raises an error when the response is not received within the timeout.
It is not possible to use:
-
Payload Validation: the payload of a message is not validated before sending it to the external web service. The payload that is returned is also not validated.
-
Availability Tracking: Claims does not keep track of the availability of web services that are called from Dynamic Logic.
-
WS-Security: calling web services that require WS-Security features.
-
Asynchronous services.
Endpoints
The endpoints used by ohiWebService are configured in the Claims properties. Since the call is synchronous the service uses one endpoint per Service. For Example: ServiceCategory.
ohi.ServiceCategory.endpoint.request |
http://machine.domain:port/application_name/ServiceCategoryRequestService |
This endpoint is used by ohiWebService for the service with the name "ServiceCategory"
ohiWebService uses the value of the ohi.ServiceCategory.endpoint.request property. Refer to Property Management for more information on setting a property.
def ws = new OhiWebService("ServiceCategory")
Error Handling
No Response
If no response is received within the timeout, ohiWebService will raise the following exception:
OHI-FL-WSCL-002: Could not invoke the external service <ServiceName>, exception is : <Exception Message>
If the dynamic logic does not handle this exception:
-
a message is written to the log
-
the processing of the claim stops.
Use Cases
Calculate the Service Category for a Claim Line.
This example shows how to determine the service category for one claim line externally.
Sample XML Request
<ServiceCategoryRequest version="4"> <procedureCode>P100</procedureCode> <location>L42</location> </ServiceCategoryRequest >
Sample XML Response
<ServiceCategoryResponse> <source>dft</source> <serviceCategory>SC56</serviceCategory> </ServiceCategoryResponse>
Dynamic Logic
def ws = new OhiWebService("ServiceCategory") def writer = new StringWriter() def xml = new groovy.xml.MarkupBuilder(writer) xml.ServiceCategoryRequest(version:4){ procedureCode( claimLine.procedure.code ) location( claimLine.locationProvider.code ) } def resp = ws.invoke(writer.toString()) def result = new XmlSlurper().parseText(resp)
Typically, this would be embedded in an End Benefits Derivation Rule at Claim Line Level |
Calculate the Service Category for all Claim Lines in a Claim
This example shows how the service category for all the claim lines in one claim can be determined externally in one call out. Note that each request in the message has a code that is used to correlate the response with the corresponding claim line.
Sample XML Request:
<ServiceCategoryRequest version="4"> <requests> <request code="560"> <procedureCode>P100</procedureCode> <location>L40</location> </request> <request code="561"> <procedureCode>P101</procedureCode> <location>L41</location> </request> </requests> </ServiceCategoryRequest >
Sample XML Response:
<ServiceCategoryResponse> <responses> <response code="560"> <serviceCategory>SC56</serviceCategory> </response> <response code="561"> <serviceCategory>SC77</serviceCategory> </response> </responses> </ServiceCategoryResponse>
Dynamic Logic:
Typically, this would also be embedded in an End Benefits Derivation Rule at Claim Level
def ws = new OhiWebService("ServiceCategory") def writer = new StringWriter() def xml = new groovy.xml.MarkupBuilder(writer) xml.ServiceCategoryRequest(version:4){ requests { claim.claimLineList.each { claimLine -> request(code: claimLine.code) { procedureCode( claimLine.procedure.code ) location( claimLine.locationProvider.code ) } } } } def resp = ws.invoke(writer.toString()) def result = new XmlSlurper().parseText(resp) // Update each claimLine by finding the corresponding response in the XML claim.claimLineList.each { claimLine -> def response = result.responses.response.find{ it.@code.text() == claimLine.code.toString() } assert response.size() == 1, "No response found for " + claimLine.code claimLine.serviceCategory = response.@serviceCategory.toString() }
Distribute Claim Amount over Claim Lines
This example shows how the amount that another insurance company paid (dynamic field OICPaid at the claim level) is distributed over the claim lines.
Dynamic Logic
Typically, this would be embedded in a Pre Benefits Derivation Rule at Claim Level.
Per claim line it allocates a share of the OIC paid at the claim level to the line until the OIC paid is out. To the lines that are allocated a part of the Claim level OIC paid the message with the code '1234' is attached.
if (claim.OICPaid > 0 { def OICPaidLeft = claim.OICPaid claim.claimLineList.sort{it.sequence}.each{claimLine -> if (OICPaidLeft > 0) {claimLine.OICPaid = Math.min(claimLine.allowedAmount.amount, OICPaidLeft); OICPaidLeft = OICPaidLeft - claimLine.allowedAmount.amount claimLine.addMessage("1234") // Add a message with the code '1234' } else {claimLine.OICPaid = 0 } } }