Troubleshooting JSONStore
Overview
Find information to help resolve issues that you might encounter when you use the JSONStore API.
Provide information when you ask for help
It is better to provide more information than to risk not providing enough information. The following list is a good starting point for the information that is required to help with JSONStore issues.
- Operating system and version. For example, Windows XP SP3 Virtual Machine or Mac OSX 10.8.3.
- Eclipse version. For example, Eclipse Indigo 3.7 Java EE.
- JDK version. For example, Java SE Runtime Environment (build 1.7).
- PMF version. For example, PMF 9.0
- iOS version. For example, iOS Simulator 6.1 or iPhone 4S iOS 6.0 (deprecated, see Deprecated features and API elements).
- Android version. For example, Android Emulator 4.1.1 or Samsung Galaxy Android 4.0 API Level 14.
- adb version. For example, Android Debug Bridge version 1.0.31.
- Logs, such as Xcode output on iOS or logcat output on Android.
Try to isolate the issue
Follow these steps to isolate the issue to more accurately report a problem.
- Reset the emulator (Android) or simulator (iOS) and call the destroy API to start with a clean system.
- Ensure that you are running on a supported production environment.
- Android >= 2.3 ARM v7/ARM v8/x86 emulator or device
- iOS >= 6.0 simulator or device (deprecated)
- Try to turn off encryption by not passing a password to the init or open APIs.
-
Look at the SQLite database file that is generated by JSONStore. Encryption must be turned off.
- Android emulator:
$ adb shell $ cd /data/data/com.<app-name>/databases/wljsonstore $ sqlite3 jsonstore.sqlite
- iOS Simulator:
$ cd ~/Library/Application Support/iPhone Simulator/7.1/Applications/<id>/Documents/wljsonstore $ sqlite3 jsonstore.sqlite
- Note: JavaScript only implementation that runs on a web browser (Firefox, Chrome, Safari, Internet Explorer) does not use an SQLite database. The file is stores in HTML5 LocalStorage.
- Look at the
searchFields
with.schema
and select data withSELECT * FROM <collection-name>;
. To exit sqlite3, type.exit
. If you pass a user name to the init method, the file is called the-username.sqlite. If you do not pass a user name, the file is called jsonstore.sqlite by default.
-
(Android only) Enable verbose JSONStore.
adb shell setprop log.tag.jsonstore-core VERBOSE adb shell getprop log.tag.jsonstore-core
- Use the debugger.
Common issues
Understanding the following JSONStore characteristics can help resolve some of the common issues that you might encounter.
- The only way to store binary data in JSONStore is to first encode it in base64. Store file names or paths instead of the actual files in JSONStore.
- Accessing JSONStore data from native code is possible in PMF 9.0
- There is no limit on how much data you can store inside JSONStore, beyond limits that are imposed by the mobile operating system.
-
JSONStore provides persistent data storage. It is not only stored in memory.
- There is a difference between a number and an integer in search fields. Numeric values like
1
and2
are stored as1.0
and2.0
when the type isnumber
. They are stored as1
and2
when the type isinteger
. - If an application is forced to stop or crashes, it always fails with error code -1 when the application is started again and the
init
oropen
API is called. If this problem happens, call thecloseAll
API first. - The JavaScript implementation of JSONStore expects code to be called serially. Wait for an operation to finish before you call the next one.
- Transactions are not supported in Android 2.3.x for Cordova applications.
- When you use JSONStore on a 64-bit device, you might see the following error:
java.lang.UnsatisfiedLinkError: dlopen failed: "..." is 32-bit instead of 64-bit
- This error means that you have 64-bit native libraries in your Android project, and JSONStore does not currently work when you use these libraries. To confirm, go to src/main/libs or src/main/jniLibs under your Android project, and check whether you have the x86_64 or arm64-v8a folders. If you do, delete these folders, and JSONStore can work again.
-
In some cases (or environments), the flow enters
wlCommonInit()
before JSONStore plugin is initialized. This causes JSONStore related API calls to fail. Thecordova-plugin-mfp
bootstrap callsWL.Client.init
automatically which triggers thewlCommonInit
function when it is completed. This initialization process is different for the JSONStore plugin. The JSONStore plugin does not have a way to halt theWL.Client.init
call. Across different environments, it may happen that the flow enterswlCommonInit()
beforemfpjsonjslloaded
completes. To ensure the ordering ofmfpjsonjsloaded
andmfpjsloaded
events, the developer has the option of callingWL.CLient.init
manually. This will remove the need for having platform specific code.Follow the steps below to configure calling of
WL.CLient.init
manually:- In
config.xml
, change theclientCustomInit
property to true.
- In
index.js
file:- add the following line at the beginning of the file:
document.addEventListener('mfpjsonjsloaded', initWL, false);
-
leave the
WL.JSONStore.init
call inwlCommonInit()
- add the following function:
function initWL(){ var options = typeof wlInitOptions !== 'undefined' ? wlInitOptions : {}; WL.Client.init(options); }
- add the following line at the beginning of the file:
This will wait for the
mfpjsonjsloaded
event (outside ofwlCommonInit
), this will ensure that the script has been loaded and will subsequently callWL.Client.init
which will triggerwlCommonInit
, this will then callWL.JSONStore.init
. - In
Store internals
See an example of how JSONStore data is stored.
The key elements in this simplified example:
_id
is the unique identifier (for example, AUTO INCREMENT PRIMARY KEY).json
contains an exact representation of the JSON object that is stored.name
and age are search fields.key
is an extra search field.
_id | key | name | age | JSON |
---|---|---|---|---|
1 | c | carlos | 99 | {name: ‘carlos’, age: 99} |
2 | t | tim | 100 | {name: ‘tim’, age: 100} |
When you search by using one of the following queries or a combination of them: {_id : 1}, {name: 'carlos'}
, {age: 99}, {key: 'c'}
, the returned document is {_id: 1, json: {name: 'carlos', age: 99} }
.
The other internal JSONStore fields are:
_dirty
: Determines whether the document was marked as dirty or not. This field is useful to track changes to the documents._deleted
: Marks a document as deleted or not. This field is useful to remove objects from the collection, to later use them to track changes with your backend and decide whether to remove them or not._operation
: A string that reflects the last operation to be performed on the document (for example, replace).
JSONStore errors
JavaScript
JSONStore uses an error object to return messages about the cause of failures.
When an error occurs during a JSONStore operation (for example the find
, and add
methods in the JSONStoreInstance
class) an error object is returned. It provides information about the cause of the failure.
var errorObject = {
src: 'find', // Operation that failed.
err: -50, // Error code.
msg: 'PERSISTENT\_STORE\_FAILURE', // Error message.
col: 'people', // Collection name.
usr: 'jsonstore', // User name.
doc: {_id: 1, {name: 'carlos', age: 99}}, // Document that is related to the failure.
res: {...} // Response from the server.
}
Not all the key/value pairs are part of every error object. For example, the doc value is only available when the operation failed because of a document (for example the remove
method in the JSONStoreInstance
class) failed to remove a document.
Objective-C
All of the APIs that might fail take an error parameter that takes an address to an NSError object. If you don not want to be notified of errors, you can pass in nil
. When an operation fails, the address is populated with an NSError, which has an error and some potential userInfo
. The userInfo
might contain extra details (for example, the document that caused the failure).
// This NSError points to an error if one occurs.
NSError* error = nil;
// Perform the destroy.
[JSONStore destroyDataAndReturnError:&error];
Java
All of the Java API calls throw a certain exception, depending on the error that happened. You can either handle each exception separately, or you can catch JSONStoreException
as an umbrella for all JSONStore exceptions.
try {
WL.JSONStore.closeAll();
}
catch(JSONStoreException e) {
// Handle error condition.
}
List of error codes
List of common error codes and their description:
Error Code | Description |
---|---|
-100 UNKNOWN_FAILURE | Unrecognized error. |
-75 OS_SECURITY_FAILURE | This error code is related to the requireOperatingSystemSecurity flag. It can occur if the destroy API fails to remove security metadata that is protected by operating system security (Touch ID with passcode fallback), or the init or open APIs are unable to locate the security metadata. It can also fail if the device does not support operating system security, but operating system security usage was requested. |
-50 PERSISTENT_STORE_NOT_OPEN | JSONStore is closed. Try calling the open method in the JSONStore class class first to enable access to the store. |
-48 TRANSACTION_FAILURE_DURING_ROLLBACK | There was a problem with rolling back the transaction. |
-47 TRANSACTION\_FAILURE_DURING_REMOVE_COLLECTION | Cannot call removeCollection while a transaction is in progress. |
-46 TRANSACTION_FAILURE_DURING_DESTROY | Cannot call destroy while there are transactions in progress. |
-45 TRANSACTION_FAILURE_DURING_CLOSE_ALL | Cannot call closeAll while there are transactions in place. |
-44 TRANSACTION_FAILURE_DURING_INIT | Cannot initialize a store while there are transactions in progress. |
-43 TRANSACTION_FAILURE | There was a problem with transactions. |
-42 NO_TRANSACTION_IN_PROGRESS | Cannot commit to rolled back a transaction when there is no transaction is progress |
-41 TRANSACTION_IN_POGRESS | Cannot start a new transaction while another transaction is in progress. |
-40 FIPS_ENABLEMENT_FAILURE | Something is wrong with FIPS. |
-24 JSON_STORE_FILE_INFO_ERROR | Problem getting the file information from the file system. |
-23 JSON_STORE_REPLACE_DOCUMENTS_FAILURE | Problem replacing documents from a collection. |
-22 JSON_STORE_REMOVE_WITH_QUERIES_FAILURE | Problem removing documents from a collection. |
-21 JSON_STORE_STORE_DATA_PROTECTION_KEY_FAILURE | Problem storing the Data Protection Key (DPK). |
-20 JSON_STORE_INVALID_JSON_STRUCTURE | Problem indexing input data. |
-12 INVALID_SEARCH_FIELD_TYPES | Check that the types that you are passing to the searchFields are stringinteger,number, orboolean. |
-11 OPERATION_FAILED_ON_SPECIFIC_DOCUMENT | An operation on an array of documents, for example the replace method can fail while it works with a specific document. The document that failed is returned and the transaction is rolled back. On Android, this error also occurs when trying to use JSONStore on unsupported architectures. |
-10 ACCEPT_CONDITION_FAILED | The accept function that the user provided returned false. |
-9 OFFSET_WITHOUT_LIMIT | To use offset, you must also specify a limit. |
-8 INVALID_LIMIT_OR_OFFSET | Validation error, must be a positive integer. |
-7 INVALID_USERNAME | Validation error (Must be [A-Z] or [a-z] or [0-9] only). |
-6 USERNAME_MISMATCH_DETECTED | To log out, a JSONStore user must call the closeAll method first. There can be only one user at a time. |
-5 DESTROY_REMOVE_PERSISTENT_STORE_FAILED | A problem with the destroy method while it tried to delete the file that holds the contents of the store. |
-4 DESTROY_REMOVE_KEYS_FAILED | Problem with the destroy method while it tried to clear the keychain (iOS) or shared user preferences (Android). |
-3 INVALID_KEY_ON_PROVISION | Passed the wrong password to an encrypted store. |
-2 PROVISION_TABLE_SEARCH_FIELDS_MISMATCH | Search fields are not dynamic. It is not possible to change search fields without calling the destroy method or the removeCollection method before you call the init or openmethod with the new search fields. This error can occur if you change the name or type of the search field. For example: {key: ‘string’} to {key: ‘number’} or {myKey: ‘string’} to {theKey: ‘string’}. |
-1 PERSISTENT_STORE_FAILURE | Generic Error. A malfunction in native code, most likely calling the init method. |
0 SUCCESS | In some cases, JSONStore native code returns 0 to indicate success. |
1 BAD_PARAMETER_EXPECTED_INT | Validation error. |
2 BAD_PARAMETER_EXPECTED_STRING | Validation error. |
3 BAD_PARAMETER_EXPECTED_FUNCTION | Validation error. |
4 BAD_PARAMETER_EXPECTED_ALPHANUMERIC_STRING | Validation error. |
5 BAD_PARAMETER_EXPECTED_OBJECT | Validation error. |
6 BAD_PARAMETER_EXPECTED_SIMPLE_OBJECT | Validation error. |
7 BAD_PARAMETER_EXPECTED_DOCUMENT | Validation error. |
8 FAILED_TO_GET_UNPUSHED_DOCUMENTS_FROM_DB | The query that selects all documents that are marked dirty failed. An example in SQL of the query would be: SELECT * FROM [collection] WHERE _dirty > 0. |
9 NO_ADAPTER_LINKED_TO_COLLECTION | To use functions like the push and load methods in the JSONStoreCollection class, an adapter must be passed to the init method. |
10 BAD_PARAMETER_EXPECTED_DOCUMENT_OR_ARRAY_OF_DOCUMENTS | Validation error |
11 INVALID_PASSWORD_EXPECTED_ALPHANUMERIC_STRING_WITH_LENGTH_GREATER_THAN_ZERO | Validation error |
12 ADAPTER_FAILURE | Problem calling WL.Client.invokeProcedure, specifically a problem in connecting to the adapter. This error is different from a failure in the adapter that tries to call a backend. |
13 BAD_PARAMETER_EXPECTED_DOCUMENT_OR_ID | Validation error |
14 CAN_NOT_REPLACE_DEFAULT_FUNCTIONS | Calling the enhance method in the JSONStoreCollection class to replace an existing function (find and add) is not allowed. |
15 COULD_NOT_MARK_DOCUMENT_PUSHED | Push sends the document to an adapter but JSONStore fails to mark the document as not dirty. |
16 COULD_NOT_GET_SECURE_KEY | To initiate a collection with a password there must be connectivity to the PMF because it returns a ‘secure random token’. IBM Worklight V5.0.6 and later allows developers to generate the secure random token locally passing {localKeyGen: true} to the init method via the options object. |
17 FAILED_TO_LOAD_INITIAL_DATA_FROM_ADAPTER | Could not load data because WL.Client.invokeProcedure called the failure callback. |
18 FAILED_TO_LOAD_INITIAL_DATA_FROM_ADAPTER_INVALID_LOAD_OBJ | The load object that was passed to the init method did not pass the validation. |
19 INVALID_KEY_IN_LOAD_OBJECT | There is a problem with the key used in the load object when you call the add method. |
20 UNDEFINED_PUSH_OPERATION | No procedure is defined for pushing dirty documents to the server. For example: the init method (new document is dirty, operation = ‘add’) and the push method (finds the new document with operation = ‘add’) were called, but no add key with the add procedure was found in the adapter that is linked to the collection. Linking an adapter is done inside the init method. |
21 INVALID_ADD_INDEX_KEY | Problem with extra search fields. |
22 INVALID_SEARCH_FIELD | One of your search fields is invalid. Verify that none of the search fields that are passed in are _id,json,_deleted, or _operation. |
23 ERROR_CLOSING_ALL | Generic Error. An error occurred when native code called the closeAll method. |
24 ERROR_CHANGING_PASSWORD | Unable to change the password. The old password passed was wrong, for example. |
25 ERROR_DURING_DESTROY | Generic Error. An error occurred when native code called the destroy method. |
26 ERROR_CLEARING_COLLECTION | Generic Error. An error occurred in when native code called the removeCollection method. |
27 INVALID_PARAMETER_FOR_FIND_BY_ID | Validation error. |
28 INVALID_SORT_OBJECT | The provided array for sorting is invalid because one of the JSON objects is invalid. The correct syntax is an array of JSON objects, where each object contains only a single property. This property searches the field with which to sort, and whether it is ascending or descending. For example: {searchField1 : “ASC”}. |
29 INVALID_FILTER_ARRAY | The provided array for filtering the results is invalid. The correct syntax for this array is an array of strings, in which each string is either a search field or an internal JSONStore field. For more information, see Store internals. |
30 BAD_PARAMETER_EXPECTED_ARRAY_OF_OBJECTS | Validation error when the array is not an array of only JSON objects. |
31 BAD_PARAMETER_EXPECTED_ARRAY_OF_CLEAN_DOCUMENTS | Validation error. |
32 BAD_PARAMETER_WRONG_SEARCH_CRITERIA | Validation error. |