MobileFirst 6.3 调用后端服务创建适配器过程
MobileFirst 6.3 invoking backend service created adapter procedure
我很难弄明白如何调用 MobileFirst 使用“发现后端服务”功能为我创建的适配器。
我创建了我的适配器,但我没有使用以下代码尝试调用它:
function callService(){
alert("Calling into Backend");
var options = {
onSuccess : loadSuccess,
onFailure : loadFailure,
invocationContext: {}
};
var params = {"itemRequiredReference":10};
var invocationData = {
adapter : 'SoapAdapter1',
procedure : 'inquireSingleService_inquireSingle',
parameters : [params]
};
WL.Client.invokeProcedure(invocationData, options);
}
但这似乎不起作用。我收到错误:
{"status":200,"invocationContext":{},"invocationResult":{"statusCode":500,"errors":[],"isSuccessful":true,"Envelope":{"SOAP-ENV":"http://schemas.xmlsoap.org/soap/envelope/","Body":{"Fault":{"":"","detail":{"CICSFault":{"CDATA":"DFHPI1010 02/02/2015 22:11:37 GENAPPA1 CPIH 00518 XML generation failed. A conversion error (INVALID_ZONED_DEC) occurred when converting field itemReferenceNumber for WEBSERVICE inquireSingleWrapper.","xmlns":"http://www.ibm.com/software/htp/cics/WSFault"}},"faultcode":"SOAP-ENV:Server","faultstring":"Conversion to SOAP failed"}},"soap":"http://schemas.xmlsoap.org/soap/envelope/"},"statusReason":"Internal Server Error","responseHeaders":{"Date":"Mon, 02 Feb 2015 22:11:37 GMT","Content-Length":"000000000000608","Content-Type":"text/xml; charset=UTF-8","Connection":"Keep-Alive","Server":"IBM_CICS_Transaction_Server/5.2.0(zOS)"},"warnings":[],"responseTime":578,"totalTime":581,"info":[]}}
生成的适配器代码如下所示:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Generated code - Do not edit //
// //
// This is a SOAP adapter that was auto-generated by Worklight for invocation of specific SOAP-based services. //
// The adapter may invoke more than one service as long as they are all from the same enpdpoint (server host). //
// Each adapter procedure matches a single operation for the same endpoint server and accepts: //
// params - Serialized JSON representation of the XML-based SOAP body to be sent to the service //
// headers - Custom HTTP headers to be specified when invoking the remote service. It is a JSON object with //
// the headers names and values. E.g. { 'name1' : 'value1', 'name2' : 'value2' } //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function inquireSingleService_inquireSingle(params, headers){
var soapEnvNS = '';
// The value of 'soapEnvNS' was set based on the version of the SOAP to be used (i.e. 1.1 or 1.2).
soapEnvNS = 'http://schemas.xmlsoap.org/soap/envelope/';
// The following mappings object was autogenerated from the XML schema of the input message to the service.
// It is being used to support a params JSON when invoking this procedure that don't specify the namespace
// prefix nor specifying whether a property is attribute or not.
//
// The 'roots' object has the list of message parts within the invocation SOAP message. Each entry has a
// mapping between the root element name and its namespace prefix and type.
// Each root object may define 'nsPrefix' and 'type'. Both are optional - If there is no need for a NS prefix
// then the 'nsPrefix' should not be specified. If the element is a simple type then the 'type' should not be
// specified.
//
// The 'types' object has a list of types each defining the children of the type and the definition of each
// child. If the child is a complext type, the 'type' property has a reference to the child type definition.
// Each child object may define:
// 'nsPrefix' (optional) - Holds the namespace prefix to be attached to the element. If there is no need for
// a NS prefix then the 'nsPrefix' should not be specified.
// 'type' (optional) - If the element is a simple type then the 'type' should not be specified. If it is an
// attribute then 'type' should have the value of '@'. Otherwise the value of 'type' is a reference to the
// type definition within the 'types' object.
var mappings = {
roots: {
'inquireSingleRequest': { nsPrefix: 'reqns', type: 'reqns:inquireSingleRequest' }
},
types: {
'reqns:inquireSingleRequest': {
children: [
{'itemRequiredReference': { nsPrefix: 'reqns' }}
]
}
}
};
var namespaces = 'xmlns:resns="http://www.exampleApp.inquireSingleResponse.com" xmlns:reqns="http://www.exampleApp.inquireSingleRequest.com" xmlns:tns="http://www.exampleApp.inquireSingleResponse.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ';
var request = buildBody(params, namespaces, mappings, soapEnvNS);
var soapAction = '';
return invokeWebService(request, headers, soapAction);
}
function buildBody(params, namespaces, mappings, soapEnvNS){
var body =
'<soap:Envelope xmlns:soap="' + soapEnvNS + '">\n' +
'<soap:Body>\n';
var fixedParams = {};
for (var paramName in params) {
if (mappings['roots'][paramName]) { //There is mapping for this param
var root = mappings['roots'][paramName];
var name = paramName;
if (root['nsPrefix'])
name = root['nsPrefix'] + ':' + paramName;
fixedParams[name] = handleMappings(params[paramName], root['type'], mappings['types']);
}
else {
fixedParams[paramName] = params[paramName];
}
}
body = jsonToXml(fixedParams, body, namespaces);
body +=
'</soap:Body>\n' +
'</soap:Envelope>\n';
return body;
}
function handleMappings(jsonObj, type, mappings) {
var fixedObj = {};
var typeMap = mappings[type]['children']; //Get the object that defines the mappings for the specific type
// loop through the types and see if there is an input param defined
for(var i = 0; i < typeMap.length; i++) {
var childType = typeMap[i];
for(var key in childType) {
if(jsonObj[key] !== null) { // input param exists
var childName = key;
if (childType[key]['nsPrefix'])
childName = childType[key]['nsPrefix'] + ':' + key;
if (!childType[key]['type']) //Simple type element
fixedObj[childName] = jsonObj[key];
else if (typeof jsonObj[key] === 'object' && jsonObj[key].length != undefined) { //Array of complex type elements
fixedObj[childName] = [];
for (var i=0; i<jsonObj[key].length; i++)
fixedObj[childName][i] = handleMappings(jsonObj[key][i], childType[key]['type'], mappings);
}
else if (typeof jsonObj[key] === 'object') //Complex type element
fixedObj[childName] = handleMappings(jsonObj[key], childType[key]['type'], mappings);
else if (childType[key]['type'] == '@') //Attribute
fixedObj['@' + childName] = jsonObj[key];
}
}
}
return fixedObj;
}
function getAttributes(jsonObj) {
var attrStr = '';
for(var attr in jsonObj) {
if (attr.charAt(0) == '@') {
var val = jsonObj[attr];
attrStr += ' ' + attr.substring(1);
attrStr += '="' + xmlEscape(val) + '"';
}
}
return attrStr;
}
function jsonToXml(jsonObj, xmlStr, namespaces) {
var toAppend = '';
for(var attr in jsonObj) {
if (attr.charAt(0) != '@') {
var val = jsonObj[attr];
if (typeof val === 'object' && val.length != undefined) {
for(var i=0; i<val.length; i++) {
toAppend += "<" + attr + getAttributes(val[i]);
if (namespaces != null)
toAppend += ' ' + namespaces;
toAppend += ">\n";
toAppend = jsonToXml(val[i], toAppend);
toAppend += "</" + attr + ">\n";
}
}
else {
toAppend += "<" + attr;
if (typeof val === 'object') {
toAppend += getAttributes(val);
if (namespaces != null)
toAppend += ' ' + namespaces;
toAppend += ">\n";
toAppend = jsonToXml(val, toAppend);
}
else {
toAppend += ">" + xmlEscape(val);
}
toAppend += "</" + attr + ">\n";
}
}
}
return xmlStr += toAppend;
}
function invokeWebService(body, headers, soapAction){
var input = {
method : 'post',
returnedContentType : 'xml',
path : '/exampleApp/inquireSingleWrapper',
body: {
content : body.toString(),
contentType : 'text/xml; charset=utf-8'
}
};
WL.Logger.error("ANDY:"+body.toString());
//Adding custom HTTP headers if they were provided as parameter to the procedure call
//Always add header for SOAP action
headers = headers || {};
if (soapAction != 'null')
headers.SOAPAction = soapAction;
input['headers'] = headers;
return WL.Server.invokeHttp(input);
}
function xmlEscape(obj) {
if(typeof obj !== 'string') {
return obj;
}
return obj.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>');
}
我有点迷路了——invocationData 对象上的 parameters 参数需要修复——但它真的很不清楚什么映射作为 json 对象我打算作为参数传递。 谁能告诉我需要传递什么参数才能将 itemRequiredReference 设置为数字 30。
如果您需要我用来生成服务的 WSDL,这就是我使用的:http://we.tl/fHgRos3f4e
这是从 soapUI @idan 调用的服务:
好吧,我终于在这里找到了一个有用的文档页面:http://www-01.ibm.com/support/knowledgecenter/SSHS8R_6.3.0/com.ibm.worklight.dev.doc/dev/c_invocation_generated_soap_adapter.html
解决方案是将参数变量设置为:
var params = {"inquireSingleRequest": {"itemRequiredReference": "10"}}
var invocationData = {
adapter : 'SoapAdapter1',
procedure : 'inquireSingleService_inquireSingle',
parameters : [params]
};
这让它可以完美地工作。
我很难弄明白如何调用 MobileFirst 使用“发现后端服务”功能为我创建的适配器。
我创建了我的适配器,但我没有使用以下代码尝试调用它:
function callService(){
alert("Calling into Backend");
var options = {
onSuccess : loadSuccess,
onFailure : loadFailure,
invocationContext: {}
};
var params = {"itemRequiredReference":10};
var invocationData = {
adapter : 'SoapAdapter1',
procedure : 'inquireSingleService_inquireSingle',
parameters : [params]
};
WL.Client.invokeProcedure(invocationData, options);
}
但这似乎不起作用。我收到错误:
{"status":200,"invocationContext":{},"invocationResult":{"statusCode":500,"errors":[],"isSuccessful":true,"Envelope":{"SOAP-ENV":"http://schemas.xmlsoap.org/soap/envelope/","Body":{"Fault":{"":"","detail":{"CICSFault":{"CDATA":"DFHPI1010 02/02/2015 22:11:37 GENAPPA1 CPIH 00518 XML generation failed. A conversion error (INVALID_ZONED_DEC) occurred when converting field itemReferenceNumber for WEBSERVICE inquireSingleWrapper.","xmlns":"http://www.ibm.com/software/htp/cics/WSFault"}},"faultcode":"SOAP-ENV:Server","faultstring":"Conversion to SOAP failed"}},"soap":"http://schemas.xmlsoap.org/soap/envelope/"},"statusReason":"Internal Server Error","responseHeaders":{"Date":"Mon, 02 Feb 2015 22:11:37 GMT","Content-Length":"000000000000608","Content-Type":"text/xml; charset=UTF-8","Connection":"Keep-Alive","Server":"IBM_CICS_Transaction_Server/5.2.0(zOS)"},"warnings":[],"responseTime":578,"totalTime":581,"info":[]}}
生成的适配器代码如下所示:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Generated code - Do not edit //
// //
// This is a SOAP adapter that was auto-generated by Worklight for invocation of specific SOAP-based services. //
// The adapter may invoke more than one service as long as they are all from the same enpdpoint (server host). //
// Each adapter procedure matches a single operation for the same endpoint server and accepts: //
// params - Serialized JSON representation of the XML-based SOAP body to be sent to the service //
// headers - Custom HTTP headers to be specified when invoking the remote service. It is a JSON object with //
// the headers names and values. E.g. { 'name1' : 'value1', 'name2' : 'value2' } //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function inquireSingleService_inquireSingle(params, headers){
var soapEnvNS = '';
// The value of 'soapEnvNS' was set based on the version of the SOAP to be used (i.e. 1.1 or 1.2).
soapEnvNS = 'http://schemas.xmlsoap.org/soap/envelope/';
// The following mappings object was autogenerated from the XML schema of the input message to the service.
// It is being used to support a params JSON when invoking this procedure that don't specify the namespace
// prefix nor specifying whether a property is attribute or not.
//
// The 'roots' object has the list of message parts within the invocation SOAP message. Each entry has a
// mapping between the root element name and its namespace prefix and type.
// Each root object may define 'nsPrefix' and 'type'. Both are optional - If there is no need for a NS prefix
// then the 'nsPrefix' should not be specified. If the element is a simple type then the 'type' should not be
// specified.
//
// The 'types' object has a list of types each defining the children of the type and the definition of each
// child. If the child is a complext type, the 'type' property has a reference to the child type definition.
// Each child object may define:
// 'nsPrefix' (optional) - Holds the namespace prefix to be attached to the element. If there is no need for
// a NS prefix then the 'nsPrefix' should not be specified.
// 'type' (optional) - If the element is a simple type then the 'type' should not be specified. If it is an
// attribute then 'type' should have the value of '@'. Otherwise the value of 'type' is a reference to the
// type definition within the 'types' object.
var mappings = {
roots: {
'inquireSingleRequest': { nsPrefix: 'reqns', type: 'reqns:inquireSingleRequest' }
},
types: {
'reqns:inquireSingleRequest': {
children: [
{'itemRequiredReference': { nsPrefix: 'reqns' }}
]
}
}
};
var namespaces = 'xmlns:resns="http://www.exampleApp.inquireSingleResponse.com" xmlns:reqns="http://www.exampleApp.inquireSingleRequest.com" xmlns:tns="http://www.exampleApp.inquireSingleResponse.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ';
var request = buildBody(params, namespaces, mappings, soapEnvNS);
var soapAction = '';
return invokeWebService(request, headers, soapAction);
}
function buildBody(params, namespaces, mappings, soapEnvNS){
var body =
'<soap:Envelope xmlns:soap="' + soapEnvNS + '">\n' +
'<soap:Body>\n';
var fixedParams = {};
for (var paramName in params) {
if (mappings['roots'][paramName]) { //There is mapping for this param
var root = mappings['roots'][paramName];
var name = paramName;
if (root['nsPrefix'])
name = root['nsPrefix'] + ':' + paramName;
fixedParams[name] = handleMappings(params[paramName], root['type'], mappings['types']);
}
else {
fixedParams[paramName] = params[paramName];
}
}
body = jsonToXml(fixedParams, body, namespaces);
body +=
'</soap:Body>\n' +
'</soap:Envelope>\n';
return body;
}
function handleMappings(jsonObj, type, mappings) {
var fixedObj = {};
var typeMap = mappings[type]['children']; //Get the object that defines the mappings for the specific type
// loop through the types and see if there is an input param defined
for(var i = 0; i < typeMap.length; i++) {
var childType = typeMap[i];
for(var key in childType) {
if(jsonObj[key] !== null) { // input param exists
var childName = key;
if (childType[key]['nsPrefix'])
childName = childType[key]['nsPrefix'] + ':' + key;
if (!childType[key]['type']) //Simple type element
fixedObj[childName] = jsonObj[key];
else if (typeof jsonObj[key] === 'object' && jsonObj[key].length != undefined) { //Array of complex type elements
fixedObj[childName] = [];
for (var i=0; i<jsonObj[key].length; i++)
fixedObj[childName][i] = handleMappings(jsonObj[key][i], childType[key]['type'], mappings);
}
else if (typeof jsonObj[key] === 'object') //Complex type element
fixedObj[childName] = handleMappings(jsonObj[key], childType[key]['type'], mappings);
else if (childType[key]['type'] == '@') //Attribute
fixedObj['@' + childName] = jsonObj[key];
}
}
}
return fixedObj;
}
function getAttributes(jsonObj) {
var attrStr = '';
for(var attr in jsonObj) {
if (attr.charAt(0) == '@') {
var val = jsonObj[attr];
attrStr += ' ' + attr.substring(1);
attrStr += '="' + xmlEscape(val) + '"';
}
}
return attrStr;
}
function jsonToXml(jsonObj, xmlStr, namespaces) {
var toAppend = '';
for(var attr in jsonObj) {
if (attr.charAt(0) != '@') {
var val = jsonObj[attr];
if (typeof val === 'object' && val.length != undefined) {
for(var i=0; i<val.length; i++) {
toAppend += "<" + attr + getAttributes(val[i]);
if (namespaces != null)
toAppend += ' ' + namespaces;
toAppend += ">\n";
toAppend = jsonToXml(val[i], toAppend);
toAppend += "</" + attr + ">\n";
}
}
else {
toAppend += "<" + attr;
if (typeof val === 'object') {
toAppend += getAttributes(val);
if (namespaces != null)
toAppend += ' ' + namespaces;
toAppend += ">\n";
toAppend = jsonToXml(val, toAppend);
}
else {
toAppend += ">" + xmlEscape(val);
}
toAppend += "</" + attr + ">\n";
}
}
}
return xmlStr += toAppend;
}
function invokeWebService(body, headers, soapAction){
var input = {
method : 'post',
returnedContentType : 'xml',
path : '/exampleApp/inquireSingleWrapper',
body: {
content : body.toString(),
contentType : 'text/xml; charset=utf-8'
}
};
WL.Logger.error("ANDY:"+body.toString());
//Adding custom HTTP headers if they were provided as parameter to the procedure call
//Always add header for SOAP action
headers = headers || {};
if (soapAction != 'null')
headers.SOAPAction = soapAction;
input['headers'] = headers;
return WL.Server.invokeHttp(input);
}
function xmlEscape(obj) {
if(typeof obj !== 'string') {
return obj;
}
return obj.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>');
}
我有点迷路了——invocationData 对象上的 parameters 参数需要修复——但它真的很不清楚什么映射作为 json 对象我打算作为参数传递。 谁能告诉我需要传递什么参数才能将 itemRequiredReference 设置为数字 30。
如果您需要我用来生成服务的 WSDL,这就是我使用的:http://we.tl/fHgRos3f4e
这是从 soapUI @idan 调用的服务:
好吧,我终于在这里找到了一个有用的文档页面:http://www-01.ibm.com/support/knowledgecenter/SSHS8R_6.3.0/com.ibm.worklight.dev.doc/dev/c_invocation_generated_soap_adapter.html
解决方案是将参数变量设置为:
var params = {"inquireSingleRequest": {"itemRequiredReference": "10"}}
var invocationData = {
adapter : 'SoapAdapter1',
procedure : 'inquireSingleService_inquireSingle',
parameters : [params]
};
这让它可以完美地工作。