DEV Community

Tech Community for Software AG Tech Community

Posted on • Originally published at tech.forums.softwareag.com on

Best-Practices to use the Microservice SDK for Java for custom API queries

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, 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'

Enter fullscreen mode Exit fullscreen mode

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 QueryParams 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();

Enter fullscreen mode Exit fullscreen mode

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));
    }

}

Enter fullscreen mode Exit fullscreen mode

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();

Enter fullscreen mode Exit fullscreen mode

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'

Enter fullscreen mode Exit fullscreen mode

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

Read full topic

Top comments (0)