Incorrectly passing data "by reference"

Hi All,

I have a parent flow that contains a document called “h_environment”.

I call a child flow, with input “environment”. I pass “h_environment” into “environment”.

The problem is, any change to a sub-element of “environment” in the child flow is being reflected in the “h_environment” document! If I do a pipeline dump to file right after the map step that makes the change, I can see BOTH documents change at that point!

I don’t understand how the child flow even “knows” about “h_environment”. ie I understand it’s in the pipeline even though not explicitly passed as an input into the child, but I don’t understand how the child flow can change “h_environment” when it’s not directly referenced anywhere!

It’s as if “h_environment” is being passed “by reference” instead of “by value”.

Has anyone got any clues?

NB I can work around this by passing in the sub-elements of “h_environment” to the corresponding sub-elements of “environment”… but there’s heaps and this is very messy!

Cheers,
Ben.

you are right , the child service will have the doc “h_environment” in the pipeline .But i am not understanding if the mapping is right ,the value in the “h_environment” document should not change ,but anyhow if u can post the service it would help to find the issue.

Sri

That’s right. It is.

When mapping variables, strings are copied by value and documents (structures) are copied by reference. There is no special handling of variables when mapping to the the inputs or from that outputs of a service.

Thus h_environment and environment are pointers to the same underlying object. Changes made via either pointer will show up via the other pointer.

Yes it will. Documents are copied by reference. If one wants a copy of a document, then you have to explicitly make one. Simply mapping from one document variable to another does not clone the source (just like Java doesn’t clone objects when one has a objA = objB; statement).

Hi Reamon,

Thanks for the information - I learn something new every day using webMethods!

Just out of interest, does the same apply to other element types such as lists and (presumably) objects, nodes, etc?

What is the correct way to pass by value? How do I make an explicit object copy? Do I need to drop to Java?

Cheers,
Ben.

Me too!

Yes. Only strings are copied by value.

Keep in mind that there really isn’t a notion of “passing” a variable to a service in the same way one passes vars to a procedure/function/method on the call stack. The declared inputs and outputs are more geared to letting you know what variable name the service expects in the pipeline–and it will manipulate those.

That said, there are some things the runtime does that make the environment behave stack-like. For example, if a child service drops a var from the pipeline, the runtime will effectively restore it when control returns to the caller. Even so, most OO languages such as Java don’t automatically clone objects passed to methods. If you pass an object, say a HashTable, to a method and it manipulates that, you wouldn’t be surprised that when it modifies the var named “ht” (the var name the method refers to) that your var named “hashTable” reflects those changes, right?

So if you want a list, document, object to be left alone and a service to manipulate a copy of it, you need to make the copy of it yourself. You can either do this via FLOW steps and/or Java.

Not necessarily. Depending on the var you’re trying clone, a couple of FLOW steps may be sufficient. For larger vars, such as a document with nested structures and such, the IS Java API provides a deep clone method. You’ll want to use such a method diligently to make sure its usage isn’t a bottleneck.