# Java

First, the required import statements:

import com.toshiba.mwcloud.gs.Collection;
import com.toshiba.mwcloud.gs.GSException;
import com.toshiba.mwcloud.gs.GridStore;
import com.toshiba.mwcloud.gs.GridStoreFactory;
import com.toshiba.mwcloud.gs.Query;
import com.toshiba.mwcloud.gs.RowKey;
import com.toshiba.mwcloud.gs.RowSet;

The container schema is defined as a static Class in Java.

static class Person {
	@RowKey String name;
	int age;
}
static class HeartRate {
	@RowKey Date ts;
	int heartRate;
        String activity;
}

To connect to GridDB, you create a Properties instance with the particulars of your GridDB installation.

Properties props = new Properties();
props.setProperty("notificationMember", "127.0.0.1:10001");
props.setProperty("clusterName", "myCluster");
props.setProperty("user", "admin");
props.setProperty("password", "admin");
GridStore store = GridStoreFactory.getInstance().getGridStore(props);

To perform queries or write records, you first need to get the container:

Collection<String, Person> people = store.putCollection("PEOPLE", Person.class);

Querying is similar to SQL/JDBC drivers.

Query<Person< query = col.query("select * where name = 'John'");
RowSet<Person> rs = query.fetch(false);
while (rs.hasNext()) {
	// Update the searched Row
	Person person1 = rs.next();
        System.out.println("Name: "+ person1.name +" Age: "+ person1.age)
}

Writing is simple...

HeartRate hr = new HeartRate();
hr.ts = new Date();
hr.heartrate = 60;
hr.activity = "resting";
TimeSeries<HeartRate> heartRate = store.putTimeSeries("HR_"+person1.name, HeartRate.class);
heartRate.put(hr);

Updating is simple:

Query<Person> query = col.query("select * where name = 'John'");
RowSet<Person> rs = query.fetch(true);
while (rs.hasNext()) {
	// Update the searched Row
	Person person1 = rs.next();
        person1.age++;
        rs.update(person1);
}

To compile use the following snippet:

$ cd gsSample/
$ export CLASSPATH=$CLASSPATH:/usr/share/java/gridstore.jar
$ javac Sample1.java
$ cd .. && java gsSample/Sample1

Alternatively, you can check out how to use maven with GridDB here (opens new window).

# Simulate IoT Data With Java

Java is perhaps the easiest programming language to start interfacing with GridDB. Unlike the other languages (Python, JavaScript, Golang, C, Ruby, and PHP), Java is the native interface, which means it works out of the box and makes zero concessions in data types or functionality.

For this article, we will continue our series of showcasing how to use each language by simulating IoT (internet of things) data and inserting that data into a GridDB TimeSeries container. The idea of the exercise is to give concrete examples of how schema creation and placing data into the containers works.

It also serves to allow developers to follow along and create a dummy dataset of IoT-like data structures to provide a simple proof-of-concept for using GridDB in a potentially bigger project or application.

# Schema Creation

To begin we will learn how to create a container using GridDB. To do so in Java, it is as simple as creating a Java class with the schema built in. With this, you can even declare which row is to be used as the RowKey.

In the following snippet of code, there will be a class called Iot which will eventually be used to create a TimeSeries container in our server. Because a TimeSeries container takes a timeseries row as the rowkey, at least two java imports will be needed: java.util.date and the GridDB RowKey.

import java.util.Date;
import com.toshiba.mwcloud.gs.RowKey;
public class Iot {
    @RowKey Date timestamp;
    double data;
    double temperature;
}

As mentioned before, the aim of this article to simulate IoT data, so the class here is a stand-in for a generic sensor which may be emiting the data, the time, and its internal temperature reading.

# Connecting To GridDB

Connecting to the database with Java consists of creating a Properties file from the java.util package and entering the credentials through various key:value pairs.

            Properties props = new Properties();
            props.setProperty("notificationMember", "127.0.0.1:10001");
            props.setProperty("clusterName", "myCluster");
            props.setProperty("user", "admin");
            props.setProperty("password", "admin");
            store = GridStoreFactory.getInstance().getGridStore(props);

Here we are using the default values.

The store variable is of type Gridstore and it is now how we will interact with the database. As an outside example, to put data, we would use one of store's methods called put.

# Generating and Putting List of Containers to GridDB

Now that the connection is out of the way, the attention will be on generating appropriate data to fit into the Iot class/schema. To do so, the java.util's random package will help to create values for data and temperature. The time data will be generated from a set arbitrary date/time and iterated upon with simple addition.

To start, we will create a method called Generate. As parameters, it will take the store object, a list which will contain all container names, and the amount of rows to be created.

To make this program as efficient as possible, we be using GridDB's multiPut which allows many rows of data to be inserted at once (as opposed to singular rows at a time with a more regular put).

Because multiPut takes more than singular row of data, the data type required to use this method is, according to the API docs: "containerRowsMap - A map made up of a list of Row objects and target Container names" which is of type (java.util.Map<java.lang.String,java.util.List<Row>>. This simply means that the data structure that is to be formed when we are generating our random data needs to be a map with a container name as the key and the corresponding rows as the value.

When running this code, it will require a couple of command line arguments from the user: the number of sensors to spoof, and the number of rows per sensor.

            int numSensors = Integer.parseInt(args[0]);
            int rowCount = Integer.parseInt(args[1]);

The number of sensors will come into play when creating our container names for the rowListMap object.

            try {
                List<String> containerNameList = new ArrayList<String>();
                for (int i = 0 ; i < numSensors; i++) {
                    String name = "iot"+i;
                    containerNameList.add(name);
                    TimeSeries<Iot> ts;
                    try {
                        ts = store.putTimeSeries(name, Iot.class);
                    } catch (GSException e) {
                        System.out.println("An error occurred when creating the container.");
                        e.printStackTrace();
                        System.exit(1);
                    }
            }

Here we are creating multiple containers with the name iot+num. Take notice that we are using the store object to put the Iot.class. Also notice that we are explicitly creating a TimeSeries container. With this in place, we can call the Generate method by using our containerName list.

final Map<String, List<Row>> rowListMap = Generate(store, containerNameList, rowCount);

# Simultating IoT Data

The beginning of the method first declares the object which will be returned

final Map<String, List<Row>> rowListMap = new HashMap<String, List<Row>>();

From there, it's simply a matter of looping over our container names and calling the Random library to create data points for the data and temperature columns. For the time, we initilize a time object and then add 1 minute per iteration. For each iteration, we add to an object called rowList and then add it to the rowListMap object (along with its container name). When it's all done, we return the rowListMap back to the main function.

        try { 
            Random rnd = new Random();
            for (String containerName : containerNameList) {
                final List<Row> rowList = new ArrayList<Row>();
                ContainerInfo containerInfo;
                try {
                    containerInfo = store.getContainerInfo(containerName);
                    System.out.println(containerName);
                    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
                    Date tm1=sf.parse("2022-03-07 10:00:00.000");
                    for (int j = 0; j < rowCount; j++) {
                        Row row = store.createRow(containerInfo);
                        row.setTimestamp(0,TimestampUtils.add(tm1, j, TimeUnit.MINUTE));
                        row.setDouble(1, rnd.nextInt(10000));
                        row.setDouble(2, rnd.nextInt(100));
                        rowList.add(row);
                    }
                    rowListMap.put(containerName, rowList);
                } catch (GSException e) {
                    System.out.println("An error occurred by the making of row data.");
                    e.printStackTrace();
                    System.exit(1);
                } catch (ParseException e) {
                    System.out.println("The format of the date had an error");
                    e.printStackTrace();
                    System.exit(1);
                }
            }
            return rowListMap;

Once our data is ready to go, we simply multiPut.

            try{
                store.multiPut(rowListMap);
            } catch (Exception e) {
                System.out.println("An error occurred when updating.");
                System.exit(1);
            }
            } catch (Exception e) {
            }

And with that, if no errors occur, you will have as many containers as specified by the numSensors config option.

# Closing GridDB Connection and Conclusion

And finally, we must always sever our connection to the database.

        } finally {
            if (store != null) {
                try {
                    store.close();
                } catch (GSException e) {
                    System.out.println("An error occurred when releasing the recsource.");
                    e.printStackTrace();
                }
            }
        }

Using GridDB is arguably the easiest and most simple when utilizing its native language Java.