Implementing communication client step by step



Since module version:

1.2.0



If one needs to implement a new communication client like FHIR or REST this tutorial will show you how it can be achieved.

Note: Currently, we only support HTTP based communication clients.



In order to create a new communication client you will have to follow these 9 steps:



STEP 1. Add dependency to FHIR module:

  • Add this line to your properties in pom.xml:

<fhirVersion>1.X.Y</fhirVersion>

Note: Specify version you wish to have dependency on by setting 'X' and 'Y' values. Minimum version is 1.14.0.



  • Add this block to your dependencies in your API and OMOD pom.xml files:

<dependency> <groupId>org.openmrs.module</groupId> <artifactId>fhir-api</artifactId> <scope>provided</scope> <version>${fhirVersion}</version> </dependency>






STEP 2. Implement org.openmrs.module.fhir.api.helper.ClientHelper interface:

org.openmrs.module.fhir.api.helper.ClientHelper interface
/** * <h1>ClientHelper</h1> * <p>Adapts specific Client to be used by pull & push business logic.</p> * * @see <a href="https://issues.openmrs.org/browse/SYNCT-274">SYNCT-274</a> * @since 1.14.0 */ public interface ClientHelper { /** * <p>Implements creation of retrieve request appropriate for specific Client.</p> * * @param url represents URL of resource to be retrieved * @return returns new RequestEntity with 'retrieve' request * @throws URISyntaxException */ RequestEntity retrieveRequest(String url) throws URISyntaxException; /** * <p>Implements creation of create request appropriate for specific Client.</p> * * @param url represents URL of resource category, where an object will be created * @param object represents an object that will be sent * @return returns new RequestEntity with 'create' request * @throws URISyntaxException */ RequestEntity createRequest(String url, Object object) throws URISyntaxException; /** * <p>Implements creation of delete request appropriate for specific Client.</p> * * @param url represents URL of resource category, from where an object will be deleted * @param uuid represents UUID of the object, that will be deleted * @return returns new RequestEntity with 'delete' request * @throws URISyntaxException */ RequestEntity deleteRequest(String url, String uuid) throws URISyntaxException; /** * <p>Implements creation of update request appropriate for specific Client.</p> * * @param url represents URL of resource, that will be updated * @param object represents an updated object * @return returns new RequestEntity with 'update' request * @throws URISyntaxException */ RequestEntity updateRequest(String url, Object object) throws URISyntaxException; /** * <p>Returns Class object corresponding to category name.</p> * * @param category represents name of category * @return returns Class object */ Class resolveClassByCategory(String category); /** * <p>Returns a list of HTTP interceptors used in communication between nodes.</p> * * @param username represents username of a user * @param password represents password of a user * @return return a list of custom interceptors */ List<ClientHttpRequestInterceptor> getCustomInterceptors(String username, String password); /** * <p>Returns a list of custom converters, that will be used to convert messages between formats.</p> * * @return returns a list of custom converters */ List<HttpMessageConverter<?>> getCustomMessageConverter(); /** * <p>Compares two objects of the same category.</p> * * @param category represents category of two compared objects * @param from represents incoming object * @param dest represents destination object * @return returns true if objects are equal, false otherwise */ boolean compareResourceObjects(String category, Object from, Object dest); /** * <p>Converts a String of formatted data to an object of a specified class.</p> * * @param formattedData represents data as a String * @param clazz represents desired class of returned object * @return returns an object of specified class */ Object convertToObject(String formattedData, Class<?> clazz); /** * <p>Converts an object to a String of formatted data.</p> * * @param object represents an object that will be converted to a String of formatted data * @return returns String of formatted data */ String convertToFormattedData(Object object); /** * <p>Converts an object to OpenMRS object of specified category.</p> * * @param object represents an object that will be converted to OpenMRS object * @param category represents category of OpenMRS object as a String * @return returns OpenMRS object of specified category * @throws NotSupportedException */ Object convertToOpenMrsObject(Object object, String category) throws NotSupportedException; }


for example:

TestClientHelper class



Note: We will be using TestClientHelper example until the end of this tutorial.






STEP 3. Modify Sync2 module. Add a new constant to org.openmrs.module.sync2.SyncConstants:

As a name take the first part of your ClientHelper interface implementation class name, in our case it will be:

org.openmrs.module.sync2.SyncConstants class






STEP 4. In Sync2 module add a new case to org.openmrs.module.sync2.client.ClientHelperFactory switch:

org.openmrs.module.sync2.client.ClientHelperFactory class


Remember: You have to import TEST_CLIENT constant first.






STEP 5. In Sync2 module, in org.openmrs.module.sync2.api.utils.SyncUtils class, implement your own method for extracting UUID from your resource link:

Note: Name of this method follows this pattern: extractUUIDFrom<name of your client>Resource.






STEP 6. In Sync2 module add a new case to org.openmrs.module.sync2.api.utils.extractUUIDFromResourceLinks switch:

org.openmrs.module.sync2.api.utils.extractUUIDFromResourceLinks method

Note: As an argument of your extract method put "resourceLinks.get(client)".

Remember: You have to import TEST_CLIENT constant first.






STEP 7. When running your OpenMRS instance, go to Atomfeed > Load Configuration page

Add your API endpoints to linkTemplates object in JSON file, for example:

Atomfeed configuration


Note: Key (in our case "test") must match TEST_CLIENT constant that was set in STEP 2.






STEP 8. Set your communication client as preferred client for pulling resources.

From Home page go to System AdministrationAdvanced AdministrationMaintenence > Advanced Settings.

Find sync2.resource.preferred.client property and set its value to the value of TEST_CLIENT constant, for example:






STEP 9. That's the end. Once you have finished this tutorial, you should have a working communication client.