0

I have used an Existing WSDL to create an Experience API where I am performing several steps before either:

  1. Passing the SOAP Request Message as-is to the Original Backend System using Mule4 Web Service Consumer or
  2. Calling another Backend System (RESTful API) and transforming the Response to match the Expected SOAP Response Message

Sample Message

<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="urn:Acme/PublicService/V1" xmlns:ns0="urn:/Acme/BasicDataPublicService/V1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <env:Header>
        <a:Action s:mustUnderstand="1" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">urn:Acme/PublicService/V1/PublicService/SetCustomer</a:Action>
        <a:MessageID xmlns:a="http://www.w3.org/2005/08/addressing">urn:uuid:4afe0693-adea-4ede-bec9-10b694708d85</a:MessageID>
        <a:ReplyTo xmlns:a="http://www.w3.org/2005/08/addressing">
            <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
        <VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo8KxyyGpakdIj8o84JOeAMsAAAAAQBkt3vfAK0C4dDgn3rAKx/iXgqYosnhKv/OHgph9cXoACQAA</VsDebuggerCausalityData>
        <a:To s:mustUnderstand="1" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">http://316.820.517.311:36990/PublicInterface/Service</a:To>
        <AuthorizationToken xmlns="urn:Acme/Authorization/V1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <CultureName>uk-UK</CultureName>
            <OnBehalfOf i:nil="true"></OnBehalfOf>
            <Password>****</Password>
            <UserName>sa-ACME</UserName>
        </AuthorizationToken>
    </env:Header>
    <env:Body>
        <ns:SetCustomer>Muli-Tier Message</ns:SetCustomer>
    </env:Body>
</env:Envelope>

SOAP Header Elements as they appear in Debug Mode

According to Mulesoft KB; this requires additional Transformation steps in the beginning of the flow. Passing the SOAP Body is not an issue; the SOAP Header is a pickle, however. Especially since the KB document is hard-coding the values; while in my case these need to be dynamic (i.e. coming from the Original SOAP Request message).

I tried mapping the Header Parameters to a Variable as described but I cannot seem to get to it.

Option 1 Mapping the Header Elements to Children Attributes of a Variable, results in the Variable Storing Null

%dw 2.0
output application/xml writeDeclaration=false, writeNilOnNull=true
ns ns0 http://www.w3.org/2005/08/addressing
ns s http://www.w3.org/2003/05/soap-envelope
---
headers: {
    ns0#Action @(s#mustUnderstands: payload.headers.Action.@mustUnderstands): payload.headers.Action as String default null,
    ns0#MessageID: payload.headers.MessageID as String default null,
    ns0#ReplyTo: {
        ns0#Address: payload.headers.ReplyTo.Address as String default null
    },
    VsDebuggerCausalityData: payload.headers.VsDebuggerCausalityData as String default null,
    ns0#To @(s#mustUnderstands: payload.headers.To.@mustUnderstands): payload.headers.To as String default null,
    AuthorizationToken: {
        CultureName: payload.headers.AuthorizationToken.CultureName as String default null,
        OnBehalfOf: payload.headers.AuthorizationToken.OnBehalfOf as String default null,
        Password: payload.headers.AuthorizationToken.Password as String default null,
        UserName: payload.headers.AuthorizationToken.UserName as String default null
    }
}

Variable (vars.headerParameters) used to store SOAP Header showing Null Values, while Variable (vars.queryParameters.dateFrom) storing a Value from SOAP Body has a Value

Option 2 Mapping payload.headers to a Variable, results in extra tags; and losing the XML Tag attributes

%dw 2.0
output application/xml writeDeclaration=false, writeNilOnNull=true
ns ns0 http://www.w3.org/2005/08/addressing
ns s http://www.w3.org/2003/05/soap-envelope
---
headers: payload.headers

Variable (vars.headerParameters) used to store SOAP Header showing double tags without tag attributes, while Variable (vars.queryParameters.dateFrom) storing a Value from SOAP Body has a Value

  • 1
    Instead of the debugger you should use HTTP wire logging (https://help.mulesoft.com/s/article/How-to-Enable-HTTP-Wire-Logging) to show how the headers are really being sent in the WSC and attach the results here. Also include the flow snippet in XML showing the transformation and WSC so there is more context to understand the behavior. – aled Aug 20 '20 at 14:27
  • Hi. Can you please clarify if you are using APIKit for SOAP to expose the API? I'm not understanding what creates "payload.headers" in the flow. – Jorge Garcia Aug 20 '20 at 14:27
  • @JorgeGarcia Yes, I am using the SOAP Kit; and the Flows were Generated by Anypoint Studio from the WSDL; then I filled in the blanks. – Muhammad Alaa Aug 20 '20 at 15:21
  • @aled I will try to do that first thing in the morning; right now I am twisting Option 2 a little and it seems that I will have my Header. Basically: I am plucking the data from within the Double Tags ( #notClean ) – Muhammad Alaa Aug 20 '20 at 15:24

2 Answers2

0

It seems there is an issue with the WebService Consumer connector when generating the SOAP Envelope Header.

Instead of using the WebService Consumer Connector, try using an HTTP Request Connector passing the payload as-is.

olamiral
  • 1,296
  • 7
  • 8
  • That sounds like an interesting approach, but what is the compromise here? e.g. what Functionality would I lose? – Muhammad Alaa Aug 20 '20 at 15:26
  • The main drawback is that you will have to handle the SOAP response manually. At the end of the day, a SOAP request is nothing more that an HTTP POST request where the content is an XML that complies with the SOAP Envelope specification. Do you know what kind of security policies are implemented in the remote web service? – olamiral Aug 20 '20 at 15:52
0

I will come back and add more details on the answer, but here is how to solve that issue:

%dw 2.0
output application/xml writeDeclaration=false, writeNilOnNull=true
---
headers: (payload.headers.headers mapObject (value, key) -> {
(value)
})