Search code examples
typescriptsoaploopbackjsloopback4strong-soap

LoopBack 4: Adding type attribute to an element in a SOAP request


I'm using LoopBack 4 to access a third party SOAP API and am having difficulty getting a specific SOAP call to work. The documentation doesn't appear to cover this scenario.

Relevant parts of WSDL:

<xs:element name="change_item">
    <xs:complexType>
        <xs:sequence>
            <xs:element minOccurs="0" name="change" nillable="true" type="q1:item_change" xmlns:q1="http://schemas.datacontract.org/2004/07/configuration_services"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>
...
<xs:complexType name="auto_adjust_item">
    <xs:complexContent mixed="false">
        <xs:extension base="tns:item_change">
            <xs:sequence/>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
<xs:element name="auto_adjust_item" nillable="true" type="tns:auto_adjust_item"/>
<xs:complexType name="item_change">
    <xs:sequence/>
</xs:complexType>
<xs:element name="item_change" nillable="true" type="tns:item_change"/>

Here is the element from a working request sent from a Java demo application:

<change xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:auto_adjust_item"/>

For everything I tried, this is what LoopBack is sending to the SOAP API (which returns an error):

<ns1:change/>

I initially tried creating classes, auto_adjust_item extending item_change, both without any properties.

I then created them as models using lb4 model item_change and lb4 model auto_adjust_item, which became ItemChange and AutoAdjustItem. AutoAdjustItem was changed to extend ItemChange instead of Model. I messed with the @model annotation parameters and nothing helped.

An instance of AutoAdjustItem is passed through the service interface where the parameter is defined as change: ItemChange.

Does anyone know how I can add the type="auto_adjust_item" attribute to the element in the SOAP request?


Solution

  • Got it!

    Parameter definition:

    change: {
        $attributes: {
            $xsiType: string
        }
    }
    

    Pass this as the parameter:

    const change = {
        $attributes: {
            $xsiType: '{http://schemas.datacontract.org/2004/07/configuration_services}auto_adjust_item'
        }
    }
    

    Even better, create it as a class:

    export class autoAdjustItem {
        $attributes = {
            $xsiType: '{http://schemas.datacontract.org/2004/07/configuration_services}auto_adjust_item'
        }
    }
    
    const change = new autoAdjustItem();
    

    The element in the SOAP request, which the server accepted:

    <ns1:change xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://schemas.datacontract.org/2004/07/configuration_services" xsi:type="ns2:auto_adjust_item"/>
    

    This feels like a bad workaround with the hard coded namespace, but it works and I'll take it. I've spent enough time on this one feature, thanks to the severe lack of support.

    I got the idea to try this by staring at this documentation, which looks very different from how the tutorial had me do things.