Repeating elements where subsequent ones contain nulls - MAP step issue

I have a flow service which loops through Contact information. The Contact is a repeating element which contains a PhoneNum, PostAddr, Email, and WebAddr element. Under each of those are a set of key/value pairs. When I call a providers service via a SOAP call it will place null values into required fields defined by their wsdl/schema for the second and so on instance. Is this how I am handling repeating elements or is this their issue?

In this screenshot I show in the first instance of Contact[0] include the PhoneNum, PostAddr, and Email, and in Contact[1] instance I only include PostAddr.

In this screenshot I have jumped into the consumer service provided by the provider. Note the second Contact[1] contains PhoneNum and Email along with the expected PostAddr, but the fields I didn’t send in my payload are present and null.

nullvaluesinrequest_1

In this screen shot I am looping through the contacts

nullvaluesinrequest_3

In this screen shot I call one of my flow services. Note Contact is a Document and not Document List which should occur in the Loop

Then I call their service which is mapped to the repeating Contact element. It should only send what I put in the payload

nullvaluesinrequest_5

Maybe this is a newbie question of why, but more so should I be doing something differently when mapping my fields to theirs when there are repeating instances that I looped through. Do I need to flush something out first so elements that were present in the first instance do not show up in the second one?

Hi Chris,

while looping over the list, the list will turn into a single document (representing the current entry in the list) from which you can then map the values.

If the result list is guaranteed to have the same number of entries this can specified on the loop step as output array.
if not, you will to initialize a temp list before the loop, map the values to a temp document, add this temp document to the temp list and drop the temp document.
After the loop map the temp list to designated target list.

Dependent on the flag if the fields are required or not you can use conditional mappings to avoid mapping “null” into fields for which no value was sent by the sender.

Regards,
Holger

So, in my case I would do the following:

SEQUENCE

MAP (Map Document Type to Temp Document Type)

LOOP on Contact in Temp Document Type with no Output Array defined

Invoke address service call

BRANCH on label

%AddrId% != $null MAP (found existing address so add ID to Contact element holding ID)

MAP Temp Document List of Contact to Original Document Type

Call providers SOAP service

Just to confirm is the temp document list suppose to be just the repeating element block from the larger document or the whole thing which I will then set the output array to the temp document’s Contact?

I’ll play with this a little. My service for searching for an existing address has to LOOP and works perfectly fine but then again I am not having to maintain the larger document type of the request.

Hi Chris,

SEQUENCE
- init tempList (just an empty Map to the tempList)
- LOOP over source list
-- transform data from current source list element to new temp doc (insert your real logic here)
-- add tempDoc to tempList (pub.list:appendTo List)
-- drop tempDoc and all other interim variables except source list element, target doc and tempList
- map tempList to real target list.
- drop tempList
- call providers SOAP service

The list for the loop will be “/OrgData/Contact” (just right click on it and select “Copy”) according to your screenshots above.
Invoking the providers SOAP service inside the loop is only meaningful when the target has only single Contact document in their structure (instead of a list/array).

Regards.
Holger

Holger,

Sorry but it isn’t clicking for me. I am almost about to create a Java service that does it all, but the desire is to try to use the flow service. When init a templist are you referring to having a MAP step where I add a variable in the input pipeline lets call templist that will link to a variable in the output pipeline called templist? In the LOOP it would go off of the original source /SBLRequest/OrgPartyInfo/OrgData/Contact which will change from a Document List to a Document that I can loop thru. Is the TempDoc a copy of the source Contact in a MAP step? When I look at appendToDocumentList it looks like it wants a Document List for its toList in Service In. Would the Service Out variable toList go to the templist created in the MAP step prior to the Loop? If so each time it gets called it seems to overwrite the existing one.

Chris

Hi Chris,

when initializing the tempList, just create a new variable in the output of the map step (as a DocList referencing the Contact docType definition) and just click on setValue, but leave it empty.
This tempList go to inList and outList for the appendToList step.
By doing so the outList with latest entry appended will replace the inList without the appended entry.

tempDoc is just a single document instance of the Contact docType definition.

Regards,
Holger

Thank you for the clarity. When I pointed to inList for the service of my document it just overwrote it. When I used the FromList it seems to behave correctly. The problem continues because even though everything looks good, once I invoke to the consumer service and I jump into it the Contact elements for second instance still does a 1-1 of what is in the first instance. For example:

This is what I am sending the consumer services:

You’ll see that Contact[0] has PhoneNum, PostalAddr, Email, and WebAddr is empty. In Contact[1] only PostalAddr has content in it.

When I jump into the first line of the consumer service I see the following:

nullvaluesinrequest_1_2

For some reason it still creates null values for elements I did not create in my request based on Contact[0]. Is this SOAP causing it? Here is my LOOP section:

and I step into the consumer service and look at the variable values

I tested the provider’s service from SoapUI and it works fine.

Hi Chris,

in this case you will need to use conditional mappings for those fields, otherwise IS will create fields with null value.
These can be put in the properties section of the mapping line.
Condition should look like “%fieldname% != $null || %fieldname% != “””.
First half means missing field, second half means existing, but empty field (length=0).

Regards,
Holger

Well, that didn’t work. I hate keeping beating the bush on this. I tried various conditional mappings and once I call the SOAP service the nulls show up in the second instance of Contact element. So, what I did is create a new flow service which will take a document list of Contact and pass it in. In the debugger I was able to see no null fields in the second instance and only saw the content I expected. Next I created a SOAP call of that very flow service and got the same results. I then modified the flow service of mine so it basically returns the input. I checked the pipeline out from the call and no changes, no extra elements, no nulls. I then map that to the document list which gets mapped to the input service of the provider’s SOAP call. I jump into that and the same fields in Contact[0] or in Contact[1] although in Contact[1] there should only be one element block called PostAddr. Interesting thing I have observed in in Contact[1] the unwanted elements are objects. Thoughts? I do know this service works fine calling it from SoapUI so it’s how my flow service is calling it I suspect, or how I configured the consumer somehow? I would switch over to a Java Service but I suspect I would encounter the same issue. This can’t be this hard. Why is it duplicating element blocks in a repeat element?

Hi Chris,

I believe you are getting null objects are due to below

image

where you mapped OrgData/Contact[1] PhoneNum and Email, even they have no values,
which is similar to setting :

  1. OrgData/Contact[1]/PhoneNum (null value) into ns1:PhoneNum
  2. OrgData/Contact[1]/PostalAddr(with value) into ns1:PostAddr
  3. OrgData/Contact[1]/Email (null value) into ns1:Email

so to prevent this, it is best to perform a BRANCH to check if OrgData/Contact/PhoneNum and OrgData/Contact/Email is not null before mapping

Regards,
thur

1 Like

@thurg Thank you for your feedback. I have made several changed based on @Holger_von_Thomsen suggestions that have cleaned up my links. I have incorporated conditional links which makes perfect sense along with using appendToDocumentList. The problem still persists as stated in my last posting which is very frustrating. My Pipeline In Document variable before I link to the SOAP Services’ Service In variable contains no additional elements with null values. Once it enters the consumer SOAP service those additional element that are not part of my original input show up. It is a 1-1 match with the second instance having null values in particular elements/fields. I have created a test flow service and converted it to a SOAP interface and the data going into it is the same coming out with no issues. The fields are not a straight aggregate but a choice option. Does that have any factor in this behavior?

I am about to scrap the flow service in this section and see if a java service does the same thing. I spent to much time getting the flow service working, although I ponder if the java service will encounter the same issue. It leads to further discussion on when it is truly best to use a flow vs java service. I have reached out to the provider for some guidance. I am hopeful they will be willing to assist.

Hi Chris,

can you share the part with the choice definition from the XSD?

Choices are not visible directly in the imported document type but the elements are marked as optional instead.

Regards,
Holger

Here is the snippet:

  <xsd:complexType name="Contact_Type">
    <xsd:sequence>
      <xsd:choice>
        <xsd:element ref="PhoneNum">
          <xsd:annotation>
            <xsd:documentation>[XXXX]Phone Number.</xsd:documentation>
          </xsd:annotation>
        </xsd:element>
        <xsd:element ref="PostAddr">
          <xsd:annotation>
            <xsd:documentation>[XXXX]Postal Address.</xsd:documentation>
          </xsd:annotation>
        </xsd:element>
        <xsd:element ref="Email">
          <xsd:annotation>
            <xsd:documentation>[XXXX]Email Address.</xsd:documentation>
          </xsd:annotation>
        </xsd:element>
        <xsd:element ref="WebAddr">
          <xsd:annotation>
            <xsd:documentation>[XXXX] Web Address</xsd:documentation>
          </xsd:annotation>
        </xsd:element>
      </xsd:choice>
    </xsd:sequence>
  </xsd:complexType>

Hi Chris,

in this case you will have to Branch over the Contact-Types (inside the loop) with one sequence per type in which you perform the mapping for each type.

Branch-Condition should then look like “%Contact_Type/element% != $null”.
“element” is one of the four types in the choice.
Remember to remove the double quotes from the condition.

Regards,
Holger

Sounds like @thurg observation and recommendation was consistent with what you are seeing @Holger_von_Thomsen. I had conditional links basically doing this vs a Branch. Once my development environment gets back up I’ll test this out.