JavaScript Data Binding (inputTypes/outputType annotation)
Table of Contents
countWords.inputTypes = {"content" : "string" , "ignoreHyphens" : "boolean"};
countWords.outputType = "xs:integer";
function countWords(content, ignoreHyphens) {
.....
}
Intepretation and treatment of JavaScript types
Although type information can be provided as JavaScript types, the WSO2 Mashup Server eventually converts them to XML schema data types. This is done to ensure that the description (WSDL 1.1, WSDL2) we provide for your service will have rich type information. If the type is specified without an "xs:" prefix they are assumed to be JavaScript (plus E4X) types and is mapped into the XML Schema type system as follows:| Declared JavaScript (plus E4X) Type | Treatment |
| String | string | Treat as xs:string |
| Number| number | Treat as xs:float |
| Boolean | boolean | Treat as xs:boolean |
| Date | date | Treat as xs:dateTime |
| Array | array | Treat as xs:anyType* |
| Object | object | Generate XML structure |
| Xml | XML | xml | Treat as xs:anyType |
| Xmllist | XMLList | XMLlist | xmlList | xmllist | Treat as xs:anyType* |
| Any | any | xs:anyType |
| None | none | No value. |
Each of these tokens has alternative case representations rendering the tokens pseudo-case-insensitive, allowing obvious case ?misspellings?.
In most cases you can be more precise by using XML schema types, for instance using the xs:integer type instead of number when only integer values are expected.
Using XML schema built in types
.inputTypes and .outputType can specify a built-in schema type, indicated by using the ?xs:? prefix.
When used as an outputType, the return type is serialized as defined below, wrapped in a <return> ?parameter?, and further wrapped in a targetNamespace-qualified RPC wrapper. The schema reflects the use of parameter and rpc wrappers, and uses the declared type as the type of the return parameter.
When used as an inputType, the parameter value deserialized by removing the parameter and rpc wrappers, and converted to a Javascript native type as defined below.
| Declared type | Serialization/Desialization |
| xs:string | string |
| xs:normalizedString | string |
| xs:token | string |
| xs:language | string |
| xs:Name | string |
| xs:NCName | string |
| xs:ID | string |
| xs:IDREF | string |
| xs:NMTOKEN | string |
| xs:ENTITY | string |
| xs:NOTATION | string |
| xs:anyURI | string |
| xs:hexBinary | string |
| xs:base64Binary | string |
| xs:float | number |
| xs:double | number |
| xs:duration | number |
| xs:integer | number |
| xs:nonPositiveInteger | number |
| xs:negativeInteger | number |
| xs:long | number |
| xs:int | number |
| xs:short | number |
| xs:byte | number |
| xs:nonNegativeInteger | number |
| xs:unsignedLong | number |
| xs:unsignedInt | number |
| xs:unsignedShort | number |
| xs:unsignedByte | number |
| xs:positiveInteger | number |
| xs:decimal | number |
| xs:boolean | boolean |
| xs:dateTime | date |
| xs:date | date, time component droped |
| xs:time | date, date component droped |
| xs:gYearMonth | date, time and day components droped |
| xs:gMonthDay | date, time and day components droped |
| xs:gYear | date, time, month and day components droped |
| xs:gDay | date, time, year and month components droped |
| xs:gMonth | date, time, year and day components droped |
| xs:NMTOKENS | string |
| xs:IDREFS | string |
| xs:ENTITIES | string |
| xs:QName | string |
| xs:anyType | E4X XML object |
Support for optional parameters and arrays
To indicate a parameter is optional, an input type token can be followed by a ???. For example:
test.inputTypes = {"required" : "string", "optional1" : "number?", "optional2" : "boolean?"};
function test(required, optional1, optional2) {
}
Messages that omit optional parameters will result in those parameters being assigned the ?undefined? value. Optional parameters will be dispayed as minoccurs="0" in the schema.
Similarly, an input parameter can be an array. This is modeled in the schema as maxOccurs="unbounded", and repeated elements of the same name are collected into an Array, with items in the array following the normal mappings for that type. The postfix ?+? can be added to an input type (except for ?array? itself) to indicate that maxOccurs=?unbounded? should be added.
The ?*? postfix is equivalent to the presence of both ??? and ?+?, except that zero matching elements in the message results in an empty Array rather than ?undefined?.
Support for simple String-Valued enumerations
Simple enumerations are a common use case for defining a custom simple type. Additionally they provide a high value to the user to have in a description format (e.g enumerations can be converted into a drop down list in the try-it).
A type that is a list of string values separated by ?|? is treated as an enumeration.
accountInfo.inputTypes = {"type" : "silver | gold | platinum"};
accountInfo.outputType = "paidup | arrears | unknown";
function accountInfo(type) {
...
}
Support for Raw values In/Out
Without an outputType annotation, a returned value might be of any of the Javascript types and therefore an automatic conversion to XML is done. If the return value is not XML itself the data in the return value will be returned wrapped in an element called return which will also have a js:type arribute specifying the JavaScript type returned.
| Dynamic type | Wrapper | Value serialization |
| String | <return js:type="string">value</return> | Value serialized as xs:string |
| Number | <return js:type="number">value</return> | Value serialized as xs:float |
| Boolean | <return js:type="boolean">value</return> | Value serialized as xs:boolean |
| Date | <return js:type="date">value</return> | Value serialized as xs:dateTime |
| Undefined | <return js:type="undefined"></return> | No value |
| Array | <return js:type="array">value</return> | Value serialized as in Array -> XML |
| Object | <return js:type="object">value</return> | Value serialized as in Object -> XML |
| XML | <return js:type="xml">value</return> | Serialize directly as XML |
| XMLList | <return js:type="xmllist">value</return> | Serialize children directly as XML |
Wrapped vs Unwrapped behaviour
The Mashup Server will wrap all your request and responses by default in RPC type wrapper elements. These wrapper elements provide a conventional structure that can be easily interpreted as function parameters by many different platforms. It provides a means to serialize simple data values such as strings in XML. Wrapper elements come in handy when using the stub, because the stub generator recognizes this convention and can provide the user a uniform interface. If you are interested in preserving the structure and types of your parameters and return values, we advise you to use the default behaviour. The wrapper element name of the request will be in the form of <operationName> and the wrapper element name of the response will be of the form <operationNameResponse>. The following example illustrates this.
function echoString(param) {
return param;
}
The wire-level XML input to this function is as follows (with "value" used as the parameter"):
<p:echoString xmlns:p="http://services.mashup.wso2.org/test?xsd">
<param>value</param>
</p:echoString>
The wire-level XML output from this function is as follows:
<ws:echoStringResponse xmlns:ws="http://services.mashup.wso2.org/test?xsd">
<return xmlns:js="http://www.wso2.org/ns/jstype" js:type="string">value</return>
</ws:echoStringResponse>
Although providing wrapper elements is the default behaviour the user can always overide this. If you want to instruct the mashup server not to use wrapper elements you should set the inputTypes annotation or the outputType annotation (depending on your requirement) to "#raw". This instructs the mashup server to exclude wrapper elements. Note that if you decide to use raw XML then the input to the function will be the XML value itself. The following example illustrates this use.
echoString.inputTypes="#raw";
echoString.outputType="#raw";
function echoString(param) {
return param;
}
The wire-level XML input to this function is as follows (with "<value/>" used as the parameter"):
<value/>
The wire-level XML output from this function is as follows:
<value/>
As you can see that "#raw" forces the mashup server to exclude the wrapper elements.
Array -> XML conversion
When arrays are returned from an operation the mashup server serializes the array to XML as follows. Take the following function as an example,
returnArrayFunction.outputType="array";
function returnArrayFunction() {
var returnArray = new Array();
returnArray.property1 = "value1";
returnArray.property2 = 2.270;
returnArray.property3 = <value>2</value>;
return returnArray;
}
Thie output of the function would be serialized as follows:
<ws:returnArrayFunctionResponse xmlns:ws="http://services.mashup.wso2.org/test?xsd">
<return xmlns:js="http://www.wso2.org/ns/jstype" js:type="array">
<property3 js:type="xml">
<value>2</value>
</property3>
<property1 js:type="string">value1</property1>
<property2 js:type="number">2.27</property2>
</return>
</ws:returnArrayFunctionResponse>
As arrays can contain multiple elements they are always wrapped in a return element with the js:type attribute set to indicate that the return was an array.
Alternatively an array could have been declared as follows (Note that the array properties are declared using indices):
returnArrayFunction.outputType="array";
function returnArrayFunction(){
var returnArray = new Array();
returnArray[0] = "value1";
returnArray[1] = 2.270;
returnArray[2] = <value>2</value>;
return returnArray;
}
In this case the response will look as follows. Instead of having the elements as properties the elements will be as items because they have no name of course.
<ws:returnArrayFunctionResponse xmlns:ws="http://services.mashup.wso2.org/test?xsd">
<return xmlns:js="http://www.wso2.org/ns/jstype" js:type="array">
<item js:type="string">value1</item>
<item js:type="number">2.27</item>
<item js:type="xml">
<value>2</value>
</item>
</return>
</ws:returnArrayFunctionResponse>
Object -> XML conversion
Serialization of Objects is identical to that of Arrays with the following exception. The type ?js:object? is used. Take a look at the following example:
returnObjectFunction.outputType="object";
function returnObjectFunction() {
var returnObject = new objectFunc();
returnObject.property1 = "value1";
returnObject.property2 = 2.270;
returnObject.property3 = <value>2</value>;
return returnObject;
}
objectFunc.visible=false;
function objectFunc(){
}
This is the response:
<ws:returnObjectFunctionResponse xmlns:ws="http://services.mashup.wso2.org/test?xsd">
<return xmlns:js="http://www.wso2.org/ns/jstype" js:type="object">
<property3 js:type="xml">
<value>2</value>
</property3>
<property1 js:type="string">value1</property1>
<property2 js:type="number">2.27</property2>
</return>
</ws:returnObjectFunctionResponse>