External Callout

Dynamic logic configured for integration steps can perform callouts. From a configuration perspective this leverages the information that is contained in a Destination record. Effectively the attributes addressKey and credentialKey are used. Then from a piece of Groovy dynamic logic, one can initialize a callout by invoking the webTarget predefined method. This method takes the identifying code of a configured destination as input, returning a JAX-RS WebTarget instance. This WebTarget instance can then be used to further construct the actual callout.

webTarget and configuration elements

As mentioned in the introduction there are two specific elements of a Destination configuration that are of importance for callouts.

  • addressKey

        This holds a value for which an OHI System Property needs to be defined, that
    specifies the base segment of the URI from which a complete address is to be
    formulated. As an example, say the value is configured to be
    "address.key.policies.application", there needs to be a OHI System Property
    defined at runtime that maps this key (e.g. a property value of:
    http://machine:8090/policies/<context-root>"). Please note, for OHI
    applications, the URL value should be at least till the context root of the
    application.
    *   credentialKey
        This holds a value that is used to obtain a cached JAX-RS client for which an
    applicable authentication mechanism is activated. In case the configured
    destination does not specify a value for this credentialKey, this means that no
    authentication mechanism is used for the callout. On the other hand when a value
    __is__ specified, an authentication mechanism is set up that matches the
    OHI System Property value that is defined for:
    "ohi.service.<credentialKey>.client.authentication".

Traversing Location header through webTarget

Typically when you use a <tt>webTarget</tt> in a POST action to create a resource, a system responds with a HTTP Response code of 201 (Created) and sends back a Location header of that new resource. Now if you want to traverse that Location header link whilst leveraging destination (and credential information), you can use the overloaded webTarget function of <tt>webTarget(<destination code>, <location header>)</tt>. When invoking this function the system will check whether the presented <tt>location header</tt> matches the base URL that is referenced by the <tt>destination code</tt>. When these match a new WebTarget is returned that you can use, if not null is returned.

Examples

This section provides some examples about the external call-out mechanism.

These examples highlight the mechanism and protocol that is currently provided for by default by this module; JAX-RS Client API.

1) Issuing a GET request to a configured destination having the code "destination_remote". The URL has an additional path parameters abc. Response is a xml. The example uses XMLSlurper to parse the response and sets the result on 'a' field of a policy object. Response is:

<root someField='someValue'/>
   String response = webTarget("destination_remote")
                     .path("abc")
                     .request()
                     .buildGet()
                     .invoke()
                     .readEntity(String.class)

   def result = new XmlSlurper().parseText(response)
   policy.someField = result.@someField

2) Issuing a GET request to a configured destination having the code "destination_remote". The URL specifies a query parameter "code" as an input. Response is the same query parameter value.

   result = webTarget("destination_remote")
            .path("abc")
            .queryParam("code","ABC")
            .request()
            .buildGet()
            .invoke()
            .readEntity(String.class)

3) Issuing a GET request to a configured destination having the code "destination_remote". The URL specifies a header parameter.

    result = webTarget("destination_remote")
            .path("abc")
            .request()
            .header("accept","application/xml;test=HeaderProperty")
            .buildGet()
            .invoke()
            .readEntity(String.class)

4) Issuing a PUT/POST request to a configured destination having the code "destination_remote". It takes in XML as an input. This example sets the response as is on 'a' field of a policy object.

   def writer = new StringWriter()
   def xml = new groovy.xml.MarkupBuilder(writer)

   xml.ServiceCategoryRequest(version:4) {
      policyCode( policy.code )
      someField ( policy.someField )
   }

   String response = webTarget("destination_remote")
                     .request()
                     .header("Accept","application/xml")
                     .buildPut(Entity.xml(writer.toString()))
                     .invoke()
                     .readEntity(String.class)

   policy.calloutField = response.toString()

5) Using a returned Location header from a WebTarget POST operation.

   newResourceLocation = webTarget("destination_remote")
                          .request()
                          .buildPost(Entity.text("Hello World!"))
                          .invoke()
                          .getLocation()

   newResourceLocationData = webTarget("destination_remote", newResourceLocation)
                              .request()
                              .buildGet()
                              .invoke()
                              .readEntity(String.class)
 6) Issuing a PATCH request to a configured destination having the code
"destination_remote". It takes in XML as an input. This example sets the
response as is on 'a' field of a policy object.
  def writer = new StringWriter()
  def xml = new groovy.xml.MarkupBuilder(writer)

  xml.ServiceCategoryRequest(version:4) {
      policyCode( policy.code )
      someField ( policy.someField )
  }
  String response = webTarget("destination_remote")
                    .request()
                    .header("Accept", "application/xml")
                    .build("PATCH", Entity.xml(writer.toString()))
                    .invoke()
                    .readEntity(String.class);

  policy.calloutField = response.toString()