Ext Data Session and bad server response ("[W] Ignoring server record: ...") - session

Our application handles and manages records changes on the client side. We use ExtJS5 Data Session mechanism.
A session tracks records that need to be updated, created or destroyed
on the server. It can also order these operations to ensure that newly
created records properly reference other newly created records by
their new, server-assigned id.
Let me introduce short use case.
User opens and fills a form. Behind the scene fields are binded to entity object which is tracked by session. When user clicks Submit then session is synchronized, i.e. Ext sends requests to the server and parse response. Here I've encountered a problem.
Server returns following object but Ext does not recognize it:
[{"success": false, errorMessage: "error"}]
Ext prints warning:
[W] Ignoring server record: {"success":false}
or
[W] Ignoring server record: {"success":true}
My question is how should look server response in order to indicate that record is not accepted/saved by backend?
The source code where above warning is printed: http://docs-origin.sencha.com/extjs/5.0/apidocs/source/Operation.html (in function doProcess)
Below I put snippet how I'm starting a batch operation (sync session):
var session = this.getViewModel().getSession(),
saveBatch = session.getSaveBatch();
saveBatch.on('complete', function (batch, operation, eOpts) {
// whole batch processing has been completed
/*...*/
});
saveBatch.on('exception', function (batch, operation, eOpts) {
// exception has been occurred (possible for each operation) (such as HTTP 500)
/*...*/
});
saveBatch.on('operationcomplete', function (batch, operation, eOpts) {
// single operation has been completed
// now, every operation is marked as successful
/*...*/
});
saveBatch.start();
update 26.09.2014
Sencha developer has suggested including an id of object in the response. so I've modified server response to:
[{"id": 10, "success": false}]
but this does not solve the problem.

I spend some time on debugging Ext.data.operation.Operation.doProcess method and I analyzed a sample code from sencha support. Ultimately I've found the solution.
There is my proxy config:
proxy: {
type: 'rest',
// ...
reader: {
type: 'json',
rootProperty: 'data',
totalProperty: 'totalCount',
successProperty: 'success',
messageProperty: 'errorMessage'
}
}
Server response when some error occured:
{
"success": false,
"errorMessage": "<error message>"
}
Server response when data was successfully saved:
The minimal form for delete or update record without changing data:
{
"success": true,
}
The extended form for creating or updating record with changing record data:
{
"success": true,
"data": [{
clientId: 5, // clientIdProperty
id: 5,
// [optional] fields to change, e.g.:
name: 'new name'
}]
}
I modified a demo which I have from sencha support:
https://fiddle.sencha.com/#fiddle/bem
in proxy config use data2.json for error and data3.json for success response.

Related

TransactionSync with Plaid Link

I'm trying to render all the transactions for a given item after the completion of the Plaid Link process. I call my transaction sync endpoint in my onSuccess method after the exchange token process. However, the first call to the transaction sync endpoint never renders anything, but when I add another item through Link, the intial item's transactions renders and the current one doesn't. I'm wondering why I need to call the sync endpoint twice to actually sync it into my db. The first call I make returns this response:
{'added': [],
'has_more': False,
'modified': [],
'next_cursor': '',
'removed': [],
'request_id': 'qmJn54LkWHqo4kh'}
I'm assuming that the item isn't ready to sync transaction yet because the cursor is at its initial state, which is why the next time I link an item it syncs. If that is the case where should I call the sync enpoint, currently calling in the onSuccess method(also tried calling the endpoint of the "HANDOFF" event but same result). How would I know when the item's transactions are ready to sync.
This is my onSuccess method, I'm calling the sync endpoint after token exchange
const onSuccess = useCallback<PlaidLinkOnSuccess>((publicToken, metadata) => {
fetch('/item/public_token/exchange',{
method: 'POST',
headers:{
'Content-Type': 'application/json',
},
body: JSON.stringify({public_token: publicToken, id:uid, metadata:metadata})
})
.then((r) =>{
fetch('/transactions/sync', {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({uid: uid})
})
})
}, []);
This is method the sync endpoint hits
#app.route('/transactions/sync', methods=['POST'])
def transactions_sync():
id = request.json["uid"]
items = collection.find_one({"_id": ObjectId(id)},{"items":1})
print(items)
for item in items["items"]:
item_id = item["item_id"]
access_token=item["access_token"]
cursor = item['cursor']
added = []
modified = []
removed = []
has_more = True
while has_more:
transaction_request = TransactionsSyncRequest(
access_token=access_token,
cursor=cursor
)
print(transaction_request)
response = client.transactions_sync(transaction_request)
print(response)
added.extend(response["added"])
modified.extend(response["modified"])
removed.extend(response["removed"])
has_more = response["has_more"]
cursor = response["next_cursor"]
for add in added:
res = collection.update_one({"_id": ObjectId(id)},{"$push":{
"transactions":{
"account_id": add["account_id"],
"transaction_id":add["transaction_id"],
"amount":add["amount"],
"name": add["name"],
#"date": add["date"],
"category":add["category"]
}
}} )
print(cursor)
collection.update_one({
"_id":ObjectId(id),
"items.item_id": item_id
},{"$set":{
"items.$.cursor": cursor
}})
return "Success",200
I tried syncing the item's transactions in the onSuccess event for Plaid Link but it didn't sync into my database until I added another item through Link (essentially it took 2 calls to the endpoint to sync). I'm expecting to sync the transactions of the newly added item to my database so I can render on the frontend, with just one call the to sync enpoint
This sounds like a timing issue. From the /transactions/sync API reference:
"Note that for newly created Items, data may not be immediately available to /transactions/sync. Plaid begins preparing transactions data when the Item is created, but the process can take anywhere from a few seconds to several minutes to complete, depending on the number of transactions available."
If you call /transactions/sync immediately after the token exchange, it won't return any transactions, because they aren't available yet. By the time the new Item has been added, enough time has passed that the transactions have been loaded on the original Item.
After calling /transactions/sync for the first time on an Item, you will register the Item for the SYNC_UPDATES_AVAILABLE webhook, which you can then use to see when to call /transactions/sync. For more info, see the documentation for that webhook.

Fineuploader possible solution to force header return true if default server will not return following JSON Data

Not sure if it's possible to force fineuploader to fire true success upload in anyway. im facing the issue of submitting form to a url "http://119.29.222.368:8991/upload"(sample ip due to P&C) where it will return only Status : "OK" without Success : true.
Following is my code, pretty sure that it successfully submitted, but my UI will get error due to the API is not returning the value success.
var uploader = new qq.FineUploader({
element: document.getElementById("uploader"),
cors: {
allowXdr: 'true',
expected:'true'
},
request: {
method:'POST',
// endpoint: '/upload',
endpoint: 'http://119.29.222.368:8991/upload',
forceMultipart:'true',
inputName:'filename',
params: {
'token': <%- JSON.stringify(token) %>,
'path':"/images/feed/"
}
}
})
This was originally requested in github.com/FineUploader/fine-uploader/issues/1325. Follow the linked pull request at the end of that issue for updates. – Ray Nicholus 20 hours ago

fineUploader Failed in the Request To endpoint and the cause in onError Callback is UnKnown Reason

kindly i have to pages using fineUploader ,
the first page is working correctly but the second isn't : the response in debugging browser console is:
My Html Body will be existing here.
Simple upload request failed for 0
[Fine Uploader 5.11.8] Error when attempting to parse xhr response
text (Unexpected token < in JSON at position 0)
for the point one :(the request didn't reach the endpoint because i made a tester in the endpoint page if any script accessed it)
so the request in the first page is working and the same request with the same path in endpoint property isn't working in the second
i read many articles with the same error but all of them were not identifying correct endpoint path , which i did correctly and tested in the first Page.
var uploader = new qq.FineUploader({
debug: true,
element: document.getElementById('my-uploader'),
request: {
endpoint: "http://localhost/fineuploader/endpoint.php",
// endpoint: "http://localhost/fineuploader/endpoint.php",//commented to prove that i used //both of the relative and absolute paths
},
chunking: {
enabled: true,
concurrent: {
enabled: true
},
success: {
endpoint: "http://localhost/fineuploader/endpoint.php?done",
}
},
deleteFile: {
enabled: true,
endpoint: "http://localhost/fineuploader/endpoint.php"
},
retry: {
enableAuto: true,
showButton: true
},
form:{element:"FormId", },
callbacks: {
onError: function(id, name, errorReason, xhrOrXdr) {
alert(qq.format("Error on file number {} - {}. Reason: {}", id, name, errorReason));
},
});
The Answer of Mr Ray Nicholus Here was useful but i want to provide the solution in my case and my mistake, my problem was that in the first page i didn't provide action attribute in form tag and in the second i did , so when i provided in the second page the action of the form a different value than what is specified in
<form id="test" action="form.php">
request: {
endpoint: "http://localhost/fineuploader/endpoint.php",},
the requests were going to the action attribute value path(form.php) not for the above request value (endpoint.php).
It's really very simple, and there is no other answer to this question: either your endpoint is incorrect (and of course the response will be invalid too) or your endpoint is correct but your endpoint is not returning valid JSON. You'll need to look at the response closely to determine the issue.
In your case, your endpoint is returning HTML, not JSON. You'll have to fix this on your server.

Access to HTTP response in Ext.data.Model.save() callbacks using REST proxy

I successfully implemented client editors and a server side API.
Now I'm adding more validation at the server side, and besides returning the proper HTTP code (200 for OK, 4xx for other uses, 500 for errors, etc.) I want to return a list of validations that failed after the submission generated by Model.save().
I run it this way:
myModel.save({
success: function (a, operation, c) {...},
failure: function (a, operation, c) {...}
});
But if there was a failure, the operation object only have the response status and its statusText, all through
operation.error.status // i.e. 409
operation.error.statusText // "Conflict"
But server side a detail of the failing validations (mostly domain level ones) are being added to the response.
Is there a way I can get what the server sent as the body of the HTTP response to the PUT/POST submission?
Do I have to return it using a particular JSON structure?
EDIT:
I'm now returning this as the body of the HTTP Response (with code 4xx):
{
data: {/* the record serialized */},
success: false, // or true if everything went ok
message: "This failed because X and Y."
}
Thanks in advance.
For some reason Ext is not attaching the response content to the error object, but it triggers an exception event if there is a failure.
So what we did was to handle the "exception" event of the model's proxy, and then we will have access to the XHR response, being able to do whatever we want with it.
myModel.getProxy().on('exception', this.onProxyException, this);
The handler is as follows:
onProxyException : function (proxy, response, operation) {
var errors;
errors = Ext.JSON.decode(response.responseText).message;
/* Whatever is needed with the errors */
}
In this example we asume the errors come in JSON format, they could be a simple text string, which wouldn't require the use of decode().
According to this blog:
http://code.tonytuan.org/2013/07/extjs-get-server-response-in-modelsave.html
You can write code like this:
model.save({
success: function (record, operation) {
// json response from server
console.log(operation.response);
},
failure: function (record, operation) {
// undefined
console.log(operation.response);
// json response from server
console.log(operation.request.scope.reader.jsonData);
}
});
in reader block add: messageProperty: 'message'
from server return: success:false, message: 'error test'
from failure get error:
failure: function (records, operation) {
Ext.Msg.alert('error', operation.error);
}

In ExtJS, How can I list multiple returns from JSON data in a field set?

Ok, I am semi-new to ExtJS, and I am building a program that has "inputs" that are listed in a grid, and in my DB these inputs can be linked to "symptoms".
I am trying to create a function that will take in the id of the input and grab all of the symptoms from the database that are linked to that symptom, and list them in a field set.
It works fine when I click on an input that is only linked to one symptom, but if the input is linked to more than one symptom, then the error says.. "invalid property id"
This is what I have for my function.
function listSymptoms(inputID){
Ext.Ajax.request({
url: "../../inc/project4.php?list=symptoms",
reader: new (Ext.data.JsonReader)({
root: "symptoms",
inputid: "id"
}),
params: {
inputid: inputID
},
method: "POST",
success: function (f, a){
var jsonData = Ext.util.JSON.decode(f.responseText);
symptomsFieldSet.body.update(jsonData.data.name);
},
failure: function (f,a){
Ext.Msg.alert('There was a problem opening your message.');
}
});
}
I have the inputID for the function being passed in when the user clicks on one of the inputs that are held inside the grid.
I believe that my problem has something to do with this line..
symptomsFieldSet.body.update(jsonData.data.name);
I am just stumped on how to handle this. Do I need to create a data store like I have for grids? Or is there an easier way to do this?
ANY help is appreciated! thanks in advance.
I think you need to rethink the structure of your JSON response object. You can send this in your JSON response to your request. If you are using Ext.util.Ajax calls instad of a form, you'll need to decode this JSON response string using the util method Ext.util.JSON.decode(). Check out the API Documentation
{
success: true,
msg: {text: 'this can be used for error message handling' },
data : [
{id:1,
chiefComplaint: 'head hurts',
symptoms: [
{symptomID: '740.1', text: 'Headache'},
{symptomID: '12352135'. text: 'and so on'}
}
]
]
}

Resources