Calling a simple .NET webservice from a mediator sequence

Hi folks,

this is my first post and I am very new to mediator so please excuse my stupidity.

I have a simple .NET webservice that is defined as follows


<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://tempuri.org/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
      <s:element name="getCustomer">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="id" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="getCustomerResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="getCustomerResult" type="tns:Customer" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:complexType name="Customer">
        <s:sequence>
          <s:element minOccurs="0" maxOccurs="1" name="Id" type="s:string" />
          <s:element minOccurs="0" maxOccurs="1" name="Title" type="s:string" />
          <s:element minOccurs="0" maxOccurs="1" name="FirstName" type="s:string" />
          <s:element minOccurs="0" maxOccurs="1" name="Surname" type="s:string" />
        </s:sequence>
      </s:complexType>
      <s:element name="deleteCustomer">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="id" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="deleteCustomerResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="1" maxOccurs="1" name="deleteCustomerResult" type="s:boolean" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="createCustomer">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="customer" type="tns:Customer" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="createCustomerResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="createCustomerResult" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
    </s:schema>
  </wsdl:types>
  <wsdl:message name="getCustomerSoapIn">
    <wsdl:part name="parameters" element="tns:getCustomer" />
  </wsdl:message>
  <wsdl:message name="getCustomerSoapOut">
    <wsdl:part name="parameters" element="tns:getCustomerResponse" />
  </wsdl:message>
  <wsdl:message name="deleteCustomerSoapIn">
    <wsdl:part name="parameters" element="tns:deleteCustomer" />
  </wsdl:message>
  <wsdl:message name="deleteCustomerSoapOut">
    <wsdl:part name="parameters" element="tns:deleteCustomerResponse" />
  </wsdl:message>
  <wsdl:message name="createCustomerSoapIn">
    <wsdl:part name="parameters" element="tns:createCustomer" />
  </wsdl:message>
  <wsdl:message name="createCustomerSoapOut">
    <wsdl:part name="parameters" element="tns:createCustomerResponse" />
  </wsdl:message>
  <wsdl:portType name="CustomerServiceSoap">
    <wsdl:operation name="getCustomer">
      <documentation xmlns="http://schemas.xmlsoap.org/wsdl/">Obtains details of a given customer.</documentation>
      <wsdl:input message="tns:getCustomerSoapIn" />
      <wsdl:output message="tns:getCustomerSoapOut" />
    </wsdl:operation>
    <wsdl:operation name="deleteCustomer">
      <wsdl:input message="tns:deleteCustomerSoapIn" />
      <wsdl:output message="tns:deleteCustomerSoapOut" />
    </wsdl:operation>
    <wsdl:operation name="createCustomer">
      <wsdl:input message="tns:createCustomerSoapIn" />
      <wsdl:output message="tns:createCustomerSoapOut" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="CustomerServiceSoap" type="tns:CustomerServiceSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
    <wsdl:operation name="getCustomer">
      <soap:operation soapAction="http://tempuri.org/getCustomer" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="deleteCustomer">
      <soap:operation soapAction="http://tempuri.org/deleteCustomer" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="createCustomer">
      <soap:operation soapAction="http://tempuri.org/createCustomer" style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CustomerService">
    <documentation xmlns="http://schemas.xmlsoap.org/wsdl/">Public interface for interacting with customers.</documentation>
    <wsdl:port name="CustomerServiceSoap" binding="tns:CustomerServiceSoap">
      <soap:address location="http://localhost/FusionAdapter/CustomerService.asmx" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

The method I am trying to call is the getCustomer() method.

My mediator sequence looks like this:


<?xml version="1.0" encoding="UTF-8"?>
<sequence version="4.0" xbd.zid="N400001">
    <block xbd.zid="N400002">
        <step component="SagLogger" xbd.logger.message="Call to sequence seq_getcustomergw begin" xbd.zid="N400003"/>
        <step component="SagSoapGateway" xbd.soap.arg0.parameters="/node()[local-name()='getCustomer' and namespace-uri()='http://tempuri.org/']" xbd.soap.handlefault="false" xbd.soap.operation="getCustomer" xbd.soap.port.qn="{{http://tempuri.org/}}CustomerServiceSoap" xbd.soap.res0.parameters="/" xbd.soap.service.qn="{{http://tempuri.org/}}CustomerService" xbd.soap.session="true" xbd.soap.style="document" xbd.soap.wsdl.url="http://localhost:81/FusionAdapter/CustomerService.asmx?WSDL" xbd.zid="N40003439"/>
        <step component="SagLogger" xbd.logger.message="Call to sequence seq_getcustomergw end" xbd.zid="N400004"/>
    </block>
</sequence>

The issue I have is with extracting data from the returned XML. You will notice right now that the xbd.soap.res0.parameters is set to / i.e. the root node of the response. This works perfectly.

BUT… I am not interested in the root node.

The ‘real’ response from the web service will be as follows:


<?xml version="1.0" encoding="utf-8"?>

<getCustomerResponse xmlns="http://tempuri.org/">
 <getCustomerResult>
  <Id>12345</Id>
  <Title>Mr</Title>
  <FirstName>Ian</FirstName>
  <Surname>Gratton</Surname>
  </getCustomerResult>
</getCustomerResponse>

Now if I modify the value of xbd.soap.res0.parameters to…


/node()[local-name()='getCustomerResponse' and namespace-uri()='http://tempuri.org/']/node()[local-name()='getCustomerResult' and namespace-uri()='http://tempuri.org/']

I get an error in the debugger which basically says


 Mediator internal error: com.softwareag.xbridge.exceptions.XException: No on_error sequence found. Exception: "com.softwareag.xbridge.exceptions.XException: result XPath selects no elements" in sequence "file:/C:/tomcat/webapps/mediator/dotnetwssamples/seq_getcustomergw.xml" at line 5.

Now I read that to imply my xpath does not select any nodes.

If I take the resulting XML and place it into XML Spy and use the exact same xpath expression it selects what I expect it to.

Am I missing something

Thanks in advance

Just a quick update.

I also appreciate there is another way I can achieve this.

I could

  1. Have a transformer step that uses XSL to prepare the SOAP envelope.
  2. Have a HttpGateway step to perform the HTTP Post against the web service endpoint
  3. Have another transformer step to extract the data from the returned SOAP envelope.

But this seems like a lot of extra work if the SagSoapGateway task can do all this in one go. I also think that this approach saves having to have separate XSL stylesheets which will obviously need to be modified if the WSDL definition of the service changes in future.

I have tried numerious other xpath statements but still without any luck.

Hi Ian,

When you specify ‘/’ as a xbd.soap.res0.xxx argument, you are really invoking a special case, where the Mediator will replace your message payload with the entire SOAP:Body content. This appears to be working, based on what you said.

When you specify something other than ‘/’ for a xbd.soap.res#.xxx argument, the value specified is an xpath that identifies the location in your payload message where the result is to be inserted, not an xpath that selects a portion of the response. When you don’t opt for the entire SOAP:Body, the data you get is defined by the WSDL for the service, in this case the wsdl:part named parameters in the getCustomerResponse message.

If you specify “/node()[local-name()=‘getCustomer’ and namespace-uri()=‘http://tempuri.org/’]”, then you should get the soap response elements (the getCustomerResponse message, inserted as a child of the getCustomer element of the payload document.

Hope this helps.

Thanks for clearing that up Mike. Its great that I can prove basic interop between mediator and .net. I have some more complex web services to call so we’ll see how I get on with those.