DTL Editor actions with persistent/serialized classes

Primary tabs

Good day all -

I am attempting to use the Data Transformation Builder (for ease of use for my other engineers) to build up a web service request object to send to an outbound operation. The source is a custom persistent class (extends Ens.Response, %JSON.Adaptor) and has serialized sub-class data elements and the request object is a custom persistent class (extends Ens.Request, %JSON.Adaptor.)

When attempting to use a for each on one of the serialized properties of the source object, the for each works (source.Items()) but when I get into inspecting, via a conditional, the items within, it doesn't work like I thought it would. If I attempt to access an item like:

source.Items.(i).Value

It does not work. I have to use:

source.Items.GetAt(i).Value

And this works. But of course the DTL Editor doesn't project the GetAt function when defining the action automatically from the drop-down - I have to manually key it in each time (which is not very user friendly to my other engineers that may not know to do this intrinsically.) The DTL Editor projects the first statement, which doesn't work.

Why is this? Is there something I missed when defining my custom message classes that instructs the DTL Editor how to properly project or access the items within a list collection? Or is the DTL Editor simply not meant to work with these custom classes in the same way?

I can get it to work, obviously, but more just trying to understand from a learning perspective.

Thanks,

Craig

Replies

Can you cut this down to a minimal example (actual code)? What you describe seems to work here. What "doesn't work"?

If I iterate over a (list of) property:

this ultimately compiles to:

As you can see, the .(i) is replaced with .GetAt(i). (Note that I replace the default key "k1" with "i" here to match your example.)

Regards,
Gertjan.

Thanks for your response - here is a snippet that doesn't compile:

ERROR: FAIS.DTL.MyDtlName.cls(Transform+11) #1011: Invalid name : '(source.Items.(i).ItemNumber=".1")' : Offset:21

You see it appears to be complaining about the reference to the source object (at least if I'm reading the error right... maybe I'm not!)

If I change line 3 (edit: and line 4 and 5 too, of course, as appropriate) to source.Items.GetAt(i).ItemNumber=".1", it works as it should and compiles and runs perfectly. But as you point out, the compiler should boil that down for me.

Here's the source:

Ah, I see -- yes, I can reproduce this, and I would think this is a bug. (It does work as expected in an "if", but not in a "case".) You may want to take this up with WRC, to see what they think.

As a workaround, are you aware that you can use local variables? You could assign the value of source.Items.(i) to a local variable, and use that in the case statement. Something like this:

In a switch statement like yours, this would probably save some typing as well. It does mean the lines in the DTL no longer display properly, though. (Although they might not anyway here.)

Regards,
Gertjan.

Good morning Gertjan - 

Thanks for confirming my suspicions re: a potential bug. Yes, I'm aware of the availability of local variables, certainly not a new user of InterSystems' products hence my confusion when what I suspected should work, based on my prior experiences, did not.

Since the 'case' is a conditional and usually treated like a shorthand 'if' in compilers, I had thought the IRIS compiler would boil it down much the same

I will open a WRC incident to let them know of the issue and utilize a workaround for now. Many thanks for your help proving I wasn't crazy!

For anyone reading this in the future, this was acknowledged as a bug by the WRC - devchange JGM926. Scheduled for 2020.2 release (subject to change.)

Simple workaround, pointed out by Gertjan's answer, is to store the value to a local variable and use the local variable in the case statement.