Reputation: 15
IBM MobileFirst version: 6.3 Mobile OS: Android 4.4.4
I have a use-case where we need to store a single or multiple base64-encoded image string(s) in a single document inside a collection. (Due to the nature of the use-case, it is not possible to split the images into multiple documents inside a collection)
Storing up to 7 base64-encoded image string into the same document works as intended. (A document with 7 base64 string images is added to the JSONStore). When a document with 8 base64-encoded string images has been added to the same document inside a collection. The document is successfully added to the collection. But when a findAll() is called on the collection (it only holds 1 document with 8 base64-encoded images; in this use case a findAll() is needed becasue there the data to populate a searchfield is not present at the time the data is fetched from the Collection); the following errors occure:
Java:
E/JSONSTORE(24451): JSONStoreLogger.logError in JSONStoreLogger.java:189 :: Error when attempting to find a document. An error occurred when reading from the database.
E/JSONSTORE(24451): com.worklight.jsonstore.exceptions.JSONStoreFindException: Error when attempting to find a document. An error occurred when reading from the database.
E/JSONSTORE(24451): at com.worklight.jsonstore.api.JSONStoreCollection.findDocuments(JSONStoreCollection.java:896)
E/JSONSTORE(24451): at com.worklight.androidgap.jsonstore.dispatchers.FindActionDispatcher.databaseActionDispatch(FindActionDispatcher.java:117)
E/JSONSTORE(24451): at com.worklight.androidgap.jsonstore.dispatchers.BaseDatabaseActionDispatcher.actionDispatch(BaseDatabaseActionDispatcher.java:36)
E/JSONSTORE(24451): at com.worklight.androidgap.jsonstore.dispatchers.BaseActionDispatcher.dispatch(BaseActionDispatcher.java:90)
E/JSONSTORE(24451): at com.worklight.androidgap.plugin.DispatchingPlugin$ActionDispatcherRunnable.run(DispatchingPlugin.java:79)
E/JSONSTORE(24451): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
E/JSONSTORE(24451): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
E/JSONSTORE(24451): at java.lang.Thread.run(Thread.java:841)
E/JSONSTORE(24451): Caused by: java.lang.IllegalStateException: get field slot from row 0 col 0 failed
E/JSONSTORE(24451): at net.sqlcipher.CursorWindow.getLong_native(Native Method)
E/JSONSTORE(24451): at net.sqlcipher.CursorWindow.getLong(CursorWindow.java:381)
E/JSONSTORE(24451): at net.sqlcipher.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:110)
E/JSONSTORE(24451): at net.sqlcipher.AbstractCursor.moveToPosition(AbstractCursor.java:195)
E/JSONSTORE(24451): at net.sqlcipher.AbstractCursor.moveToNext(AbstractCursor.java:257)
E/JSONSTORE(24451): at android.database.CursorWrapper.moveToNext(CursorWrapper.java:166)
E/JSONSTORE(24451): at com.worklight.jsonstore.api.JSONStoreCollection.findDocuments(JSONStoreCollection.java:877)
E/JSONSTORE(24451): ... 7 more
E/JSONSTORE(24451): JSONStoreLogger.logError in JSONStoreLogger.java:189 :: error while executing find query on database "tempCollection"com.worklight.jsonstore.exceptions.JSONStoreFindException: Error when attempting to find a document. An error occurred when reading from the database.
E/JSONSTORE(24451): com.worklight.jsonstore.exceptions.JSONStoreFindException: Error when attempting to find a document. An error occurred when reading from the database.
E/JSONSTORE(24451): at com.worklight.jsonstore.api.JSONStoreCollection.findDocuments(JSONStoreCollection.java:896)
E/JSONSTORE(24451): at com.worklight.androidgap.jsonstore.dispatchers.FindActionDispatcher.databaseActionDispatch(FindActionDispatcher.java:117)
E/JSONSTORE(24451): at com.worklight.androidgap.jsonstore.dispatchers.BaseDatabaseActionDispatcher.actionDispatch(BaseDatabaseActionDispatcher.java:36)
E/JSONSTORE(24451): at com.worklight.androidgap.jsonstore.dispatchers.BaseActionDispatcher.dispatch(BaseActionDispatcher.java:90)
E/JSONSTORE(24451): at com.worklight.androidgap.plugin.DispatchingPlugin$ActionDispatcherRunnable.run(DispatchingPlugin.java:79)
E/JSONSTORE(24451): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
E/JSONSTORE(24451): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
E/JSONSTORE(24451): at java.lang.Thread.run(Thread.java:841)
E/JSONSTORE(24451): Caused by: java.lang.IllegalStateException: get field slot from row 0 col 0 failed
E/JSONSTORE(24451): at net.sqlcipher.CursorWindow.getLong_native(Native Method)
E/JSONSTORE(24451): at net.sqlcipher.CursorWindow.getLong(CursorWindow.java:381)
E/JSONSTORE(24451): at net.sqlcipher.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:110)
E/JSONSTORE(24451): at net.sqlcipher.AbstractCursor.moveToPosition(AbstractCursor.java:195)
E/JSONSTORE(24451): at net.sqlcipher.AbstractCursor.moveToNext(AbstractCursor.java:257)
E/JSONSTORE(24451): at android.database.CursorWrapper.moveToNext(CursorWrapper.java:166)
E/JSONSTORE(24451): at com.worklight.jsonstore.api.JSONStoreCollection.findDocuments(JSONStoreCollection.java:877)
E/JSONSTORE(24451): ... 7 more
E/wl.jsonstore(24451): {"src":"find","err":22,"msg":"INVALID_SEARCH_FIELD","col":"tempCollection","usr":"testUser","doc":{},"res":{}}
Javascript:
{"src":"findAll","err":22,"msg":"INVALID_SEARCH_FIELD","col":"tempCollection","usr":"testUser","doc":{},"res":{}}
Is there something I'm doing wrong, or something I am misusing?
EDIT:
init:
var storeDetails = {
collections: {
tempCollection: {}
},
options: {
username: 'ausername',
password: 'apassword',
localKeyGen: true //Optional local key generation flag, default false.
}
};
WL.JSONStore.init(storeDetails.collections, storeDetails.options);
findAll:
var options = {
limit: 1
};
WL.JSONStore.get('tempCollection').findAll(options);
Base64-encoded image string: I am using the Cordova camera API (included with Worklight/MF). A snippet of the code: By using Camera.DestinationType.DATA_URL, the image is returned as a base64-encoded string.
var options = {
quality: 100,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
encodingType: Camera.EncodingType.PNG,
targetWidth: 500,
targetHeight: 500,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: true,
cameraDirection: Camera.Direction.BACK
};
navigator.camera.getPicture(function (imageData) {
var doc = {
src: imageData;
};
WL.JSONStore.get('tempCollection').add(doc);
}, function (err) {
}, options);
Upvotes: 0
Views: 653
Reputation: 597
I was able to reproduce your problem. After adding some images as part of a single array in a JSON doc I got the same error that you presented. But also, before the error you showed I can see this other one
05-04 20:27:38.934: E/CursorWindow(32148): need to grow: mSize = 1048576, size = 1107180, freeSpace() = 1048482, numRows = 1
05-04 20:27:38.934: E/CursorWindow(32148): Attempting to grow window beyond max size (1048576)
05-04 20:27:38.934: E/Cursor(32148): Failed allocating 1107180 bytes for text/blob at 0,1
05-04 20:27:38.935: D/Cursor(32148): finish_program_and_get_row_count row 0
05-04 20:27:39.151: E/CursorWindow(32148): need to grow: mSize = 1048576, size = 1107180, freeSpace() = 1048482, numRows = 1
05-04 20:27:39.151: E/CursorWindow(32148): Attempting to grow window beyond max size (1048576)
05-04 20:27:39.151: E/Cursor(32148): Failed allocating 1107180 bytes for text/blob at 0,1
05-04 20:27:39.152: D/Cursor(32148): finish_program_and_get_row_count row 0
05-04 20:27:39.152: E/CursorWindow(32148): Bad request for field slot 0,0. numRows = 0, numColumns = 2
So my guess is that you are stressing the limits of your device memory.
When you add several pictures to a single JSON document you are creating a huge JSON document. Then when you search it, probably there is some type o parsing operation, or something similar, that requires the entire JSON to be allocated in memory. The result of findAll itself will contain that huge json document. And possibly that need to use continuous memory allocation.
The problem is that the total amount of memory available to a single Android app is limited. The actual value depends on the device manufacturer. And it is not necessarily related to how "high-end" the device is, or total memory available in the device. Some manufactures may create devices with 2GB of memory but only a few MB available for each app, so they are prioritizing the ability to keep many apps running in parallel instead of a few apps taking all the resources.
In the end, my suggestion is that you really should store each image in an independent JSON document. You could have a single document with an array of IDs and the images stored in a second collection, or some other alternative solution.
Also note that this is NOT a limitation of JSONStore, but a limitation imposed by Android platform. A single app will never be allowed to consume all the memory resources alone, it is always limited to some MB.
Upvotes: 2