This topic describes how to use LindormTSDB SDK for Java to connect to Lindorm Time Series Database (LindormTSDB) and use LindormTSDB.

Prerequisites

  • Java Development Kit (JDK) is installed. JDK V1.8 and later version are supported.
  • The version of LindormTSDB that is used for the Lindorm instance is V3.4.7 or later.
  • The IP address of your client is added to the allowlist of the Lindorm instance. For information about how to configure an allowlist, see Configure whitelists.
  • The endpoint of the LindormTSDB cluster of your Lindorm instance is obtained. For more information, see Obtain a connection string.

Before you begin

Before you use LindormTSDB SDK for Java to connect to LindormTSDB, you must install LindormTSDB SDK for Java. For example, you can use one of the following methods to install LindormTSDB SDK for Java V1.0.0:
  • Method 1: Recommended. Import LindormTSDB SDK for Java to a Maven project. You can add the following dependency to the pom.xml file.
    <dependency>
      <groupId>com.aliyun.lindorm</groupId>
      <artifactId>lindorm-tsdb-client</artifactId>
      <version>1.0.4</version>
    </dependency>
    Note LindormTSDB SDK for Java provides a Maven-based sample project. You can download the demo of the sample project. Then, you can compile and run the sample project on your on-premises machine, and you can also develop a new project based on the sample project.
  • Method 2: Import the JAR files of LindormTSDB SDK to an Eclipse project.
    1. Download the JAR files of LindormTSDB SDK.
    2. Extract files from the package that is downloaded.
    3. Import the files that are extracted to the Eclipse project.
      1. In Eclipse, open the project in which you want to run LindormTSDB SDK for Java, right-click the project name, and then click Properties from the shortcut menu.
      2. In the dialog box that appears, choose Java Build Path > Libraries > Add JARs and select the lindorm-tsdb-client-1.0.0.jar file and JAR files in the lib folder.
      3. Click Apply and Close.
  • Method 3: Import the JAR files of LindormTSDB SDK to an IntelliJ IDEA project
    1. Download the JAR files of LindormTSDB SDK.
    2. Extract files from the package that is downloaded.
    3. Import the files that are extracted to the IntelliJ IDEA project.
      1. In IntelliJ IDEA, open the project in which you want to run LindormTSDB SDK for Java. In the menu bar, choose File > Project Structure.
      2. On the left-side navigation pane of the Project Structure dialog box, choose Project Structure > Modules.
      3. Click the The Add icon icon and click JARs or directories.
      4. In the dialog box that appears, select the lindorm-tsdb-client-1.0.0.jar file and the JAR files in the lib folder, and click OK.
      5. Click Apply.
      6. Click OK.
Note
  • You can obtain each version of LindormTSDB SDK for Java from the Maven repository. For more information, see Maven Repository.
  • For more information about the versions of LindormTSDB SDK for Java, see Release notes.

Procedure

  1. Creates a LindormTSDB client. When you create a LindormTSDB client, you must specify the endpoint of the LindormTSDB cluster of your Lindorm instance. For more information, see Obtain a connection string.
    String url = "http://ld-bp17j28j2y7pm****-proxy-tsdb-pub.lindorm.rds.aliyuncs.com:8242";
    // A LindormTSDB client is thread-safe and can be reused. You do not need to create a client for each thread and then destroy the client after operations are complete.
    ClientOptions options = ClientOptions.newBuilder(url).build();
    LindormTSDBClient lindormTSDBClient = LindormTSDBFactory.connect(options);
  2. Create a database named demo and a time series table named sensor. For information about the SQL statements that are used to create databases and time series tables, see CREATE DATABASE and CREATE TABLE.
    lindormTSDBClient.execute("CREATE DATABASE demo");
    lindormTSDBClient.execute("demo","CREATE TABLE sensor (device_id VARCHAR TAG,region VARCHAR TAG,time BIGINT,temperature DOUBLE,humidity DOUBLE,PRIMARY KEY(device_id))");
  3. Write data to the time series table.
    Note By default, the LindormTSDB client asynchronously write data in batches to a table to improve the performance of data writing operations. If you want to write data in a synchronous manner, you can call the write() method to write data, use CompletableFuture<WriteResult> to process the data that is written, and then call the join() method to join the results.
    int numRecords = 10;
    List<Record> records = new ArrayList<>(numRecords);
    long currentTime = System.currentTimeMillis();
    for (int i = 0; i < numRecords; i++) {
        Record record = Record
            .table("sensor")
            .time(currentTime + i * 1000)
            .tag("device_id", "F07A1260")
            .tag("region", "north-cn")
            .addField("temperature", 12.1 + i)
            .addField("humidity", 45.0 + i)
            .build();
        records.add(record);
    }
    
    CompletableFuture<WriteResult> future = lindormTSDBClient.write("demo", records);
    // Process the data that is asynchronously written.
    future.whenComplete((r, ex) -> {
        // Process write failures.
        if (ex != null) {
            System.out.println("Failed to write.");
            if (ex instanceof LindormTSDBException) {
                LindormTSDBException e = (LindormTSDBException) ex;
                System.out.println("Caught an LindormTSDBException, which means your request made it to Lindorm TSDB, "
                                   + "but was rejected with an error response for some reason.");
                System.out.println("Error Code: " + e.getCode());
                System.out.println("SQL State:  " + e.getSqlstate());
                System.out.println("Error Message: " + e.getMessage());
            }  else {
                ex.printStackTrace();
            }
        } else  {
            System.out.println("Write successfully.");
        }
    });
    // In this example, a simple synchronization operation is performed to process the data that is written to the table.
    System.out.println(future.join());
  4. Query data from the time series table. For information about the SQL statements that can be used to query data, see Basic query statements.
    String sql = "select * from sensor limit 10";
    ResultSet resultSet = lindormTSDBClient.query("demo", sql);
    
    try {
        // Process the query results.
        QueryResult result = null;
        // Query results are returned in batches. By default, a batch can include up to 1,000 rows.
        // When the next() method that is used to obtain result sets returns the value null, all results are retrieved.
        while ((result = resultSet.next()) != null) {
            List<String> columns = result.getColumns();
            System.out.println("columns: " + columns);
            List<String> metadata = result.getMetadata();
            System.out.println("metadata: " + metadata);
            List<List<Object>> rows = result.getRows();
            for (int i = 0, size = rows.size(); i < size; i++) {
                List<Object> row = rows.get(i);
                System.out.println("row #" + i + " : " + row);
            }
        }
    } finally {
        // Use resultSet.close(); to release I/O resources after a query is complete.
        resultSet.close();
    }

Complete demo

import com.aliyun.lindorm.tsdb.client.ClientOptions;
import com.aliyun.lindorm.tsdb.client.LindormTSDBClient;
import com.aliyun.lindorm.tsdb.client.LindormTSDBFactory;
import com.aliyun.lindorm.tsdb.client.exception.LindormTSDBException;
import com.aliyun.lindorm.tsdb.client.model.QueryResult;
import com.aliyun.lindorm.tsdb.client.model.Record;
import com.aliyun.lindorm.tsdb.client.model.ResultSet;
import com.aliyun.lindorm.tsdb.client.model.WriteResult;
import com.aliyun.lindorm.tsdb.client.utils.ExceptionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

public class QuickStart {

    public static void main(String[] args) {

        // 1. Create a client.
        String url = "http://ld-xxxx-proxy-tsdb-pub.lindorm.rds.aliyuncs.com:8242";
        // A LindormTSDB client is thread-safe and can be reused. You do not need to create a client for each thread and then destroy the client after operations are complete.
        ClientOptions options = ClientOptions.newBuilder(url).build();
        LindormTSDBClient lindormTSDBClient = LindormTSDBFactory.connect(options);

        // 2. Create a database named demo and a table named sensor.
        lindormTSDBClient.execute("CREATE DATABASE demo");
        lindormTSDBClient.execute("demo","CREATE TABLE sensor (device_id VARCHAR TAG,region VARCHAR TAG,time BIGINT,temperature DOUBLE,humidity DOUBLE,PRIMARY KEY(device_id))");

        // 3. Write data to the table.
        int numRecords = 10;
        List<Record> records = new ArrayList<>(numRecords);
        long currentTime = System.currentTimeMillis();
        for (int i = 0; i < numRecords; i++) {
            Record record = Record
                    .table("sensor")
                    .time(currentTime + i * 1000)
                    .tag("device_id", "F07A1260")
                    .tag("region", "north-cn")
                    .addField("temperature", 12.1 + i)
                    .addField("humidity", 45.0 + i)
                    .build();
            records.add(record);
        }

        CompletableFuture<WriteResult> future = lindormTSDBClient.write("demo", records);
        // Process the data that is asynchronously written.
        future.whenComplete((r, ex) -> {
            // Process write failures.
            if (ex != null) {
                System.out.println("Failed to write.");
                Throwable throwable = ExceptionUtils.getRootCause(ex);
                if (throwable instanceof LindormTSDBException) {
                    LindormTSDBException e = (LindormTSDBException) throwable;
                    System.out.println("Caught an LindormTSDBException, which means your request made it to Lindorm TSDB, "
                            + "but was rejected with an error response for some reason.");
                    System.out.println("Error Code: " + e.getCode());
                    System.out.println("SQL State:  " + e.getSqlstate());
                    System.out.println("Error Message: " + e.getMessage());
                }  else {
                    throwable.printStackTrace();
                }
            } else  {
                System.out.println("Write successfully.");
            }
        });
        // In this example, a simple synchronization operation is performed to process the data that is written to the table.
        System.out.println(future.join());

        // 4. Query data.
        String sql = "select * from sensor limit 10";
        ResultSet resultSet = lindormTSDBClient.query("demo", sql);

        try {
            // Process the query results.
            QueryResult result = null;
            // Query results are returned in batches. By default, a batch can include up to 1,000 rows.
            // When the next() method that is used to obtain result sets returns the value null, all results are retrieved.
            while ((result = resultSet.next()) != null) {
                List<String> columns = result.getColumns();
                System.out.println("columns: " + columns);
                List<String> metadata = result.getMetadata();
                System.out.println("metadata: " + metadata);
                List<List<Object>> rows = result.getRows();
                for (int i = 0, size = rows.size(); i < size; i++) {
                    List<Object> row = rows.get(i);
                    System.out.println("row #" + i + " : " + row);
                }
            }
        } finally {
            // Use resultSet.close(); to release I/O resources after a query is complete.
            resultSet.close();
        }

        lindormTSDBClient.shutdown();
    }
}