FAQ
This document compiles frequently asked questions and solutions when using the Lovrabet Java OpenSDK.
Table of Contents
- Authentication & Authorization
- Parameters & Data
- Performance Issues
- Network Issues
- Data Consistency
- Development & Debugging
Authentication & Authorization
Q1: Getting "Invalid Token" or "Signature Verification Failed"
Possible causes:
- AccessKey is incorrect or expired
- System time differs from server time by more than 10 minutes
- 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:
- Log in to Lovrabet Platform
- Go to Application Management and check the following:
- Whether OpenAPI feature is enabled
- Whether AccessKey has been generated
- Whether AccessKey is within validity period
- 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:
- Check if
appCodeis correct:
// appCode format is usually: app-xxxxxxxx
String appCode = "app-c2dd52a2"; // Ensure format is correct
// Check for extra spaces or newlines
appCode = appCode.trim();
- 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:
- Log in to Lovrabet Platform and check the dataset field definitions
- Confirm which fields are required
- 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
- Go to Application Management
- Select the corresponding dataset
- View field list to get field codes (e.g.,
TEXT_1,NUMBER_3)
Method 2: Using Browser Developer Tools
- Open the dataset in Lovrabet Platform
- Open browser developer tools (F12)
- Switch to Network tab
- Create or edit a record
- View request parameters to understand field names and data formats
Field Naming Rules:
TEXT_1,TEXT_2- Text fieldsNUMBER_1,NUMBER_2- Number fieldsSELECT_1,SELECT_2- Select fieldsDATETIME_1,DATETIME_2- Date/time fieldsBOOLEAN_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:
- Page number exceeds actual data range
- Query conditions filter out all data
- 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:
- Loading too much data at once
- 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:
- Unstable network
- Slow server response
- 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:
- Database master-slave sync delay
- 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:
- Check official documentation for change details
- Verify in test environment before upgrading production
- Watch for breaking changes
Getting Help
If the above issues don't solve your questions, please get help through the following channels:
Technical Support
- 📧 Email: service@lovrabet.com
- 🌐 Official Website: https://lovrabet.com
- 📚 Documentation Center: https://open.lovrabet.com
When Reporting Issues, Please Provide:
- SDK Version:
lovrabet-runtime-opensdkversion number - JDK Version: Java version being used
- Error Message: Complete error stack (sanitize sensitive information)
- Steps to Reproduce: How to trigger the issue
- 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:
-
📖 Quick Start Complete your first CRUD program in 5 minutes
-
📚 Core Concepts Deep dive into how the SDK works
-
📋 API Reference Browse the complete interface documentation
-
💡 Business Examples Learn 5 real-world scenario implementations
-
🚀 Best Practices Master production environment optimization techniques
-
❓ FAQ ← Current location Resolve questions during usage
Last Updated: 2025-10-12