Synchronous Integration

An exchange typically is processed asynchronously. In some cases this might not be possible and/or desirable from a client perspective. For this purpose it is possible to invoke an integration and have it processed in a seemingly synchronous/blocking way.

Consider the following example 'Service Check' to better understand blocking calls.

Service Check

The rest destination "capitations" to reach out to Oracle Health Insurance Value-Based Payments application is configured as:

Fields Configuration Remarks

code

capitations

credentialKey

cap_user

Refer to policies_user configuration in the File Upload example for more details.

addressKey

address.key.cap.baseurl

To set up address key using generic api - /properties the following must be done

POST  http(s)://{host:port}/{oig application context}/generic/properties

with payload:

{
  "name": "address.key.cap.baseurl",
  "value": "URL till OHI Value Based Payments context root
   e.g. http://{host"port}/{context-root}"
}

destinationType

REST

typeConfig

path: {path}

httpMethod: {httpMethod}

In this example the provider code, service code, and as of date are supplied as request parameters. Generic API can be used to GET /organizationproviders details. The system reads the dynamic record 'Capitated Services' to check if the given service is capitated or not. If the service is capitated as of the input date, then the exchange must return the response as 'Service is Capitated', otherwise 'Service is Not Capitated'. This use case can be realized by having a CUSTOM step.

Implement the dynamic logic 'Custom Function' as follows:

import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import java.text.SimpleDateFormat
import javax.ws.rs.core.Response

def jsonPayload = JsonOutput.toJson([
              resource: [q: "code.eq(" + properties.get('providerCode') + ")"]
        ]
        )

Response providers = webTarget("capitation")
        .path("generic").path("organizationproviders/search")
        .request()
        .header("Accept", "application/json")
        .buildPost(Entity.json(jsonPayload))
        .invoke()
        .invoke()

if (providers.status == 200) {
    (new JsonSlurper()
            .parseText(providers.readEntity(String.class)))
            .items.each { item ->

        def serviceCode = properties.get("serviceCode")
        def qualifier = properties.get("qualifier")
        def referenceDate = properties.get("referenceDate")

        def capitatedServicesFiltered = item.capitatedServices.find {
            it.code == serviceCode && it.qualifier == qualifier && dateBetween(it, referenceDate) == true
        }

        if (capitatedServicesFiltered != null) {
            exchangeStep.addLogEntry("Service is capitated.")
            properties.put("result", 'Service is capitated.')
            return "Service is capitated"
        } else {
            exchangeStep.addLogEntry("Service is not capitated.")
            properties.put("result", 'Service is not capitated.')
            return "Service is not capitated"

        }
    }
}

def dateBetween(it, referenceDate) {
    def pattern = "yyyy-MM-dd"
    if (it.endDate == null) {
        return referenceDate >= it.startDate
    } else {
        return referenceDate >= it.startDate && referenceDate <= it.endDate
    }
}

return ""

The integration is configured by sending in the following payload to /integrations generic api

{
    "code": "PROVIDER_SERVICE_CHECK",
    "type": "integration",
    "descr": "PROVIDER_SERVICE_CHECK",
    "integrationSteps": [
        {
            "code": "PROVIDER_SERVICE_CHECK",
            "sequence": 1,
            "subtype":"CUSTOM",
            "outputName":"PROVIDER_SERVICE_CHECK",
             "destination": {
                  "code": "capitation"

             },
            "typeConfig": {"customFunctionCode" :"PROVIDER_SERVICE_CHECK"}

        }
    ]
}

For a blocking call, this integration must be invoked with the following HTTP Headers

Description

ohi-exchange-allowed-time-ms

The maximum allowed time in milliseconds a client is willing to wait for the exchange to complete. Typically, in the order of magnitude of 1 to 5 seconds.

ohi-exchange-execute-blocking

true

Tuning Polling Frequency for Blocking Invocation

To provide a synchronous or blocking experience for a client, the system uses a polling scheme to check the exchange’s progress. After the initial HTTP POST of the client, the system redirects the client to an HTTP GET. This HTTP GET is blocked from the client’s perspective until the exchange reaches a final state or times out. As part of this HTTP GET operation, under the covers, the system starts a poller thread that periodically checks the exchange.

Configure the polling frequency with which this thread is checking using the following system property:

  • ohi.exchange.await.poll.frequency.<0> Shows the polling frequency for an integration to block an exchange. Replace <0> with the actual integration code.