Skip to main content

Camel DHIS2 Component

The Camel DHIS2 Component leverages the DHIS2 Java SDK to integrate Apache Camel with DHIS2. The component is distributed with Apache Camel and can be added to a Maven project POM like so:

<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-dhis2</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>

Getting started

note

A basic understanding of Apache Camel and endpoints is assumed. Visit the Apache Camel page to learn the fundamental Camel concepts. All Camel route examples given in this page are expressed in the YAML DSL.

A DHIS2 endpoint is declared in a route using the following URI format:

dhis2:apiName/methodName?[parameters]

Endpoint parameters

Parameters common across all APIs are listed below:

baseApiUrl

DHIS2 server base API URL to sends requests to.

username

Username of the DHIS2 user to operate as.

password

Password of the DHIS2 username.

personalAccessToken

Personal access token to authenticate with DHIS2. This option is mutually exclusive to username and password

client

Reference to the underlying client communicating with the DHIS2 server. Referencing a client avoids the need to duplicate the base API URL and credentials when declaring multiple DHIS2 endpoints. Duplicating the base API URL and credentials negatively impacts run-time performance because an identical DHIS2 Java SDK client is created for each endpoint. This option is mutually exclusive to baseApiUrl, username, password, and personalAccessToken. The subsequent example demonstrates how to (1) create the client, (2) register it with Camel, and then (3) reference the client from a DHIS2 endpoint:

- beans:
- name: dhis2Client
type: org.hisp.dhis.integration.sdk.api.Dhis2Client
scriptLanguage: groovy
script: >
org.hisp.dhis.integration.sdk.Dhis2ClientBuilder.newClient('https://play.im.dhis2.org/stable-2-40-5/api', 'admin', 'district').build()

- from:
uri: direct:resourceTablesAnalytics
steps:
- to:
uri: dhis2:resourceTables/analytics
parameters:
skipAggregate: true
skipEvents: true
lastYears: 1
client: "#dhis2Client"
note

Visit the DHIS2 Java SDK page to learn more about the DHIS2 Java SDK.

The client parameter within the to DHIS2 endpoint in the above route snippet is set to #dhis2Client. #dhis2Client is an entry in Camel registry which is bound to an instance of Dhis2Client thanks to the following YAML section:

- beans:
- name: dhis2Client
type: org.hisp.dhis.integration.sdk.api.Dhis2Client
scriptLanguage: groovy
script: >
org.hisp.dhis.integration.sdk.Dhis2ClientBuilder.newClient('https://play.im.dhis2.org/stable-2-40-5/api', 'admin', 'district').build()

The script key instantiates Dhis2Client using the following Groovy code:

org.hisp.dhis.integration.sdk.Dhis2ClientBuilder.newClient('https://play.im.dhis2.org/stable-2-40-5/api', 'admin', 'district').build()

HTTP query parameters

Besides the endpoint parameters, custom HTTP query parameters can be set from the message header using the CamelDhis2.queryParams header name. Here is a Camel route snippet that adds the HTTP query parameters ou and program to the message before sending a request to DHIS2:

...
...
- setHeader:
name: CamelDhis2.queryParams
groovy: "['ou':'DiszpKrYNg8','program':'IpHINAT79UW']"
- to:
uri: dhis2:...
parameters:
...
...

HTTP query parameter lists are also supported as shown in the next snippet:

...
...
- setHeader:
name: CamelDhis2.queryParams
groovy: "['ou':['DiszpKrYNg8', 'fdc6uOvgoji'],'program':'IpHINAT79UW']"
- to:
uri: dhis2:...
parameters:
...
...

In URL terms, the request sent to DHIS2 in this example will have these query parameters: ...?ou=DiszpKrYNg8&ou=fdc6uOvgoji&program=IpHINAT79UW.

Endpoint APIs & Methods

The endpoint API name and supported method names are described below:

get

Specify get for the API name to fetch a DHIS2 resource or a collection of DHIS2 resources. A resource is fetched with the resource method name as shown next:

- from:
uri: direct:getResource
steps:
- to:
uri: dhis2:get/resource
parameters:
path: organisationUnits/O6uvpzGd5pu
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api

The path parameter identifies the path where the resource is located in DHIS2: organisationUnits/O6uvpzGd5pu. The type of the message body produced from dhis2:get/resource is java.io.InputStream. The raw JSON stream can be deserialised into a POJO like this:

- from:
uri: direct:getResource
steps:
- to:
uri: dhis2:get/resource
parameters:
path: organisationUnits/O6uvpzGd5pu
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api
- unmarshal:
json:
unmarshalType: org.hisp.dhis.api.model.v40_2_2.OrganisationUnit
note

The POJO class may be user-defined or a resource class included in the DHIS2 Java SDK.

A collection of resources is fetched with the collection method name, for example:

- from:
uri: direct:getCollection
steps:
- to:
uri: dhis2:get/collection
parameters:
path: organisationUnits
arrayName: organisationUnits
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api

Apart from the path parameter, dhis2:get/collection has a specific parameter called arrayName. This required parameter is the name of the JSON property containing the resource collection in the reply (e.g., organisationUnits). The type of the message body produced from dhis2:get/collection is java.util.Iterator<org.apache.camel.component.dhis2.api.Dhis2Resource>. Dhis2Resource is essentially a java.util.HashMap. One can choose to iterate over the body using a splitter, like so:

- from:
uri: direct:getCollection
steps:
- to:
uri: dhis2:get/collection
parameters:
path: organisationUnits
arrayName: organisationUnits
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api
- split:
simple: ${body}
steps:
- log: ${body}

Converting a Dhis2Resource item into POJO is accomplished with convertBodyTo(...):

- from:
uri: direct:getCollection
steps:
- to:
uri: dhis2:get/collection
parameters:
path: organisationUnits
arrayName: organisationUnits
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api
- split:
simple: ${body}
steps:
- convertBodyTo:
type: org.hisp.dhis.api.model.v40_2_2.OrganisationUnit
- log: ${body}

By default, paging is disabled. Paging can be enabled by setting the paging parameter to true:

- from:
uri: direct:getCollection
steps:
- to:
uri: dhis2:get/collection
parameters:
path: organisationUnits
arrayName: organisationUnits
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api
paging: true
- split:
simple: ${body}
steps:
- convertBodyTo:
type: org.hisp.dhis.api.model.v40_2_2.OrganisationUnit
- log: ${body}

filter

Both the resource and collection methods accept one or more filter parameters to select results with DHIS2's object filter. The filter endpoint parameter in the following example is set to phoneNumber:!null: in order to fetch DHIS2 users which have a phone number:

- from:
uri: direct:getCollection
steps:
- to:
uri: dhis2:get/collection
parameters:
path: users
arrayName: users
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api
filter: "phoneNumber:!null:"
- split:
simple: ${body}
steps:
- convertBodyTo:
type: org.hisp.dhis.api.model.v40_2_2.User
- log: ${body}

fields

Both the resource and collection methods accept the fields parameter to select the resource fields that are fetched. The fields endpoint parameter in the following example is set to * in order to select all the organisation unit resource fields:

- from:
uri: direct:getResource
steps:
- to:
uri: dhis2:get/resource
parameters:
path: organisationUnits/O6uvpzGd5pu
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api
fields: "*"
- unmarshal:
json:
unmarshalType: org.hisp.dhis.api.model.v40_2_2.OrganisationUnit

rootJunction

Both the resource and collection methods accept the rootJunction parameter to set the logic junction used between filters. The rootJunction endpoint parameter in the following example is set to AND in order to fetch users that have both a phone and WhatsApp number:

- from:
uri: direct:getCollection
steps:
- to:
uri: dhis2:get/collection
parameters:
path: users
arrayName: users
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api
filter: "whatsApp:!null:"
rootJunction: AND
- split:
simple: ${body}
steps:
- convertBodyTo:
type: org.hisp.dhis.api.model.v40_2_2.User
- log: ${body}

post

Specify post for the API name and resource for the method name to save a DHIS2 resource as demonstrated in this route:

- from:
uri: direct:postResource
steps:
- setBody:
groovy: |
new org.hisp.dhis.api.model.v40_2_2.DataValueSet()
.withCompleteDate(java.time.ZonedDateTime.now(java.time.ZoneOffset.UTC).format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE))
.withOrgUnit('O6uvpzGd5pu')
.withDataSet('lyLU2wR22tC')
.withPeriod(org.hisp.dhis.integration.sdk.support.period.PeriodBuilder.monthOf(new Date(), -1))
.withDataValues([new org.hisp.dhis.api.model.v40_2_2.DataValue().withDataElement('aIJZ2d2QgVV').withValue('20')])
- to:
uri: dhis2:post/resource
parameters:
path: dataValueSets
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api
- unmarshal:
json: {}
- choice:
when:
- groovy: body.status != 'OK'
steps:
- log:
loggingLevel: ERROR
message: Import error from DHIS2 while saving data value set => ${body}

In the above route, the message body is set to a data value set using Groovy:

new org.hisp.dhis.api.model.v40_2_2.DataValueSet()
.withCompleteDate(java.time.ZonedDateTime.now(java.time.ZoneOffset.UTC).format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE))
.withOrgUnit('O6uvpzGd5pu')
.withDataSet('lyLU2wR22tC')
.withPeriod(org.hisp.dhis.integration.sdk.support.period.PeriodBuilder.monthOf(new Date(), -1))
.withDataValues([new org.hisp.dhis.api.model.v40_2_2.DataValue().withDataElement('aIJZ2d2QgVV').withValue('20')])

This data value set is saved in DHIS2 thanks to a dhis2:post/resource endpoint:

- to:
uri: dhis2:post/resource
parameters:
path: dataValueSets
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api

dataValueSets is the path parameter which identifies the path where the resource will be saved. dhis2:post/resource expects the message body to contain the resource to be sent to DHIS2. The body produced from the endpoint is of type java.io.InputStream. In this example, the route deserialises the reply into a java.util.Map object with:

- unmarshal:
json: {}

put

Specify put for the API name and resource for the method name to update a DHIS2 resource as demonstrated in this route:

- from:
uri: direct:putResource
steps:
- setBody:
groovy: |
new org.hisp.dhis.api.model.v40_2_2.OrganisationUnit()
.withName('Acme')
.withShortName('Acme')
.withOpeningDate(new Date())
- to:
uri: dhis2:put/resource
parameters:
path: organisationUnits/jUb8gELQApl
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api
- unmarshal:
json: {}
- choice:
when:
- groovy: body.status != 'OK'
steps:
- log:
loggingLevel: ERROR
message: Import error from DHIS2 while updating org unit => ${body}

In the above route, the message body is set to an organisation unit using Groovy:

new org.hisp.dhis.api.model.v40_2_2.OrganisationUnit()
.withName('Acme')
.withShortName('Acme')
.withOpeningDate(new Date())

The organisation unit jUb8gELQApl in DHIS2 is updated with the organisation unit in the message body thanks to a dhis2:put/resource endpoint:

- to:
uri: dhis2:put/resource
parameters:
path: organisationUnits/jUb8gELQApl
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api

organisationUnits/jUb8gELQApl is the path parameter which identifies the path where the resource to be updated is located in DHIS2. dhis2:put/resource expects the message body to contain the resource to be sent to DHIS2. The body produced from the endpoint is of type java.io.InputStream. In this example, the route deserialises the reply into a java.util.Map object with:

- unmarshal:
json: {}

delete

Specify delete for the API name and resource for the method name to delete a DHIS2 resource as demonstrated in this route:

- from:
uri: direct:deleteResource
steps:
- to:
uri: dhis2:delete/resource
parameters:
path: organisationUnits/jUb8gELQApl
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api
- unmarshal:
json: {}
- choice:
when:
- groovy: body.status != 'OK'
steps:
- log:
loggingLevel: ERROR
message: Import error from DHIS2 while deleting org unit => ${body}

The above route deletes the organisation unit jUb8gELQApl in DHIS2 thanks to the dhis2:delete/resource endpoint:

- to:
uri: dhis2:delete/resource
parameters:
path: organisationUnits/jUb8gELQApl
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api

organisationUnits/jUb8gELQApl is the path parameter which identifies the path where the resource to be deleted is located in DHIS2. A resource can be added to the HTTP request sent by setting the message body to the resource. The body produced from dhis2:put/resource is of type java.io.InputStream. In this example, the route deserialises the reply into a java.util.Map object with:

- unmarshal:
json: {}

resourceTables

Specify resourceTables for the API name and analytics for the method name to run analytics on DHIS2 as demonstrated in this route:

- from:
uri: direct:resourceTablesAnalytics
steps:
- to:
uri: dhis2:resourceTables/analytics
parameters:
skipAggregate: false
skipEvents: true
lastYears: 1
username: admin
password: district
baseApiUrl: https://play.im.dhis2.org/stable-2-40-5/api

dhis2:resourceTables/analytics does not produce a new message body. The following table describes the parameters specific to dhis2:resourceTables/analytics:

Parameter NameDescription
skipAggregateSkip generation of aggregate data and completeness data.
skipEventsSkip generation of event data.
lastYearsNumber of last years of data to include.
intervalDuration in milliseconds between completeness checks. Default is 30000
asyncWhether to block until analytics is complete. Default is false.