How to use Spring client library, aka Client4SpringBoot?

Introduction

The platform offers several modules allow for the acquisition of information, mostly API Manager and DigitalBroker (also known as IoTBroker).

The API Manager allows you to easily, visually publish access (queries, updates, insertions) to ontologies such as REST APIs offering OpenAPI interfaces (swagger), so that you can create a client in any technology to attack these APIs.

You can see how to use the API Manager in any of these tutorials:

(API Manager) Creación y Ciclo de vida de las APIs / (API Manager) Invocación a APIS vía Swagger y generación de cliente con Swagger Editor / (API Manager) Invocar APIs de gestión de la plataforma con Token OAuth2

Using the API Manager has several advantages, such as having a record and catalogue of the interfaces (the services) published by the system for client consumption.

But there are scenarios where the API Manager approach may not be the most suitable, for instance:

  • If I am working in Java with Spring Boot and I don't want to generate many wrappers for the published APIs.

  • If I am using the platform as a data repository and I have a great number of ontologies to deal with.

  • If I need more flexibility and reduced development times.

  • If I am a device and I want to use a more efficient protocol such as MQTT.

In these and many other scenarios, you may be more interested in using the DigitalBroker as your business' input point.

What is Client4SpringBoot?

Client4SpringBoot is a Java library designed to work on Spring Boot and that simplifies access to DigitalBroker by wrapping the queries with a Repository interface that allows you invoke the DigitalBroker using Java methods.

Let's see what it looks like:

The way to access the ontologies is through an interface where the queries on the DigitalBroker are defined:

then I configure connection with the DigitalBroker and, through Spring's dependences injection, I can use this Repository to access the DigitalBroker. 


How can I use it?

Let's see how you can use Client4SpringBoot with an example. In the example, you will do this:

  • You will create an example ontology, e.g. an ontology to represent an incidence reported by a citizen in a city (CitizenTicket) and a connection with the Platform (Token,...)

  • You will create a Maven project and configure it with the library so you can communicate with the platform, inserting and recovering data to and from the previously created ontology.

Let's go!!!

Accessing the Environment and creating the Ontology and the DigitalClient for the example

  1. Let's start by connecting to one of the Environments' Control Panel in the Platform. For this example, you will use the experimentation environment we enabled: https://lab.onesaitplatform.com/controlpanel/
    If you don't have a user yet, you can create it directly by clicking New Account.
    Once in the ControlPanel you can start working. Log in and go to the menu option: My Ontologies:

    Select CREATE to create a new ontology. In this case, select Creation Step by Step:

    although you could also choose loading data from a file.

    In this example, you will create the ontology with this data: 


    Remember that the ontology name is unique, so that your Ontology must include something making it unique such as: CitizenTicket_<iduser>
    Now select a base template to create the ontology. In the example, select GENERAL's EmptyBase:
    This template has no base attribute, so that you can create your ontology as you want.
    Click ADD NEW PROPERTY to add your properties:

     
    In the example, create these attributes:

  •  

    • mail: String required (it represent the person's contact e-mail).

    • explanation: String required (it represents the incidence's description).

    • status: String required (the incidence's status; when just registered, it is PENDING).

    • coordinates: GeoJSON Point type optional (coordinates where the incidence was registered).

    • fullName: String optional (full name of the incidence's sender).

It looks like this in the Control Panel:

Next click on the button . This updates the JSON-Schema, that internally represents the ontology, and you can edit it in:

In the window appearing now, select to see the JSON-Schema and, in this case, to replace the root element, currently EmptyBase, with something more descriptive such as CitizenTicket:

You can click to get an idea on how's the JSON structure you must send to the platform from your client:

Save this example, as it will be useful later:

{"CitizenTicket":{ "mail":"string","explanation":"string","status":"string","coordinates":{"coordinates":[28.6,28.6],"type":"Point"},"fullName":"string"}}

You'll end your ontology creation by clicking on the button.

Bear in mind you have generated an ontology with default configuration, that is to say, authorizing no other user and using MongoDB as the storage database. This can be configured in the AUTHORIZATIONS and ADVANCED SETTINGS tabs.



2. Once the ontology is created, the System allows you to create an API for this ontology, a Device, a gadget or a Dashboard.

In this case, select Create new Device

This will take you directly to the Create Client screen:

In this screen, you must give your client an identification, for example ClientCitizenTicket_lmgracia, and you must also specify that it works with your ontology, CitizenTicket_lmgracia, with access level: All.

Click NEW:

This will take you to the Digital Client list:

You can enter to see the detail with the button. There, you will see that the platform has generated a Token for this Digital Client (If you click Modify, you can create more Tokens).

Save this Token for communication from the client: dbea2f7877ed4712824a4856a62cae88

3. You can also insert some example data for the tests. To do this, go back to the Development>My ontologies menu, look for your ontology:

And click the button. This allows you to create instances of your ontology from an editor. Click NEW:

Fill in the data and click New.

It will immediately create a record.

If you go to the TOOLS>Query Tool Menu Option, you can query on your CitizenTicket ontology and you'll be returned this:

You can see that a contextData element, associated to the insertion, has been added. It includes context information such as insertion user and date.

Creating and configuring the Spring Boot base project

Once you have created the ontology and the DigitalClient, you can start developing the client with the Client4SpringBoot library:

  1. Before starting, if you don't have the Platform's Development Environment, we recommend you install it. You can see how to do it in this tutorial: /wiki/spaces/PT/pages/7897242 (specifically in Step 1: How to install Development Environment in Windows)
    Once you have your environment configured with Java, Maven and Eclipse, you can go on.

  2. The first step is creating a Spring Boot application. For example, you can go to Spring Initializr website at https://start.spring.io and create a project, in this case with the following parameters:

    1. Select Maven Project, with Java and Spring Boot's last stable version (currently 2.0.4)

    2. As the group, select com.minsait.onesait.platform.examples

    3. As the artefact, example-crud-Client4SpringBoot

    4. Under dependencies, select Web and Actuator

    You will get something like:

  3. Click Generate Project. This will generate a ZIP file, which you'll leave in a local folder (If you are using the environment, we recommend S:\sources\examples\)
    It should look like this:

    If you are using the Development Environment, you can delete the mvnw.cmd file and the .mvn folder to ensure that you are using the Maven Repo configured in the environment.

  4. Now go to the Maven descriptor, pom.xml, to configure a couple of things:

    1. Add the dependency to the Client4SpringBoot library and to its specific version (currently 1.0.0-rc14):

      <dependency>
      <groupId>com.minsait.onesait.platform</groupId>
      <artifactId>onesaitplatform-iotclient4springboot</artifactId>
      <version>1.0.0-rc14</version>
      </dependency>

    2. Configure the repositories, including the repository from which you can download the onesait Platform libraries:

      <repositories>
      <repository>
      <id>onesait platform releases</id>
      <url>http://sofia2.org/nexus/content/repositories/releases/</url>
      </repository>
      <repository>
      <id>maven central</id>
      <url>http://central.maven.org/maven2/</url>
      </repository>
      </repositories>

Configuring communication with the platform

  1. Let's start by opening an IDE to develop. The Development Environment includes a configured Eclipse that you can launch from S:\scripts\eclipse.bat


  2. From Eclipse, import your Maven project from Import>Existing Maven Projects:


In the src/main/resources folder, an application.properties file must have been just generated. Rename it to application.yml

and include the following entries:

  1. In these entries, you must specify the information you previously registered from the ControlPanel:

    • onesaitplatform.iotclient.token=dbea2f7877ed4712824a4856a62cae88

    • onesaitplatform.iotclient.deviceTemplate=ClientCitizenTicket_lmgracia

    • onesaitplatform.iotclient.device=instance1




spring: ## General Config 

   application.name: Example IoTClient4SpringBoot

 

onesaitplatform:

  iotclient:

    urlRestIoTBroker: https://s4citiespro.westeurope.cloudapp.azure.com/iot-broker

    sslverify: true

    token: dbea2f7877ed4712824a4856a62cae88

    deviceTemplate: ClientCitizenTicket_lmgracia

    device: instance1

    connectTimeoutInSec: 10

    writeTimeoutInSec: 30

    readTimeoutInSec: 30

 

## LOGGING CONF

logging:

   path: ./target/

   file: ${spring.application.name}

   level:

      org.springframework: INFO

      com.minsait: INFO



Creating the Java class representing your ontology

The next step is creating the Java class representing your ontology. In the future, this will be done automatically, but the process is very simple. Let's see how it goes.

  1. To help you stay organized in the base package ( com.minsait.onesait.platform.examples.examplecrudiotclient4springboot), create a domain package and, in it, two classes: CitizenTicketOntology and CitizenTicket

  2. The first thing to do is adding the @Data annotation to both classes. This Lombok annotation automatically generates the get and set of each attribute and the methods hashCode and toString()  https://projectlombok.org/features/Data

  3. Now edit the CitizenTicketOntology class to add this:

  4. Let's see what each element means:
    - The _id field represents the internal identification in the database where the element was inserted, in this case MongoDB. If you don't need it, you may decide not to include it, but we have done it here.


    - The contextData field represents the insertion context automatically provided by the Platform. It includes user and insertion date and time. You may decide not to include it if you are not going to use it. The Platform provides the ContextData class:


    - The citizenTicket field really represents the ontology instance, the one we were seeing before. It is mapped with the CitizenTicket property name (Same as in the JSON):


    When creating the ontology, if you had not used the root element (in this case CitizenTicket), then you would not need the container class. We recommend creating a root element if it gives semantics to the instance (Whenever I see this instance, I automatically know its type).

  5. The next step is creating the attributes making up your ontology. Let's remember them:

    • mail: String required (it represents the contact person's e-mail address).

    • explanation: String required (it represents the incidence description).

    • status: String required (the incidence status; when registering, it is PENDING).

    • coordinates: GeoJSON Point Type optional (coordinates where the incidence was registered).

    • fullName: String optional (incidence sender's full name).

    In this class, they will look like this:


    Notice that you are adding JsonIgnore to the optional attributes so that, if these are null, they are not sent. Besides, the coordinates map with the GeometryPoint object (Point GeoJson).

  6. Lastly, go back to the CitizenTicketOntology class and add a new @JsonInclude(Include.NON_NULL) annotation. It prevents the attributes to be returned if they are null (If the ContextData is null, they are not returned):

Creating the basic Repository to connect with the Platform

Once you have configured connection with the platform in the application.yml file and the class representing the ontology (CitizenTicket), you can create a Repository (Repository pattern)

Let's see how:

  1. In the .repository package, create a CitizenTickerRepository interface, where you'll add the @IoTBrokerRepository("CitizenTicket_lmgracia") annotation to specify the (main) ontology on which the Repository works:


    Remember to replace the ontology name with yours.

  2. Now, add the methods that your Repository uses. Let's see the basic ones (and later we'll see some advanced ones):



    1. The @IoTBrokerQuery annotation is used for queries, such as recovering all the tickets with getAllTickets or to count them, etc. You can also pass it parameters, as you can see in the getTicketsByUser method.
      Ever since release 1.0.0-rc19, the query can be passed dynamically, as an argument, and you can include parameters that will be replaced in the inserted query with the value specified in the @IotBrokerParam annotation.



      The @IoTBrokerInsert annotation can be used to insert one CitizenTicket, or a list of them. As a result, it returns a String with its ID.

    2. The @IotBrokerUpdate annotation allows you to update a Ticket by sending, as the parameters, its id (from the database) and instance.

    3. The @IoTBrokerDelete annotation allows you to delete a Ticket by its ID.

    4. Ever since release 1.1.0-rc01, the @IoTBrokerDynamicRepository annotation allows you to query on a repository (ontology)different to the one specified at class level, at a parameter level, in a method, using the @IoTBrokerRepository annotation. That way, you can parameter the ontology on which the method works, allowing you to create Repositories where you don't even specify an ontology at the level of@IoTBrokerRepository annotation.

Communication with the Platform

You have everything ready to communicate with the platform through the communicating class:

  1. Create a CitizenTicketController class in the .control package and annotate it with the @Component annotation so it is a Spring Bean, and with the @Slf4j annotation, that instantiates a SL4J log (configured with logback in platform):

  2. Add the injection to your Repository:

  3. To test the communication, do a check method that you will annotate with @PostConstruct (so that it is automatically invoked once the Spring Boot context is loaded):

  4. Now you only have to fill in the method. Let's do something simple:


    (Add an interrupt point

  5. To test this, you only need to add a couple more annotations to your SpringBoot application's Application class. Go there and add these annotations:  @EnableAutoConfiguration, needed for the library to work, and @ComponentScan, with the base package so that it can find the defined Beans:



    @EnableAutoConfiguration
    @ComponentScan("com.minsait.onesait.platform.examples.examplecrudiotclient4springboot")

  6. From Eclipse, you can now launch your Eclipse project simply by hovering on the Application class and:


    If you have selected Depuration, you can see how it stops:




  7. And test that it works:

    (Spanish text: There is 1 Ticket at the beginning. There is 2 Tickets now. Deleted ticket with id 5b76... There is 1 Ticket at the end).
           

  8. We recommend you follow this handbook completely, but you can also download the example from here and test it: example-crud-IoTClient4SpringBoot.zip



Operations managing the element's Id:

Operations such as Inserts, Bulk, Update or Delete can need to get the BDTR's Id of the affected elements (inserted, updated, deleted ones).

For UPDATE and DELETE operations, we recommend to not use this mode and instead not recover the Id of affected elements, unless it is strictly needed, because you would be wasting the BDTR native capacities to update and delete in bulk, thus accepting a worse performance.

This can be done like this:

  • Inserts: They return the Id as a String in the Repository operation:

  • BULK: They return a BulkResult object, allowing you to get the number of inserted elements and the list of their Ids in BDTR:

  Where BulkResult is defined in the following class:

  • UPDATE: This is done using a Query type operation, specifying that the response is an UpdateResult type object:

Where UpdateResult is defined in the following class:



  • DELETE: This is done through a Query type operation, specifying that the response is a DeleteResult type object:

Where DeleteResult is defined in the following class:





Support for count type operations:

Allows performing count type operations, both with query criteria and without criteria: