Mapping data between context and WSDL data

About this task

When invoke Web service inside BTT, the common way is get the required data from Context to fill the parameter of the target endpoint (Web service operation), and after the invocation, the return value will be mapped back to the Context. Invoker has provided a complete set of APIs to help you map data automatically. Let's take the sample in Invoking with non-primitive data parameters to illustrate how it works.

Procedure

  1. The definition of Context has special requirement to meet the mapping data rule.
    1. One Java Bean match to a KeyedCollection.
    2. If the parameter in the WSDL file has been defined in a wrapper style, you must define the KeyedCollection in the hierarchical way with two levels. The value of id attribute for the nested KeyedColleciton must equal to the name of the wrapper element inside WSDL.
      <xs:element
      name="queryCanRecourse" type="tns:queryCanRecourse"></xs:element><xs:complexType
      name="queryRecourse">
      				<xs:sequence>
      <xs:element name="arg0" type="tns:recourseSearchBean" minOccurs="0"></xs:element>
      				</xs:sequence>
      		</xs:complexType><xs:complexType name="recourseSearchBean">
      				<xs:complexContent>
      			        <xs:extension base="tns:baseSearchBean">					     <xs:sequence>
      							<xs:element name="acceptor" type="xs:string" minOccurs="0"></xs:element>
      							<xs:element name="acptDt" type="xs:dateTime" minOccurs="0"></xs:element>
      							 						</xs:sequence>
      					</xs:extension>
      				</xs:complexContent>
      			</xs:complexType>
      The XML snippet is quoted from a WSDL file. The message queryRecourse is a complex type and the definition of KeyedCollection correspondent with the queryRecourse is like the following:
      <kColl id="QueryRecourseData" dynamic="true">
      	<kColl id="arg0">
      		<field id="">
                  <field id="">
       	</field></field></kColl>
      			
      </kColl>
      As you can seen from the example, the value of id for the outer layer KeyedCollection is arbitrary, but the value of id for the inner layer is arg0 which is equal to <xs:element name=""></xs:element>
    3. c. If the parameter in the WSDL file has been defined in a non-wrapper style, define the KeyedCollection with one level. Take the example to show how to define a non-wrapper style data mapping.
      <xs:element name="login">
          <xs:complexType>
           <xs:sequence>
            <xs:element name="user" type="tns1:User"></xs:element>
           </xs:sequence>
          </xs:complexType>
      </xs:element><xs:complexType name="User">
          <xs:sequence>
           <xs:element name="password" type="xsd:string" nillable="true"></xs:element>
           <xs:element name="userID" type="xsd:string" nillable="true"></xs:element>
          </xs:sequence>
       </xs:complexType><kColl id="loginData">
        <field id="userID"></field>
        <field id="password"></field>
      </kColl>
  2. Configure WSDII in the invoker.xml
    Table 1. WSDII attributes
    Attributes Attributes Description
    id Arbitrary value, variable for the invocation
    wsdURL WSDL URL for the target service
    operation The target invocation operation
    id Arbitrary value
    type Parameter type, if primitive type, the value is the class name; if non-primitive type, the value is GenericDataObject.
    Sample for WSDII definition: <WSDII id="login" wsdlURL="http://localhost:8080/BankWebServiceProvider2/wsdl/UserService.wsdl" operation="login"> <parameters> <wsDIIparameter id="NewOperationRequest" type="GenericDataObject"></wsDIIparameter> </parameters> </WSDII>
  3. Write invocation code. There are two important APIs must introduce firstly.
    1. convertContexDataToGenericDataObject Map data from Context to Generic Data Object
    2. convertGenericDataObjectToContex Map data from Generic Data Object to Context
    Invocation operation of Web Service, like the following snippet, is template-oriented. You have to pay much attention to the UserDefineTypeInfo which get from WebServiceInfo. There are two ways to get the UserDefineTypeInfo, by QName and by name. If by QName, initiate an instance of QName with correct namespaceURI and localpart. If by name, you can refer the next section WSDL Extractor Tool to find how to locate the correct parameter value.
    WSDynamicInvoker inv =(WSDynamicInvoker) ivf.createInvoker("login2");
    Context loginCtx = ContextFactory.createContext("loginCtx");
    loginCtx.setValueAt("userID", "user01");
    loginCtx.setValueAt("password", "xxxxx");
    WebServiceInfo wsinfo =((WSDynamicInvoker)inv).getWsInfo(); 
    WebServiceDIInvokerParameter websdiiparm = (WebServiceDIInvokerParameter) inv.getParameters().get("NewOperationRequest");
    	
    UserDefineTypeInfo userType = wsinfo.getUserDefineTypeByName("{http://beans}User");
    GenericDataObject gdb = inv.convertContexDataToGenericDataObject(websdiiparm, userType, loginCtx);
    	Object result =  inv.execute(new Object[]{gdb});