HTTP Adapter Error "Runtime: Failed to parse JSON string" - ibm-mobilefirst

I am using IBM Worklight Studio, and trying to create HTTP Adapter which retrieve JSON object from external http server.
When I just access target http server with HTTP Get access(with browser, for example), I know their response is like following array style JSON format:
[
{ "xxx":"aaa", "yyy":"bbb", ... },
{ "xxx":"ccc", "yyy":"ddd", ... },
:
{ "xxx":"eee", "yyy":"fff", ... }
]
And I had created HTTP Adapter which would retrieve above information
var input = {
method : 'get',
returnedContentType : 'json',
path : path
};
return WL.Server.invokeHttp(input);
Now I tried to invoke this adapter with "Run As -> Invoke Worklight Procedure", then I got this error message:
{
"errors": [
"Runtime: Failed to parse JSON string\n\n[\n {\n
(raw JSON data) } ],
"info": [],
"isSuccessful": false,
"warnings": []
}
And in my log console, worklight says following error messages:
FWLSE0101E: Caused by: java.io.IOException: Expecting '{' on line 2, column 2 instead, obtained token: 'Token: ['
From above information, it seems that worklight would expect that returned JSON object need to start with "{", not "[".
Is this my guess right? Are there any workaround for this?
Thanks for advance.

Worklight knows how to handle JSON objects that start with [ (JSON arrays). In such case Worklight will return the response as:
{ "array" : [*the json array*]}
Looking at the code of the HTTP Adapter, I see that there is a bug with parsing JSON arrays that do not start with [.
I do not see a workaround for this problem, except changing the response returned from the http server.
I opened an internal bug about this, thank you for helping us find this bug.

You can change returnedContentType to "plain", this will make WL server return content as a big string and not attempt to parse it.
Then in your adapter you can use var obj = JSON.parse(response.text)

Related

Karate: JSON is converted to string ([object Object]) when matching

I'm trying to match the response of an API with a schema. I have the following setup.
Here is the feature file:
Feature: As a user, I would like to test APIs of member modules.
Background:
* def DIR_PATH = 'data/users/'
* def signup_request_helpers = read(<path_to_js_file>)
* def signup_response_helpers = read(<path_to_js_file>)
* def request_data = signup_request_data()
Scenario: Test signup of user
Given url my_url
And request request_data
When method POST
Then status 200
Then match response == signup_response_schema
Here is the JS file that holds the response schema
var signup_response_schema = {
"success": true,
"message": "Successfully signed up.",
"data": {
"user": user_schema,
"confirmation_url": "#string",
"token": "#string",
"role": "#array"
}
};
The problem is that karate seems to be converting the response schema into a string. This is the error message that I get:
actual: {<response>}, expected: [object Object]
Please note that I can match individual string fields fine. The problem only occurs when I try to match objects. Also, I have tried printing the schema and the variable seems to be holding the correct value which is the schema object.
I've tried the following:
Convert the schema into a string and then a JSON using the library's directives. This doesn't verify the schema
Convert directly to json which still renders the schema as [object Object]
NOTE: I'm running Karate on docker if that makes any difference. Following is the command that I use in my docker-compose file:
java -jar -Dkarate.config.dir=/app /app/karate-0.9.1.jar -T 5 path_to_file
JS in Karate is not that seamless. This will work:
var temp = {
"success": true,
"message": "Successfully signed up.",
"data": {
"user": user_schema,
"confirmation_url": "#string",
"token": "#string",
"role": "#array"
}
};
karate.set('signup_response_schema', temp);
Normally in Karate *.js files start with function and contain a single function block. And the result of reading (evaluating) that block is assigned to a Karate variable using def. But the recommended option for you is this, where you just have a JSON in the file, and the extension matters:
Then match response == read('signup_response_schema.json')
Note that read() will also evaluate embedded expressions, which can be useful. Although the JSON is not expected to be strictly well-formed, it is recommended.
The issue here wasn't of JS evaluation. The variable signup_response_schema holds the value that I assigned to it in the JS file.
The problem was with the actual matching of the schema because one of the keys was missing in the actual response. Karate usually throws specific error messages indicating which keys were missing but for some reason, this isn't the case here.

Handle unavailable server with vue-resource

Is there a way to handle errors with vue-resource when a HTTP response has not been received?
For example, when the backend server is unavailable (i.e. http://localhost:30000 doesn't exist) I receive the following error in Safari:
[Error] Failed to load resource: Could not connect to the server. (create, line 0)
However the vue-resource response object passed to the error callback is empty (doesn't give any indication about the failure to connect to the server):
{ "url": "http://localhost:30000", "ok": false, "status": 0, "statusText": "", "headers": { "map": { "": [ "" ] } }, "body": null }
What is the best way to handle this? Hardcoding for a status === 0 seems like it might be overly generic?

IBM Mobile First 7.1: multipart/related Content-Type and XSL transformation

I need to invoke from an HTTP adapter a SOAP service that has a multipart/related content type.
If I use this object as WL.Server.invokeHttp parameter
{
method : 'post',
returnedContentType : 'xml',
returnedContentEncoding : 'utf-8',
path : servicePath,
body : {
content : MY_REQUEST,
contentType : "text/xml; charset=utf-8"
},
transformation: {
type: 'xslFile',
xslFile: 'myXsl.xsl'
}
};
I got this error:
"Runtime: Failed to read the HTTP response to: /MyService
\njava.lang.IllegalArgumentException: Http content type 'multipart/related' not supported.
Supported types are: [json, css, csv, javascript, plain, xml, html]"
So I modified the parameter returnedContentType: 'plain' to obtain a result. Now the response looks like this:
{
"isSuccessful": true,
"errors": [],
"warnings": [],
"info": [],
"text": "--uuid:85c87f37-9436-41d1-94d4-0b944c3618b1\nContent-Type: application/xop+xml; charset=UTF-8; type=\"text/xml\";\nContent-Transfer-Encoding: binary\nContent-ID: <root.message#cxf.apache.org>\n\n
MY SOAP RESPONSE
\n--uuid:85c87f37-9436-41d1-94d4-0b944c3618b1--",
"responseHeaders": {
...
"Content-Type": "multipart/related; type=\"application/xop+xml\"; boundary=\"uuid:85c87f37-9436-41d1-94d4-0b944c3618b1\"; start=\"<root.message#cxf.apache.org>\"; start-info=\"text/xml\""
...
}
}
But the xsl transformation is not performed.
With some string manipulation on the text parameter I can obtain the SOAP response as a string but I didn't find a way(some API) to manually invoke the XSL transformation to obtain a json.
XSL transformation is done only on the server-side (there is no manual 'activation' for it). What you could do perhaps, if you still need to do XSL transformation, is run the XSL via JavaScript. See for example: how to run XSL file using JavaScript / HTML file

Cross-domain requests does not work using Sencha Touch 2

I have an application which displays some articles. The application works perfectly on Wamp in localhost. I've uploaded my database management in an other server. I already configured my ArticleStore.js in JSONP but when I run my application the following error appears in the console :
Resource interpreted as Script but transferred with MIME type text/html: "http://[ip_address]:[port]/totos?_dc=1372152920457&keyword=&page=1&start=0&limit=25&callback=Ext.data.JsonP.callback1"
and :
Uncaught SyntaxError: Unexpected token : totos:1
When I clic on the url above I'm redirected to the view which display the following content :
{"articles_list":[{"id":"28","title":"Prixtel dope son service client avec le forfait Sumo"}],"total":1}
For sake of simplicity, I tested to display just the title of one article. Here's the JSON response for the line 1 when I clic on 'totos:1':
{"articles_list":[{"id":"28","title":"Prixtel dope son service client avec le forfait Sumo"}],"total":1}
Here's my ArticleStore.js content :
Ext.define("MyApp.store.ArticleListStore",
{
extend: "Ext.data.Store",
requires: ["MyApp.model.ArticleModel","Ext.data.proxy.JsonP"],
config: {
model: "MyApp.model.ArticleModel",
proxy: {
type: 'jsonp',
model: "MyApp.model.ArticleModel",
url: "http://62.23.96.124:81/totos",
},
reader: {
type: "json",
rootProperty: "articles_list",
totalProperty: "total"
},
},
autoLoad: true
}
});
When I was launched my resquest in localhost directly on Wamp server my JSON responses had the same syntax (The JSON tree architecture is the same). Here's an example :
{"articles_list":[{"id":"384","title":"Skype est disponible sur Windows Phone"}],"total":1}
I cannot see any difference between the two responses. However, I have an 'Unexpected token' error!. As you can see the two nodes 'articles_list' and 'total' have the same place in the JSON tree for the two examples. I don't understand why there is an syntax error. I'm really lost. Does anyone can help me, please ?
Thanks a lot in advance for your help.
Your server is not formatting the response correctly for JSON-P. JSON-P essentially needs your response to be embedded within a function, which is specified by the callbackKey property of your proxy:
proxy: {
type: 'jsonp',
url : "http://62.23.96.124:81/totos",
callbackKey: 'myCallbackKey'
}
Then, on your server, you need to use that parameter to wrap your response:
myCallbackKey({
"articles_list": [
{
"id":"28",
"title":"Prixtel dope son service client avec le forfait Sumo"
}
],
"total":1
})
You can learn more about this from the docs here: http://docs.sencha.com/touch/2.2.1/#!/api/Ext.data.proxy.JsonP.
You also will want to know a little more about the purpose of JSON-P, and how it works. Find out more here: What is JSONP all about?

worklight adapter

I am getting a problem in worklight adapter , In the following http adapter method
,it is showing The mandatory parameter 'action' is missing, returning statusCode as
500 and statusReason as "Internal Server Error". I had given all the user credentials
correctly in adapter xml file, but I don't know why I'm getting this error.
Code:
function actionOnProcessInstance()
{
var param = "/rest/bpm/bfm/v1/process/_PI:9003013d.4387342e.1efe573f.7c20307?action=resume";
var input =
{
method : 'put',
returnedContentType : 'json',
path : param,
};
var response = WL.Server.invokeHttp(input);
return response;
}
In 5.0.5.x, invokeHttp will take any params provided on the path for put and post and place them inside the http body instead of having them remain on the path as query params (as the developer probably intended). This behavior will be updated in an upcoming version but for now there's no way to force these to stay as query params.