Assign Message with multiple variables using Assign Variable

This proxy is extracting 2 variables in a proxy request flow. After the variables have been confirmed as extracted (via trace logs), I am using an Assign Message to format a request to be sent to the back end target server.

What I am doing:

If the client provides the parameter in the request, then I will extract the variable, and assign it as "variable.A".

If the client does not provide the parameter in the request, then I will assign it a defaulted variable obtained from an Access Entity policy triggered in the proxy preflow and call it "variable.B".

The AssignMessage/AssignVariable should determine:

- If "variable.A" does not exist or is null, then use "variable.B"

Below is the AssignMessage:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="AM-productPricingPayloadDefault">
    <AssignVariable>
        <Name>productId</Name>
        <Ref>variable.A</Ref>
        <Template>{variable.B}</Template>
    <AssignVariable>

What I am seeing:

If "variable.A" is provided by the client, then the proxy executes as expected. However, if "variable.A" is not provided, then the proxy does not substitute using "variable.B".

What I expect to see:

If the client does not send parameter to populate "variable.A", then the AssignVariable would look to the "Template" section and use "variable.B".

Again, I have confirmed that "variable.B" is a legitimate/populated cached variable via Apigee Trace Logs and according to the Apigee Docs (https://docs.apigee.com/api-platform/reference/policies/assign-message-policy#assignvariable). What I am attempting should work using the Template functionality so I am assuming I simply have a format/syntax issue that I am not seeing. I would also prefer to NOT use a JavaScript for this. Any assistance would be appreciated.

1 3 1,712
3 REPLIES 3

That's not how the AssignVariables action works. If the doc states otherwise, then we need to correct the documentation.

Here's what happens:

Template Ref Value Result
Y any any evaluate the template, and set the result as the value for the target variable.
N Y Y resolve the variable mentioned in Ref and set its value into the target variable, if it fails, set the value from the Value element
N Y N resolve the variable mentioned in Ref and set its value into the target variable, if it fails, do nothing.
N N Y set the given value as variable value if it is not null
N N N valid config, but pointless. No-op.

In other words if there is a Template present, it is applied. The order in which you specify Ref, Value, and Template does not affect precedence.

As a result, what you want is... not covered by any of those cases.

The team has considered adding a null-coalescing function to the message template. This would give you something like:

 <AssignVariable>
    <Name>productId</Name>
    <Template>{coalesce(variable.A,variable.B)}</Template>
 <AssignVariable>

Which basically says "assign the first non-null value". But this has not yet been implemented.

Unfortunately I don't know of a way to do this with a single AssignMessage alone. You could do it with a Condition element wrapped around a second AssignMessage, but I guess you already knew that.

Or JavaScript.

for null-coalescing function, ref: b/139698514

I appreciate you responding back. I guess I must have misread the documentation, but below is what gave me the impression this was possible:

Use the <Ref> element to specify the source variable. If the variable referenced by <Ref> is not accessible, Edge uses the value specified by the <Value> element.

If the flow variable specified by <Ref> does not exist, cannot be read, or is null, then Edge assigns the value of <Value> to the destination flow variable instead.

I at first was hoping I could simply assign another variable in the "Value" section but it looks like that will only accept a literal string rather than a variable. Now that I am looking I do so that if "Template" is defined in the AssignVariable it will take precedence over the other child elements meaning the "Ref" element will not even be evaluated.

Thanks again for the advice on this it keeps me from spending another couple hours of getting no where. I will look to do this with JavaScript.