Skip to main content

FAQ

This document compiles frequently asked questions and solutions when using the Lovrabet Java OpenSDK.


Table of Contents


Authentication & Authorization

Q1: Getting "Invalid Token" or "Signature Verification Failed"

Possible causes:

  1. AccessKey is incorrect or expired
  2. System time differs from server time by more than 10 minutes
  3. Network request was modified by proxy or middleware

Solutions:

// 1. Verify AccessKey is correct
System.out.println("First 10 characters of AccessKey: " + accessKey.substring(0, 10));

// 2. Check system time
System.out.println("Current timestamp: " + System.currentTimeMillis());
System.out.println("Current time: " + new Date());

// 3. Confirm request parameters are correct
System.out.println("AppCode: " + request.getAppCode());
System.out.println("ModelCode: " + request.getModelCode());

If time is inaccurate:

# Linux/Mac sync system time
sudo ntpdate -u time.apple.com

# Or use NTP service
sudo systemctl start ntpd

Q2: Getting "AccessKey Does Not Exist or Has Expired"

Solutions:

  1. Log in to Lovrabet Platform
  2. Go to Application Management and check the following:
    • Whether OpenAPI feature is enabled
    • Whether AccessKey has been generated
    • Whether AccessKey is within validity period
  3. If AccessKey is expired or lost, regenerate it:
    • Go to Application Settings
    • Find OpenAPI Configuration
    • Click "Regenerate AccessKey"
    • Copy the new AccessKey and update configuration

Note: After regenerating AccessKey, the old one becomes invalid immediately. You need to update all applications using that AccessKey.


Q3: Getting "Application Code Does Not Exist"

Solutions:

  1. Check if appCode is correct:
// appCode format is usually: app-xxxxxxxx
String appCode = "app-c2dd52a2"; // Ensure format is correct

// Check for extra spaces or newlines
appCode = appCode.trim();
  1. Confirm application code in Lovrabet Platform:
    • Go to Application Management
    • View Application Details
    • Copy the correct application code

Q4: How to Manage AccessKeys for Multiple Applications?

Recommended solutions:

Method 1: Environment Variables + Configuration Files

# application.yml
lovrabet:
app1:
access-key: ${APP1_ACCESS_KEY}
app-code: app-xxx1
app2:
access-key: ${APP2_ACCESS_KEY}
app-code: app-xxx2

Method 2: Use Secret Management Service

@Configuration
public class LovrabetMultiAppConfig {

@Bean("app1Client")
public LovrabetSDKClient app1Client(SecretManager secretManager) {
String accessKey = secretManager.getSecret("lovrabet-app1-key");
return new LovrabetSDKClient(accessKey, baseUrl);
}

@Bean("app2Client")
public LovrabetSDKClient app2Client(SecretManager secretManager) {
String accessKey = secretManager.getSecret("lovrabet-app2-key");
return new LovrabetSDKClient(accessKey, baseUrl);
}
}

Parameters & Data

Q5: Getting "Required Field Missing" When Creating Data

Solutions:

  1. Log in to Lovrabet Platform and check the dataset field definitions
  2. Confirm which fields are required
  3. Ensure all required fields have values:
Map<String, Object> paramMap = new HashMap<>();

// ✅ Correct: Provide values for required fields
paramMap.put("TEXT_1", "Customer Name");
paramMap.put("NUMBER_3", 100);

// ❌ Wrong: Don't pass null values
// paramMap.put("TEXT_2", null);

// For optional empty fields, simply don't add them to paramMap

Q6: Unsure About Field Names, How to View Dataset Field Definitions?

Method 1: View in Lovrabet Platform

  1. Go to Application Management
  2. Select the corresponding dataset
  3. View field list to get field codes (e.g., TEXT_1, NUMBER_3)

Method 2: Using Browser Developer Tools

  1. Open the dataset in Lovrabet Platform
  2. Open browser developer tools (F12)
  3. Switch to Network tab
  4. Create or edit a record
  5. View request parameters to understand field names and data formats

Field Naming Rules:

  • TEXT_1, TEXT_2 - Text fields
  • NUMBER_1, NUMBER_2 - Number fields
  • SELECT_1, SELECT_2 - Select fields
  • DATETIME_1, DATETIME_2 - Date/time fields
  • BOOLEAN_1, BOOLEAN_2 - Boolean fields

Q7: How to Handle DateTime Fields?

Option 1: Use Timestamps (Recommended)

// Current time
paramMap.put("DATETIME_1", System.currentTimeMillis());

// Specific date
Calendar calendar = Calendar.getInstance();
calendar.set(2025, Calendar.JANUARY, 12, 10, 30, 0);
paramMap.put("DATETIME_1", calendar.getTimeInMillis());

// From Date object
Date date = new Date();
paramMap.put("DATETIME_1", date.getTime());

Option 2: Use String Format

// Format: yyyy-MM-dd HH:mm:ss
paramMap.put("DATETIME_1", "2025-01-12 10:30:00");

Reading DateTime:

// API returns timestamp (milliseconds)
Number timestampMs = (Number) data.get("DATETIME_1");
if (timestampMs != null) {
Date date = new Date(timestampMs.longValue());
System.out.println("Create time: " + date);
}

Q8: Do I Need to Pass All Fields When Updating Data?

No, you only need to pass the fields you want to update:

// ✅ Recommended: Only pass fields to update
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("TEXT_1", "New Customer Name"); // Only update customer name

LovrabetRequest request = new LovrabetRequest();
request.setId(513L);
request.setParamMap(paramMap);

sdkClient.update(request);

Note: The ID field is automatically added to paramMap by the SDK, no need to add it manually.


Q9: How to Handle Select Fields (Dropdowns)?

Single Select Fields:

// Select field values can be string or number, depending on dataset definition
paramMap.put("SELECT_4", "china-north"); // String type
paramMap.put("SELECT_7", 463); // Number type

Multi-Select Fields:

// Multi-select fields use List
List<String> regions = Arrays.asList("north", "south", "east");
paramMap.put("MULTI_SELECT_1", regions);

Querying Available Options for Select Fields:

Check the option list in the dataset field definition in Lovrabet Platform.


Q10: Paginated Query Returns Empty Data, But Dataset Has Data

Possible causes:

  1. Page number exceeds actual data range
  2. Query conditions filter out all data
  3. Data permission restrictions

Troubleshooting steps:

// 1. First query page 1
paramMap.put("currentPage", 1);
paramMap.put("pageSize", 10);

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

if (result.isSuccess()) {
List<?> dataList = (List<?>) result.getData();
System.out.println("Page 1 data count: " + dataList.size());

if (dataList.isEmpty()) {
// 2. Check query conditions
System.out.println("Query parameters: " + paramMap);

// 3. Try without any query conditions
Map<String, Object> simpleParams = new HashMap<>();
simpleParams.put("currentPage", 1);
simpleParams.put("pageSize", 10);
request.setParamMap(simpleParams);

LovrabetResult<?> result2 = sdkClient.getList(request);
// ...
}
}

Performance Issues

Q11: Query is Slow, How to Optimize?

Optimization strategies:

1. Reduce data volume per query

// ❌ Not recommended: pageSize too large
paramMap.put("pageSize", 1000);

// ✅ Recommended: Use reasonable pageSize
paramMap.put("pageSize", 50); // Between 20-100

2. Use local caching

// For data that doesn't change often, use caching
private final Cache<String, Map<String, Object>> cache =
Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();

public Map<String, Object> getData(String id) {
return cache.get(id, key -> fetchFromApi(key));
}

3. Concurrent queries

// Use thread pool for concurrent queries
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<Map<String, Object>>> futures = new ArrayList<>();

for (String id : idList) {
Future<Map<String, Object>> future = executor.submit(() -> {
return queryData(id);
});
futures.add(future);
}

// Collect results
for (Future<Map<String, Object>> future : futures) {
Map<String, Object> data = future.get();
// Process data
}

executor.shutdown();

Q12: Low Efficiency When Creating Large Amounts of Data, How to Improve?

Optimization solutions:

1. Use thread pool for concurrent creation

ExecutorService executor = Executors.newFixedThreadPool(10);  // Control concurrency

List<CompletableFuture<Void>> futures = dataList.stream()
.map(data -> CompletableFuture.runAsync(() -> {
try {
LovrabetRequest request = buildRequest(data);
sdkClient.create(request);
} catch (Exception e) {
logger.error("Creation failed", e);
}
}, executor))
.collect(Collectors.toList());

// Wait for all tasks to complete
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
executor.shutdown();

2. Batch processing + error retry

public void batchCreateWithRetry(List<Map<String, Object>> dataList) {
int batchSize = 100;
for (int i = 0; i < dataList.size(); i += batchSize) {
int end = Math.min(i + batchSize, dataList.size());
List<Map<String, Object>> batch = dataList.subList(i, end);

// Batch create
batchCreate(batch);

// Brief pause to avoid overload
Thread.sleep(100);
}
}

Q13: High Memory Usage

Possible causes:

  1. Loading too much data at once
  2. Not releasing resources in time

Solutions:

1. Stream processing for large data volumes

// ❌ Not recommended: Loading all data at once
List<Map<String, Object>> allData = getAllData(); // May have 100,000 records

// ✅ Recommended: Paginated stream processing
public void processAllData(Consumer<Map<String, Object>> processor) {
int currentPage = 1;
int pageSize = 100;
boolean hasMore = true;

while (hasMore) {
List<Map<String, Object>> pageData = getPageData(currentPage, pageSize);

if (pageData.isEmpty()) {
hasMore = false;
} else {
// Process current page data
pageData.forEach(processor);

// Release reference to help GC
pageData.clear();

if (pageData.size() < pageSize) {
hasMore = false;
} else {
currentPage++;
}
}
}
}

2. Clean up cache regularly

// Periodically clean cache
@Scheduled(fixedRate = 3600000) // Every hour
public void cleanupCache() {
cache.cleanUp();
logger.info("Cache cleanup completed");
}

Network Issues

Q14: Getting "Connection timeout" or "Read timeout"

Possible causes:

  1. Unstable network
  2. Slow server response
  3. Request data volume too large

Solutions:

1. Check network connectivity

# Test network connection
ping runtime.lovrabet.com

# Test HTTPS connection
curl -I https://runtime.lovrabet.com/openapi

2. Implement retry mechanism

// Use retry utility (refer to best practices documentation)
LovrabetResult<?> result = RetryHelper.executeWithRetry(
() -> sdkClient.getOne(request),
3, // Max 3 retries
1000L // Initial delay 1 second
);

3. Reduce data volume per request

// If query data volume is too large causing timeout
paramMap.put("pageSize", 20); // Reduce pageSize

Q15: Cannot Access Lovrabet API from Corporate Intranet

Possible cause: Company firewall or proxy restrictions

Solutions:

1. Configure proxy

// Set system proxy
System.setProperty("https.proxyHost", "proxy.company.com");
System.setProperty("https.proxyPort", "8080");

// If proxy requires authentication
System.setProperty("https.proxyUser", "username");
System.setProperty("https.proxyPassword", "password");

2. Contact network administrator

Add the following domains to whitelist:

  • runtime.lovrabet.com
  • Port: 443 (HTTPS)

Q16: Occasional "SocketException: Connection reset"

Cause: Network jitter or connection reset

Solution:

Implement automatic retry mechanism (refer to Best Practices - Error Handling):

LovrabetResult<?> result = RetryHelper.executeWithRetry(
() -> sdkClient.getList(request),
3, // Max 3 retries
2000L // Initial delay 2 seconds
);

Data Consistency

Q17: Cannot See Latest Value After Updating Data

Possible causes:

  1. Database master-slave sync delay
  2. Local cache not updated

Solutions:

1. Wait briefly before querying

// Update data
sdkClient.update(updateRequest);

// Brief wait (usually 100-200ms is enough)
Thread.sleep(100);

// Query data
LovrabetResult<?> result = sdkClient.getOne(queryRequest);

2. Use data returned from update

// Use local data directly after update, don't re-query
Map<String, Object> localData = updateRequest.getParamMap();
// Use localData instead of re-querying

3. Clear local cache

// Clear cache after update
sdkClient.update(request);
cache.invalidate(id); // Clear cache for this ID

Q18: How to Avoid Conflicts When Concurrently Updating Same Data?

Option 1: Optimistic Locking (Recommended)

public boolean updateWithVersion(Long id, Map<String, Object> newData) {
// 1. Query current data and version number
Map<String, Object> current = getData(id);
Integer currentVersion = (Integer) current.get("version");

// 2. Include version number when updating
newData.put("version", currentVersion + 1);

LovrabetRequest request = new LovrabetRequest();
request.setId(id);
request.setParamMap(newData);

LovrabetResult<String> result = sdkClient.update(request);

// 3. Check update result
if (!result.isSuccess()) {
// Version conflict, may need to retry
logger.warn("Version conflict, current version: {}", currentVersion);
return false;
}

return true;
}

Option 2: Distributed Lock

public void updateWithLock(Long id, Map<String, Object> newData) {
String lockKey = "lovrabet:lock:" + id;

// Acquire distributed lock
RLock lock = redissonClient.getLock(lockKey);

try {
// Try to acquire lock, wait up to 10 seconds, lock timeout 30 seconds
if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
try {
// Execute update operation
sdkClient.update(buildRequest(id, newData));
} finally {
lock.unlock();
}
} else {
logger.warn("Lock acquisition timeout: {}", id);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

Development & Debugging

Q19: How to View HTTP Request Details Sent by SDK?

Method 1: Enable logging

# application.yml or logback.xml
logging:
level:
com.lovrabet.runtime.opensdk: DEBUG

Method 2: Use packet capture tools

  • Windows: Fiddler
  • Mac: Charles Proxy
  • Cross-platform: Wireshark

Configure proxy:

System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", "8888"); // Charles default port

Q20: How to Test SDK in Local Development Environment?

Option 1: Use test datasets

Create dedicated test datasets in Lovrabet Platform to avoid polluting production data.

# application-dev.yml
lovrabet:
app-code: app-dev-xxx
model-code: test-dataset-xxx

Option 2: Mock SDK client

@TestConfiguration
public class TestConfig {

@Bean
@Primary // Override normal Bean
public LovrabetSDKClient mockSdkClient() {
LovrabetSDKClient mockClient = Mockito.mock(LovrabetSDKClient.class);

// Set Mock behavior
LovrabetResult<String> mockResult = new LovrabetResult<>();
mockResult.setSuccess(true);
mockResult.setData("mock-id-12345");

Mockito.when(mockClient.create(Mockito.any()))
.thenReturn(mockResult);

return mockClient;
}
}

Q21: How to Troubleshoot "Data Created Successfully But Cannot Query"?

Troubleshooting steps:

// 1. Create data and record returned ID
LovrabetResult<String> createResult = sdkClient.create(request);
if (createResult.isSuccess()) {
String newId = createResult.getData();
logger.info("Creation successful, new ID: {}", newId);

// 2. Query immediately to confirm
Thread.sleep(200); // Wait 200ms

LovrabetRequest queryRequest = new LovrabetRequest();
queryRequest.setAppCode(appCode);
queryRequest.setModelCode(modelCode);
queryRequest.setId(Long.parseLong(newId));

LovrabetResult<?> queryResult = sdkClient.getOne(queryRequest);

if (queryResult.isSuccess()) {
Map<String, Object> data = (Map<String, Object>) queryResult.getData();
logger.info("Query successful: {}", data);
} else {
logger.error("Query failed: {}", queryResult.getResultMsg());
// 3. Check if appCode and modelCode are consistent
logger.error("Creation appCode: {}, modelCode: {}",
request.getAppCode(), request.getModelCode());
logger.error("Query appCode: {}, modelCode: {}",
queryRequest.getAppCode(), queryRequest.getModelCode());
}
}

Q22: How to Upgrade SDK Version?

Maven Projects:

<dependency>
<groupId>com.lovrabet.runtime</groupId>
<artifactId>lovrabet-runtime-opensdk</artifactId>
<version>1.1.0-SNAPSHOT</version> <!-- Update version number -->
</dependency>

Then execute:

mvn clean install

Gradle Projects:

implementation 'com.lovrabet.runtime:lovrabet-runtime-opensdk:1.1.0-SNAPSHOT'

Then execute:

./gradlew clean build

Upgrade notes:

  1. Check official documentation for change details
  2. Verify in test environment before upgrading production
  3. Watch for breaking changes

Getting Help

If the above issues don't solve your questions, please get help through the following channels:

Technical Support

When Reporting Issues, Please Provide:

  1. SDK Version: lovrabet-runtime-opensdk version number
  2. JDK Version: Java version being used
  3. Error Message: Complete error stack (sanitize sensitive information)
  4. Steps to Reproduce: How to trigger the issue
  5. Code Snippet: Relevant code example (sanitized)

Example Email:

Subject: [OpenSDK] Required field missing error when creating data

Hello,

I encountered an issue when using Lovrabet Java OpenSDK:

1. SDK Version: lovrabet-runtime-opensdk 1.0.0-SNAPSHOT
2. JDK Version: Java 11
3. Error Message:
resultCode: PARAM_ERROR
resultMsg: Required field TEXT_1 is missing

4. Code Snippet:
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("TEXT_1", "Test data");
// ...

5. Solutions Already Tried:
- Confirmed field name is correct
- Confirmed value is not null

How can I resolve this issue?

Thanks!

Next Steps

After reviewing the FAQ, you can follow this order to review the learning materials:

  1. 📖 Quick Start Complete your first CRUD program in 5 minutes

  2. 📚 Core Concepts Deep dive into how the SDK works

  3. 📋 API Reference Browse the complete interface documentation

  4. 💡 Business Examples Learn 5 real-world scenario implementations

  5. 🚀 Best Practices Master production environment optimization techniques

  6. FAQ ← Current location Resolve questions during usage


Last Updated: 2025-10-12