PROVISION_TABLE_SEARCH_FIELDS_MISMATCH for IBM Mobile First JsonStore Initialization - ibm-mobilefirst

I am using Javascript JSONStore to initialize JsonStore collection in IBM Mobile First Platform 8.0.0. The issue I am facing is below code working fine for some device and for some device is it Giving below error.
01-19 19:49:43.487 11622-11646/com.mobiInspect D/JSONSTORE: JSONStoreLogger.logTrace in JSONStoreLogger.java:197 :: Table schema mismatch for existing collection.
01-19 19:49:43.492 11622-11646/com.mobiInspect D/JSONSTORE: JSONStoreLogger.logTrace in JSONStoreLogger.java:197 :: dispatching action "provision"
01-19 19:49:43.498 11622-11646/com.mobiInspect D/JSONSTORE: JSONStoreLogger.logTrace in JSONStoreLogger.java:197 :: invoking action dispatcher "provision" with parameters:
01-19 19:49:43.501 11622-11646/com.mobiInspect D/JSONSTORE: JSONStoreLogger.logTrace in JSONStoreLogger.java:197 :: dbName=inspectorList
01-19 19:49:43.505 11622-11622/com.mobiInspect D/WebView: evaluateJavascript=cordova.callbackFromNative('LoggerPlugin1661877744',true,1,["OK"],false);
01-19 19:49:43.506 11622-11646/com.mobiInspect D/JSONSTORE: JSONStoreLogger.logTrace in JSONStoreLogger.java:197 :: schema={"name":"string"}
01-19 19:49:43.512 11622-11646/com.mobiInspect D/JSONSTORE: JSONStoreLogger.logTrace in JSONStoreLogger.java:197 :: options=[value not logged]
01-19 19:49:43.515 11622-11646/com.mobiInspect D/JSONSTORE: JSONStoreLogger.logTrace in JSONStoreLogger.java:197 :: additionalSearchFields={}
01-19 19:49:43.519 11622-11646/com.mobiInspect D/JSONSTORE: JSONStoreLogger.logTrace in JSONStoreLogger.java:197 :: dropCollection=false
01-19 19:49:43.523 11622-11646/com.mobiInspect D/JSONSTORE: JSONStoreLogger.logTrace in JSONStoreLogger.java:197 :: username=jsonstore
01-19 19:49:43.529 11622-11646/com.mobiInspect D/JSONSTORE: JSONStoreLogger.logTrace in JSONStoreLogger.java:197 :: collectionPassword=xxxxxxxx
01-19 19:49:43.533 11622-11646/com.mobiInspect E/null: Initialization failure on : Task List Collection {"src":"initCollection","err":-2,"msg":"PROVISION_TABLE_SEARCH_FIELDS_MISMATCH","col":"myTasks","usr":"jsonstore","doc":{},"res":{}}
01-19 19:49:43.535 11622-11646/com.mobiInspect E/wl.jsonstore: {"src":"initCollection","err":-2,"msg":"PROVISION_TABLE_SEARCH_FIELDS_MISMATCH","col":"myTasks","usr":"jsonstore","doc":{},"res":{}}
01-19 19:49:43.753 11622-11633/com.mobiInspect I/art: Background sticky concurrent mark sweep GC freed 41582(2MB) AllocSpace objects, 0(0B) LOS objects, 10% free, 15MB/17MB, paused 3.657ms total 148.294ms
01-19 19:49:43.768 11622-11646/com.mobiInspect D/wl.response: WLResponse. in WLResponse.java:69 :: Response does not include a Content-Encoding header. Attempting to read response body.
01-19 19:49:43.814 11622-11646/com.mobiInspect D/wl.request: WLRequestSender.run in WLRequestSender.java:43 :: Sending request https://www.serverurl.com/mfp/api/az/v1/token
$scope.init_collection = function () {
ProgressIndicator.showSimpleWithLabel(false, 'Loading...');
//Data Collection
collections1['COLLECTION_NAME'] = {
searchFields: {'id': 'string', 'processid': 'string', 'state': 'integer'}
};
WL.JSONStore.init(collections1, options)
.then(function () {
WL.Logger.info("Inside Task Submission Collection");
WL.JSONStore.fileInfo()
.then(function (res) {
WL.Logger.debug(" Success response of Task Submission Collection fileInfo :" +JSON.stringify(res));
//res => [{isEncrypted : true, name : carlos, size : 3072}]
})
.fail(function (failRes) {
WL.Logger.debug("Failure response of Task Submission Collection fileInfo :" +JSON.stringify(failRes));
// Handle failure.
});
})
.fail(function (errorObject) {
//WL.Logger.error(Messages.ERR_LGN_FAIL_INI_DTA_STRG);
WL.Logger.error("Initialization failure on : Task Submission Collection "+JSON.stringify(errorObject));
});
//WL.Logger.info(Messages.INF_LGN_INI_DTA_STRG);
//Data Collection
//Image Collection
collections2["COLLECTION_IMAGE"] = {
searchFields: {'id': 'string', 'processid': 'string', 'isImageSubmitted': 'boolean'}
};
WL.JSONStore.init(collections2, options)
.then(function () {
WL.Logger.info("Inside Image Submission Collection");
WL.JSONStore.fileInfo()
.then(function (res) {
WL.Logger.debug(" Success response of Image Submission Collection fileInfo :" +JSON.stringify(res));
//res => [{isEncrypted : true, name : carlos, size : 3072}]
})
.fail(function (failRes) {
WL.Logger.debug("Failure response of Image Submission Collection fileInfo :" +JSON.stringify(failRes));
// Handle failure.
});
})
.fail(function (errorObject) {
//WL.Logger.error(Messages.ERR_LGN_FAIL_INI_IMG_CLL);
WL.Logger.error("Initialization failure on : Image Submission Collection "+JSON.stringify(errorObject));
});
//WL.Logger.info(Messages.INF_LGN_CLL_INI);
//Image Collection
//TODAY Collection
collections3["COLLECTION_TODAY"] = {
searchFields: {'id': 'string', 'processid': 'string', 'state': 'integer', 'insname': 'string'}
};
WL.JSONStore.init(collections3, options)
.then(function () {
WL.Logger.info("Inside Task List Collection");
WL.JSONStore.fileInfo()
.then(function (res) {
WL.Logger.debug("Success response of Task List Collection fileInfo :" +JSON.stringify(res));
//res => [{isEncrypted : true, name : carlos, size : 3072}]
})
.fail(function (failRes) {
WL.Logger.debug("Failure response of Task List Collection fileInfo :" +JSON.stringify(failRes));
// Handle failure.
});
})
.fail(function (errorObject) {
//WL.Logger.error(Messages.ERR_LGN_FAIL_INI_IMG_CLL);
WL.Logger.error("Initialization failure on : Task List Collection "+JSON.stringify(errorObject));
});
//WL.Logger.info(Messages.INF_LGN_CLL_INI);
//TODAY Collection
//List Collection
collections4["COLLECTION_LIST"] = {
searchFields: {'name': 'string'}
};
WL.JSONStore.init(collections4, options)
.then(function () {
WL.Logger.info("Inside Inspector List Collection");
WL.JSONStore.fileInfo()
.then(function (res) {
WL.Logger.debug("Success response of Inspector List Collection fileInfo :" +JSON.stringify(res));
//res => [{isEncrypted : true, name : carlos, size : 3072}]
})
.fail(function (failRes) {
WL.Logger.debug("Failure response of Inspector List Collection fileInfo :" +JSON.stringify(failRes));
// Handle failure.
});
})
.fail(function (errorObject) {
//WL.Logger.error(Messages.ERR_LGN_FAIL_INI_IMG_CLL);
WL.Logger.error("Initialization failure on : Inspector List Collection " +JSON.stringify(errorObject));
});
WL.Logger.info(Messages.INF_LGN_CLL_INI);
//List Collection
};
Am I missing anything here for JsonStore Initialization in IBM MFP 8.0? Any help would be appreciated.

Error msg 'PROVISION_TABLE_SEARCH_FIELDS_MISMATCH' can occur when
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’}.
See here for more details :
http://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/8.0/troubleshooting/jsonstore/

Related

Accessing object properties in Vue after loading in Sails app

When the SailsJS app loads a page, I have it pulling the id parameter from the url and loading a recipe from the database. The recipe object logs to console correctly, so I'm sure it's loading, but none of the Vue variables are rendering.
I'm loading the data in this controller action:
// api/controllers/recipes/view-single-recipe.js
module.exports = {
friendlyName: 'View single recipe',
description: 'Display "Single recipe" page.',
exits: {
success: {
viewTemplatePath: 'pages/recipes/single-recipe'
}
},
fn: async function (inputs, exits) {
const recipe = await Recipe.find({id: this.req.params.id}).populate('ingredients')
console.log(recipe) //logs the data correctly
return exits.success({
recipe: recipe
});
}
};
Then I'm atteming to access the recipe object in my view using VueJS:
<!-- views/pages/recipes/single-recipe.ejs -->
<div id="single-recipe" v-cloak>
<h1>{{recipe.name}}</h1> <!-- rendering as <h1></h1>
<!-- ... more stuff ... -->
</div>
<%- /* Expose server-rendered data as window.SAILS_LOCALS :: */ exposeLocalsToBrowser() %>
Here's the data object that loads:
[{
ingredients: [
[Object],
[Object],
[Object],
[Object],
[Object]
],
createdAt: 1536016866419,
updatedAt: 1536016866419,
id: '5b8c169936f1df3439fa39c7',
name: 'Sweet Green',
ratingSweet: 2,
ratingTexture: 5,
ratingOverall: 4,
ratingColor: 5,
notes: 'Personal favorite, maybe needs more ginger',
owner: '5b8c16301cee97343513e184'
}]
Not sure if it matters, but here is the route:
'GET /recipes/single-recipe/:id': { action: 'recipes/view-single-recipe' }
And the URL being access is http://localhost:1337/recipes/single-recipe/5b8c169936f1df3439fa39c7
How do I access the data object properties in the view?
You should use findOne
// api/controllers/recipes/view-single-recipe.js
module.exports = {
friendlyName: 'View single recipe',
description: 'Display "Single recipe" page.',
exits: {
success: {
viewTemplatePath: 'pages/recipes/single-recipe'
}
},
fn: async function (inputs, exits) {
const recipe = await Recipe.findOne({
id: this.req.params.id
}).populate('ingredients')
return exits.success({ recipe: recipe });
}
};
Also note that inputs variable in fn are not being used.
And there need to be some handler if record is not exists.
The answer is that when using find() query, the results returned are an array. So if there is only one result, it needs to be accessed at the first result in the array [0]
// api/controllers/recipes/view-single-recipe.js
module.exports = {
// ...
fn: async function (inputs, exits) {
const recipe = await Recipe.find({id: this.req.params.id}).populate('ingredients')
console.log(recipe) //logs the data correctly
return exits.success({
recipe: recipe[0]
});
}
};

How to avoid duplicate entries in IBM JSONStore

WL.JSONStore.get(collectionName).change(data, options) method does not seem to work for duplicate values. I get duplicate values entered whenever data is loaded through the adapter. Below is the code that I have used to avoid duplicate entries.
init(){
console.log('JSONStore init function callled');
let collections = {
activities: {
searchField: {serialKey: 'string'},
adapter: {
name: 'ServiceAdapter',
add: 'pushActivities',
remove: 'removeActivity',
replace: 'replaceActivity',
load: {
procedure: 'getActivities',
params: [],
key: 'rows'
}
}
}
}
WL.JSONStore.init(collections).then((success) => {
console.log('-->JSONStore init success')
}, (failure) => {
console.log('-->JSONStore init failed', failure)
})
}
load() {
let dataRequest = new
WLResourceRequest("/adapters/ServiceAdapter/getActivities",
WLResourceRequest.GET);
dataRequest.send().then(
(response) => {
this.data = response.responseJSON.rows;
this.activityService.put(this.data);
})
}
put(data){
console.log('--> JSONStore put function called');
let collectionName = 'activities';
let options = {
replaceCriteria: ['serialKey'],
addNew: true,
markDirty: false
};
WL.JSONStore.get(collectionName).change(data, options).then((success) => {
console.log('--> JSONStore put success')
}, (failure) => {
console.log('--> JSONStore put failed', failure)
})
}
Adapter Function:
function getActivities() {
var path = 'employees' + '/_all_docs?include_docs=true';
var input = {
method : 'get',
returnedContentType : 'json',
path : path,
};
var response = MFP.Server.invokeHttp(input);
if (!response.rows) {
response.isSuccessful = false;
return response;
} else {
var results = [];
for (var i=0; i < response.rows.length; i++) {
results.push(response.rows[i].doc);
}
return {'rows': results};
}
}
I have even tried by:
searchFields: {serialKey: 'string',serialId: 'string'}
replaceCriteria: ['serialKey','serialId']
But no luck.
NOTE: There is no error in the former one, whereas the later results in an error.
ERROR : PROVISION_TABLE_SEARCH_FIELDS_MISMATCH (I have already tried to destroy the collection and perform the change, as the link suggests.
I have followed the below link:
https://www.youtube.com/watch?v=Ep6w1zXoI-k
I am using the below versions:
mfpdev : 8.0.0-2017102406
Let me know if you need any more details.

JQuery DataTable data not available even data is received from server

I want to draw a table to show users data from my server.
First I am using Ajex to get the users data:
var usersList = {};
usersList.users = ["Afthieleanmah", "Hadulmahsanran","tabletest1"];
var dataSet1=[];
var i;
$.ajax({
url: '../users',
type: 'POST',
contentType: 'application/json',
cache: false,
data: JSON.stringify(usersList),
success:function(response, text){
if(response.users !== undefined){
dataSet1 = response.users;
}
}
});
I can successfully get the users data and save the data in dataSet1 as a JSON array contains Objects. Its format is like this:
[
{
username: "Tiger Nixon",
job_title: "System Architect",
city: "Edinburgh",
extn: "5421"
},
{
username: "Tiger Nixon2",
job_title: "System Architect",
city: "Edinburgh",
extn: "5421"
}
]
Then I create a table and pass in configuration:
// table confirgurations
var tableConfig={
pageLength: 5,
bLengthChange: false,
columns:[
{data: "username", title: "Name"},
{data: "job_title", title: "Position"},
{data: "city", title: "City"}
],
data:dataSet1
};
// create table
var userTable=$('#table-id').DataTable(tableConfig);
I am sure that I can get users data from API "/users" and save it into dataSet1. But everytime I load the page containing the table, the table always shows "No data available in table". I set a breakpoint on this line :
var tableConfig={
and let it continue to run. The weird things happen. The Table shows the data.............. No idea why
You should initialize your table after you receive response from the server in the success function. Also use destroy in case you're performin your Ajax request multiple times.
For example:
$.ajax({
// ... skipped ...
success:function(response, text){
if(response.users !== undefined){
dataSet1 = response.users;
}
// table confirgurations
var tableConfig={
// ... skippped ...
destroy: true
};
// ... skippped ...
var userTable=$('#table-id').DataTable(tableConfig);
}
});
However ideally you should let jQuery DataTables do the Ajax request using ajax option.

How do I operate the m.withAttr tutorials code?

A contrived example of bi-directional data binding
var user = {
model: function(name) {
this.name = m.prop(name);
},
controller: function() {
return {user: new user.model("John Doe")};
},
view: function(controller) {
m.render("body", [
m("input", {onchange: m.withAttr("value", controller.user.name), value: controller.user.name()})
]);
}
};
https://lhorie.github.io/mithril/mithril.withAttr.html
I tried the above code does not work nothing.
It was the first to try to append the following.
m.mount(document.body, user);
Uncaught SyntaxError: Unexpected token n
Then I tried to append the following.
var users = m.prop([]);
var error = m.prop("");
m.request({method: "GET", url: "/users/index.php"})
.then(users, error);
▼/users/index.php
<?php
echo '[{name: "John"}, {name: "Mary"}]';
Uncaught SyntaxError: Unexpected token n
How do I operate the m.withAttr tutorials code?
Try returning m('body', [...]) from your controller.
view: function (ctrl) {
return m("body", [
...
]);
}
render should not be used inside of Mithril components (render is only used to mount Mithril components on existing DOM nodes).
The example is difficult to operate because it's contrived, it's not meant to be working out-of-the-box. Here's a slightly modified, working version:
http://jsfiddle.net/ciscoheat/8dwenn02/2/
var user = {
model: function(name) {
this.name = m.prop(name);
},
controller: function() {
return {user: new user.model("John Doe")};
},
view: function(controller) {
return [
m("input", {
oninput: m.withAttr("value", controller.user.name),
value: controller.user.name()
}),
m("h1", controller.user.name())
];
}
};
m.mount(document.body, user);
Changes made:
m.mount injects html inside the element specified as first parameter, so rendering a body element in view will make a body inside a body.
Changed the input field event to oninput for instant feedback, and added a h1 to display the model, so you can see it changing when the input field changes.
Using m.request
Another example how to make an ajax request that displays the retrieved data, as per your modifications:
http://jsfiddle.net/ciscoheat/3senfh9c/
var userList = {
controller: function() {
var users = m.prop([]);
var error = m.prop("");
m.request({
method: "GET",
url: "http://jsonplaceholder.typicode.com/users",
}).then(users, error);
return { users: users, error: error };
},
view: function(controller) {
return [
controller.users().map(function(u) {
return m("div", u.name)
}),
controller.error() ? m(".error", {style: "color:red"}, "Error: " + controller.error()) : null
];
}
};
m.mount(document.body, userList);
The Unexpected token n error can happen if the requested url doesn't return valid JSON, so you need to fix the JSON data in /users/index.php to make it work with your own code. There are no quotes around the name field.

Not storing value on localstorage in sencha

I am trying to store data offline aspect, but here i want to store data on localstorage, did not store able to store this, all value getting null in localstorage.
This the based on ; http://www.robertkehoe.com/2012/11/sencha-touch-2-localstorage-example/
Models:
*Online.js*
Ext.define('default.model.Online', {
extend: 'Ext.data.Model',
config: {
fields: [
'cat_id',
'category_name'
]
}
});
Offline.js
Ext.define('default.model.Offline', {
extend: 'Ext.data.Model',
config: {
fields: [
'cat_id',
'category_name'
],
identifier:'uuid', // IMPORTANT, needed to avoid console warnings!
proxy: {
type: 'localstorage',
id : 'category'
}
}
});
Stores:
Ext.define('default.store.News', {
extend:'Ext.data.Store',
config:{
model:'default.model.Online',
proxy: {
timeout: 3000, // How long to wait before going into "Offline" mode, in milliseconds.
type: 'ajax',
url: 'http://alucio.com.np/trunk/dev/sillydic/admin/api/word/categories/SDSILLYTOKEN/650773253e7f157a93c53d47a866204dedc7c363?_dc=1376475408437&page=1&start=0&limit=25' , // Sample URL that simulates offline mode. Example.org does not allow cross-domain requests so this will always fail
reader: {
type: "json",
rootProperty: "data"
}
},
autoLoad: true
}
});
Controller:
Ext.define('default.controller.Core', {
extend : 'Ext.app.Controller',
config : {
refs : {
newsList : '#newsList'
}
},
init : function () {
var onlineStore = Ext.getStore('News'),
localStore = Ext.create('Ext.data.Store', {
model: "default.model.Offline"
}),
me = this;
localStore.load();
onlineStore.on('refresh', function (store,record) {
Ext.Msg.alert('Notice', 'You are in online mode', Ext.emptyFn);
// console.dir(record.data.name);
console.dir(record.get('category_name'));
console.log(record.items[0].raw.category_name);
console.log(record.get('category_name'));
// Get rid of old records, so store can be repopulated with latest details
localStore.getProxy().clear();
store.each(function(record) {
var rec = {
name : record.data.category_name+ ' (from localStorage)' // in a real app you would not update a real field like this!
};
localStore.add(rec);
localStore.sync();
});
});
onlineStore.getProxy().on('exception', function () {
me.getNewsList().setStore(localStore); //rebind the view to the local store
localStore.load(); // This causes the "loading" mask to disappear
Ext.Msg.alert('Notice', 'You are in offline mode', Ext.emptyFn); //alert the user that they are in offline mode
});
}
});
I think, I am not getting value from this record.data.category_nam . Here I am getting first value from this:record.items[0].raw.category_name. So how to store in localstorage.
and View file:
Ext.define('default.view.Main', {
extend : 'Ext.List',
config : {
id : 'newsList',
store : 'News',
disableSelection : false,
itemTpl : Ext.create('Ext.XTemplate',
'{category_name}'
),
items : {
docked : 'top',
xtype : 'titlebar',
title : 'News List'
}
}
});
In localstorage, following output:
category-5ea01a8d-ef1e-469e-8ec4-790ec7306aaf
{"cat_id":null,"category_name":null,"id":"5ea01a8d-ef1e-469e-8ec4-790ec7306aaf"}
category-f3e090dd-8f25-4b20-bb6e-b1a030e07900
{"cat_id":null,"category_name":null,"id":"f3e090dd-8f25-4b20-bb6e-b1a030e07900"}
category-5148e6eb-85ae-4acd-9dcd-517552cf5d97
{"cat_id":null,"category_name":null,"id":"5148e6eb-85ae-4acd-9dcd-517552cf5d97"}
category-ec23ff8b-1faa-4f62-9284-d1281707a9bc
{"cat_id":null,"category_name":null,"id":"ec23ff8b-1faa-4f62-9284-d1281707a9bc"}
category-6c1d
I have display in view but could not store in localstorage for offline propose.where i did wrong, i could not get it.
Record you created should match the SF.model.Offline model.
In your following code
var rec = {
// name is the field name of the `SF.model.Offline` model.
name : record.data.category_name+ ' (from localStorage)'
};
localStore.add(rec);
localStore.sync();
But you see there is no field called name in SF.model.Offline model.
This is how you should do
Models
Ext.define('SF.model.Online', {
extend : 'Ext.data.Model',
config: {
fields: ['cat_id','category_name'],
}
});
Ext.define('SF.model.Offline', {
extend : 'Ext.data.Model',
config: {
fields: ['cat_id','category_name'],
identifier:'uuid',
proxy: {
type: 'localstorage',
id : 'category'
}
}
});
Store
Ext.define('SF.store.Category', {
extend : 'Ext.data.Store',
config : {
model : 'SF.model.Online',
storeId : 'category',
proxy: {
timeout: 3000,
type: 'ajax',
url: 'same url' ,
reader: {
type: "json",
rootProperty: "data"
}
},
autoLoad : true
}
});
In Controller
var onlineStore = Ext.getStore('category'),
localStore = Ext.create('Ext.data.Store', {
model: "SF.model.Offline"
}),
me = this;
localStore.load();
onlineStore.on('refresh', function (store, records) {
localStore.getProxy().clear();
onlineStore.each(function(record) {
//You creating record here, The record fields should match SF.model.Offline model fields
var rec = {
cat_id : record.data.cat_id + ' (from localStorage)',
category_name : record.data.category_name + ' (from localStorage)'
};
localStore.add(rec);
localStore.sync();
});
});
onlineStore.getProxy().on('exception', function () {
me.getNewsList().setStore(localStore);
localStore.load();
Ext.Msg.alert('Notice', 'You are in offline mode', Ext.emptyFn);
});