Skip to content

Core concepts

This document walks through the core classes and concepts behind the Lovrabet Java OpenSDK, so you can understand how the SDK works.


1. The SDK client (LovrabetSDKClient)

LovrabetSDKClient is the heart of the SDK — it wraps every OpenAPI endpoint.

1.1 Creating the client

Java
public LovrabetSDKClient(String accessKey, String baseUrl);

Parameters:

ParameterTypeRequiredDescription
accessKeyStringYesAccess key, generated in the app admin console
baseUrlStringYesAPI server URL: https://runtime.lovrabet.com/openapi

Example:

Java
String accessKey = "ak-OD8xWhMOsL5ChQ3Akhv4uYYiu1fPOFQGVF9BULIeov8";
String baseUrl = "https://runtime.lovrabet.com/openapi";

LovrabetSDKClient sdkClient = new LovrabetSDKClient(accessKey, baseUrl);

1.2 Client features

Thread safety

LovrabetSDKClient is thread-safe and can be shared across threads:

Java
// 推荐:创建单例复用
public class SdkClientManager {
    private static volatile LovrabetSDKClient instance;

    public static LovrabetSDKClient getInstance() {
        if (instance == null) {
            synchronized (SdkClientManager.class) {
                if (instance == null) {
                    instance = new LovrabetSDKClient(
                        ConfigManager.getAccessKey(),
                        ConfigManager.getBaseUrl()
                    );
                }
            }
        }
        return instance;
    }
}

// 在应用中使用
LovrabetSDKClient client = SdkClientManager.getInstance();

Automatic authentication

The SDK signs every request automatically, so you never have to deal with the signing algorithm yourself:

Java
// SDK 会自动完成:
// 1. 生成时间戳
// 2. 构建签名字符串
// 3. 计算 HMAC-SHA256 签名
// 4. 添加认证头到 HTTP 请求

LovrabetResult<?> result = sdkClient.getList(request);  // 自动签名

2. The request object (LovrabetRequest)

LovrabetRequest holds the parameters for an API call.

2.1 Class definition

Java
public class LovrabetRequest {
    private Long id;                          // 主键ID
    private String appCode;                   // 应用编码(必填)
    private String modelCode;                 // 数据集编码
    private Map<String, Object> paramMap;     // 业务参数

    // Getters and Setters
}

2.2 Field reference

FieldTypeRequiredUsed byDescription
appCodeStringYesAll methodsApp code, found in the app admin console
modelCodeStringSome methodsData operationsDataset code identifying the target dataset
idLongSome methodsgetOne, updatePrimary key ID of the record
paramMapMapNoVariousPagination parameters, query conditions, data fields, etc.

2.3 Usage examples

Basic request (appCode only)

For app-level endpoints such as listing datasets:

Java
LovrabetRequest request = new LovrabetRequest();
request.setAppCode("app-c2dd52a2");

Dataset request

For dataset-level endpoints such as querying records:

Java
LovrabetRequest request = new LovrabetRequest();
request.setAppCode("app-c2dd52a2");
request.setModelCode("b460abdbb0fb49e1865110d9dfbbc9b4");

// 添加分页参数
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("pageSize", 10);
paramMap.put("currentPage", 1);
request.setParamMap(paramMap);

Single-record request

For fetching or updating a specific record:

Java
LovrabetRequest request = new LovrabetRequest();
request.setAppCode("app-c2dd52a2");
request.setModelCode("32c036010c504757b80d438e3c0ec8b7");
request.setId(513L);

// 更新操作还需要设置要修改的字段
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("TEXT_1", "新的文本内容");
request.setParamMap(paramMap);

2.4 paramMap guide

paramMap is a flexible container that serves several purposes:

Use case 1: pagination parameters

Java
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("currentPage", 1);      // 当前页码,从 1 开始
paramMap.put("pageSize", 20);        // 每页显示的记录数

Use case 2: data fields (create/update)

Java
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("TEXT_1", "订单编号-001");           // 文本字段
paramMap.put("NUMBER_3", 100);                    // 数字字段
paramMap.put("DATETIME_1", System.currentTimeMillis());  // 时间戳
paramMap.put("SELECT_4", "china-north");          // 选择字段

Use case 3: query conditions (if the API supports them)

Java
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("status", "active");     // 根据状态筛选
paramMap.put("category", "product");  // 根据分类筛选

3. The response object (LovrabetResult)

LovrabetResult<T> is the uniform response object for every API call.

3.1 Class definition

Java
public class LovrabetResult<T> {
    private boolean success;                  // 执行是否成功
    private String resultCode;                // 结果代码
    private String resultMsg;                 // 结果消息
    private T data;                           // 返回数据
    private LovrabetPage page;                // 分页信息(部分接口)
    private List<LovrabetField> fieldList;    // 字段列表(部分接口)

    // Getters and Setters
}

3.2 Field reference

FieldTypeDescription
successbooleanWhether the request succeeded — true for success, false for failure
resultCodeStringResult code — "0000" on success, a specific error code on failure
resultMsgStringResult message; contains error details on failure
dataTThe returned business data; the type varies by method
pageLovrabetPagePagination info (returned only by paginated queries)
fieldListListField list (returned by some methods)

3.3 Standard response-handling patterns

Pattern 1: basic check

Java
LovrabetResult<?> result = sdkClient.someMethod(request);

if (result.isSuccess()) {
    // 成功:处理业务数据
    Object data = result.getData();
    System.out.println("操作成功: " + data);
} else {
    // 失败:处理错误信息
    System.err.println("操作失败 [" + result.getResultCode() + "]: " + result.getResultMsg());
}

Pattern 2: type-safe handling

Java
// 获取单条数据
LovrabetResult<?> result = sdkClient.getOne(request);

if (result.isSuccess()) {
    Map<String, Object> data = (Map<String, Object>) result.getData();

    // 访问具体字段
    String text = (String) data.get("TEXT_1");
    Integer number = (Integer) data.get("NUMBER_3");

    System.out.println("文本字段: " + text);
    System.out.println("数字字段: " + number);
}

Pattern 3: list handling

Java
// 获取列表数据
LovrabetResult<?> result = sdkClient.getList(request);

if (result.isSuccess()) {
    List<Map<String, Object>> dataList = (List<Map<String, Object>>) result.getData();

    System.out.println("数据量: " + dataList.size());

    // 遍历处理
    for (Map<String, Object> record : dataList) {
        System.out.println("记录: " + record);
    }
}

Pattern 4: error handling with retries

Java
int maxRetries = 3;
int retryCount = 0;
LovrabetResult<?> result = null;

while (retryCount < maxRetries) {
    result = sdkClient.getOne(request);

    if (result.isSuccess()) {
        // 成功,跳出循环
        break;
    } else {
        retryCount++;
        System.err.println("尝试 " + retryCount + " 失败: " + result.getResultMsg());

        if (retryCount < maxRetries) {
            try {
                Thread.sleep(1000);  // 等待 1 秒后重试
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

// 最终处理
if (result != null && result.isSuccess()) {
    System.out.println("数据: " + result.getData());
} else {
    System.err.println("多次重试后仍然失败");
}

4. Authentication

The SDK authenticates every request with an HMAC-SHA256 signature, protecting both the security and integrity of the call.

4.1 Signing flow (automatic)

The SDK handles signing for you, but knowing the flow helps when troubleshooting:

Step 1: collect the signing parameters

The SDK collects these parameters (sorted lexicographically):

  • accessKey: the access key
  • timeStamp: timestamp in milliseconds
  • appCode: the app code
  • datasetCode: the dataset code

Step 2: build the string to sign

Plain
accessKey=ak-xxx&appCode=app-xxx&datasetCode=xxx&timeStamp=1234567890

Step 3: compute the HMAC-SHA256 signature

It computes the HMAC-SHA256 of the signing string with a fixed key, then Base64-encodes the result.

Step 4: add to request headers

The SDK adds the following information to the HTTP request headers:

  • X-Time-Stamp: timestamp
  • X-App-Code: app code
  • X-Dataset-Code: dataset code
  • X-Token: the generated signature

4.2 Security best practices

✅ Do this

Java
// 1. 使用环境变量
String accessKey = System.getenv("LOVRABET_ACCESS_KEY");

// 2. 使用配置文件
@Value("${lovrabet.accessKey}")
private String accessKey;

// 3. 使用密钥管理服务
String accessKey = secretManager.getSecret("lovrabet-access-key");

❌ Don't do this

Java
// ❌ 不要硬编码在代码中
String accessKey = "ak-OD8xWhMOsL5ChQ3Akhv4uYYiu1fPOFQGVF9BULIeov8";

// ❌ 不要提交到代码仓库
// git add config.properties  (包含 accessKey)

// ❌ 不要在日志中打印
logger.info("AccessKey: " + accessKey);  // 危险!

4.3 Common authentication issues

Issue 1: "Token invalid"

Causes:

  • The AccessKey is incorrect
  • The system clock is more than 10 minutes off from the server time

Fix:

Java
// 检查系统时间
System.out.println("当前时间戳: " + System.currentTimeMillis());

// 确认 AccessKey
System.out.println("AccessKey 前 10 位: " + accessKey.substring(0, 10));

Issue 2: "AccessKey not found or expired"

Fix:

  1. Log in to the Lovrabet platform
  2. Check that the AccessKey has been generated and hasn't expired
  3. Confirm that the OpenAPI feature is enabled
  4. Regenerate the AccessKey if needed

5. The full request-response flow

The diagram below shows one complete API call:

Plain
┌─────────────────┐
│  创建 Request   │
│  设置参数       │
└────────┬────────┘


┌─────────────────┐
│  SDK 自动签名   │  ← 自动添加时间戳、计算签名
└────────┬────────┘


┌─────────────────┐
│  发送 HTTP 请求 │  ← 携带签名头
└────────┬────────┘


┌─────────────────┐
│  服务器验证签名 │
└────────┬────────┘


┌─────────────────┐
│  处理业务逻辑   │
└────────┬────────┘


┌─────────────────┐
│  返回 Result    │  ← 包含 success、data 等
└────────┬────────┘


┌─────────────────┐
│  应用处理结果   │  ← if (result.isSuccess()) { ... }
└─────────────────┘

Example code

Java
// 1. 创建 Request
LovrabetRequest request = new LovrabetRequest();
request.setAppCode("app-c2dd52a2");
request.setModelCode("32c036010c504757b80d438e3c0ec8b7");
request.setId(513L);

// 2-4. SDK 自动完成签名、发送、验证

// 5. 服务器处理并返回 Result
LovrabetResult<?> result = sdkClient.getOne(request);

// 6. 应用处理结果
if (result.isSuccess()) {
    Map<String, Object> data = (Map<String, Object>) result.getData();
    System.out.println("查询成功: " + data);
} else {
    System.err.println("查询失败: " + result.getResultMsg());
}

Next steps

Now that you understand the core concepts, we suggest continuing in this order:

  1. 📖 Quick start — build your first CRUD program in 5 minutes
  2. 📚 Core concepts ← you are here — understand how the SDK works
  3. 📋 API reference ← recommended next — the complete API documentation
  4. 💡 Examples — 5 real-world implementations
  5. 🚀 Best practices — production optimization tips
  6. FAQ — answers to common questions

Need help? See the FAQ or contact service@lovrabet.com

基于飞书知识库同步生成,内容以飞书源文档为准