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