Best-Practices to use the Microservice SDK for Java for custom API queries
Tags: cumulocity, iot, microservices, sdk
Published: 2023-11-14 13:53:26

---
title: Best-Practices to use the Microservice SDK for Java for custom API queries
published: true
date: 2023-10-31 10:15:01 UTC
tags: cumulocity, iot, microservices, sdk
canonical_url: https://tech.forums.softwareag.com/t/best-practices-to-use-the-microservice-sdk-for-java-for-custom-api-queries/285281
---

 

## Introduction

The Cumulocity IoT API provides a wide range of API query capabilities, but only a subset is easily useable directly by the Microservice SDK for Java.

Mostly the **inventory API** provides the most capable (and complex) [query language](https://cumulocity.com/api/core/#tag/Query-language), which is heavily used in many projects. Also other APIs like **alarm** , **event** , **measurement** , **audit** and **identity** also can be used with the same approach!

Due to the wide variety of features, query language and URL parameters the SDK does not support this in all detail.  
Implementing a microservice usually requires to interact for example with the inventory API to search for devices by specific criteria. Once the required API call is identified, e.g. via Postman, you think of easily taking that into a microservice to automate the task.  
This article is about to show some best-practices including code examples on how to simplify calling the Cumulocity IoT API with the full set of its features.

## Pre-requisite

Any microservice based on the Cumulocity IoT Microservice SDK for Java is applicable.

## How does it work?

### Problem statement

You want to query devices by their creation time. Hence via API call you know to use a GET API call like below and you want to be able to do the same call within a microservice, using the microservice SDK.

```
GET /inventory/managedObjects?query=$filter=creationTime.date gt '2023-06-12T12:00:00.000Z' and creationTime.date le '2023-06-12T12:59:59.999Z'

```

### Limitations of standard SDK classes

Normally you can use `InventoryFilter` to query the inventory API, but it is limited and does not (easily) support the powerful query language (e.g. filter by creation time from the problem statement above) or URL parameters like `withParents`. Hence I want to share a best-practice to use the SDK in a code friendly, reusable and readable way.

### Using the QueryParam class directly from the SDK - not optimal

The `QueryParam` class allows to define custom URL parameters when doing API calls - especially those not directly supported by the `InventoryFilter` class which is used by the `InventoryApi` class.

The `getManagedObjects()` method of the `inventoryApi` returns an `ManagedObjectCollection` object, for which the interesting and simple method `get` is available.

This `get` method takes the pageSize as the first parameter and one or more `QueryParam`s as following parameters.

> Note: This applies not only to the inventory API, but also other APIs mentioned in the introduction.

In the below simple example the **withParents** URL parameter is used with the value **true**.

However this code gets quite huge when using more parameters. The next section shows a convenience class which reduces the code and ensures reusability.

```
import com.cumulocity.sdk.client.Filter;
import com.cumulocity.sdk.client.QueryParam;

QueryParam queryParam = new QueryParam(new Param() {
		@Override
		public String getName() {
			return "withParents";
		}
	}, "true");

Iterable<ManagedObjectRepresentation> managedObjects = inventoryApi
	.getManagedObjects()
	.get(50, queryParam)
	.allPages();

```

### Create convenience class for code simplification

The below class `CustomQueryParam` implements the Param interface and allows to easily, repetitively use `QueryParam` objects to define any URL parameter of the inventory API.

Any URL parameter can be simply provided as an enum with its actually parameter name - feel free to use and extend this enum.  
See below for how to use this enum and how it simplifies the code.

```
public enum CustomQueryParam implements Param {
	WITH_TOTAL_PAGES("withTotalPages"),
	PAGE_SIZE("pageSize"),
	QUERY("query"),
	DEVICE_QUERY("q"),
	DATE_FROM("dateFrom"),
	STATUS("status"),
	FRAGMENT_TYPE("fragmentType"),
	DEVICE_ID("deviceId"),
	REVERT("revert"),
	;

	private String name;
	
	private String value;
	
	public String getValue() {
		return value;
	}

	private CustomQueryParam(final String name) {
		this.name = name;
	}

	@Override
	public String getName() {
		return name;
	}

	public CustomQueryParam setValue(final String value) {
		this.value = value;
		return this;
	}

	public QueryParam toQueryParam() {
		return new QueryParam(this, Filter.encode(value));
	}

}

```

### Making use of the CustomQueryParam class

Now we come back to our initial example and see how we can simplify this.  
Additionally we can solve our initial problem to also query by creation time easily.

We can easily create 2 QueryParam objects for the **withParents** URL parameter and for the creation time query - both as a (long) one-liner.

The `get` method can then be called with the page size and both query parameters in one go.

Now `allPages` nicely returns an Iterable with the result of our query.

```
int pageSize = 50;
QueryParam withParents = CustomQueryParam.WITH_PARENTS.setValue("true").toQueryParam();
QueryParam creationTimeQuery = CustomQueryParam.QUERY.setValue("creationTime.date ge " + "'" + CustomUtil.getDateWithTime() + "'").toQueryParam();
		
Iterable<ManagedObjectRepresentation> managedObjects = inventoryApi
	.getManagedObjects()
	.get(pageSize, withParents, creationTimeQuery)
	.allPages();

```

The above code would result in following API call:

```
GET /inventory/managedObjects?pageSize=50&withParents=true&query=$filter=creationTime.date gt '2023-06-12T12:00:00.000Z' and creationTime.date le '2023-06-12T12:59:59.999Z'

```

## Conclusion

The above best-practice shows that even any complex API calls using multiple URL parameters can be implemented much easier with the given convenience class and methods to allow a fast transfer from the raw API call into the microservice implementation.

## Useful links | Relevant resources

- [Inventory API - Query language](https://cumulocity.com/api/core/#tag/Query-language)


[Read full topic](https://tech.forums.softwareag.com/t/best-practices-to-use-the-microservice-sdk-for-java-for-custom-api-queries/285281)