I want to update several KVM entries at runtime, and I don’t know the names of the entries so I have to use variables. I have a JavaScript which will decide which are the entries to be modified and store them into an array variable, and I have another array variable for the values to be put. My problem is I can not access to the items of the array… I need something like this:
But this is not working, Apigee takes those variables as null. I’ve tried “items.0”, “items.values.0” and other combinations but it doesn’t work.
Maybe the problem is in the way I save the array variables? I’v made this JavaScript just for testing:
var items = [];
items.push("Name1");
items.push("Name2");
var values = [];
values.push("Value1");
values.push("Value2");
context.setVariable("items",items);
context.setVariable("values",values);
But when I use Debug I see those variables as “org.mozilla.javascript.NativeArray“ which I don’t know if is right. I’ve tried also with “JSON.stringify(items)” and then I can see the content of the array variable in the Debug, but anyway the KeyValueMapOperations policy still doesn’t work.
Also I’ve tried to use a JSON instead of an array, but it seems that KVM policies doesn’t allow JSONPath.
Sorry if this was already answered, I searched but couldn’t find anything.
Hey @JAAO, thanks for your question! We’ll keep checking in on this thread and encourage other members to share their thoughts.
By the way, we’re hosting a free community webinar next week “Production Patterns: Exporting Apigee logs for analysis” on September 4 at 11am EDT. If you’re interested, you can sign up here to join and get the link.
Hi, JAAO,
I’m not completely clear on what you want to accomplish. I see from the KVM policy you want to put things into the KVM. And I think you want to put things into the KVM , using keys and values that you extract from a JSON payload.
As you noted, the KVM policy does not accept jsonPath expressions for determining the key or the value. You cannot use <Parameter ref="items[0]"/> You must refer to a specific variable only. eg, <Parameter ref="item0"/>, assuming you have somehow set the variable item0 to hold a specific value, previous to the execution of the KVM policy.
If you want to set a variable based on JsonPath then you can use the AssignMessage policy, with AssignVariable, and the jsonPath static function, or you can use JavaScript. If you use JavaScript, the value you place into a variable with context.setVariable must be a primitive - a string or a number, not an array of same.
My suggestion to you is to break down the problem.
Get your KVM Put to work the way you want, referencing variables, as it is documented. Statically assign values into the variables, or use variables derived from the request like request.queryparam.key and request.queryparam.value.
Once that is working, separately use AssignMessage/AssignVariable with JSONPath to extract a value or values from a JSON payload, into a variable. Or JavaScript. The result of this part should be that specific variables hold specific primitive values, extracted from JSON. Use the debug UI to verify it is working as you desire.
Combine those two, and then maybe you have your solution.
Please note: this approach won’t work for a variable-sized list of items. I mean if sometimes you have 2 items, and sometimes 5, .. the approach I just described won’t work very well. The KVM policy does not have a way to express “Put this list of values, with this list of keys”. You have to explicitly specify each key, and each value.
Thank you very much for your answer. You understood it right, I have to put things into the KVM, using keys and values I have to calculate (they are not in the JSON payload directly, I will need a JavaScript anyway). I didn’t knew that arrays are not allowed into a KVM policy.
And yes, it’s a variable-sized list of items. I guess I always can do something like this in the JavaScript code:
This way I will have a variable number of primitive items and values that I can use in the KVM policy.
About the problem you mention in your last paragraph, the items size will always be lower than 7 for now, so I guess I could make a KVM policy that put 6 entries and let the null ones write a “__$$_EDGE_KVM_EMPTY_KEY_$$__“ (I can always add a policy to delete this entry), or put 6 KVM policies, each with a condition evaluating if “item0”, “item1” etc. are null. I’m not sure which would be a better solution. Edit: I have made several tests and it seems that the second option (using several policies with a condition) has better performance.
Is there a better way of putting into a KVM a variable-sized list of items?
Suppose item0=value0, item1=value1 and so on. If you have up to seven values , why not just use
«value0,value1,value2,…»
As THE value. And use one key. Look it up once and use a separate step to extract the sub-value from what you retrieved from the KVM. That may save you some effort.
The kvm get policy even has an “index” attribute that would allow you to get one item out of a comma separated list of values.
Another way to do this is to store all of the values encoded in a Json hash. Lookup the Json , then use a separate step that uses jsonpath to extract the particular thing you want.
Also - separate question - (you may have already mentioned this, I don’t recall) will the values in KVM change over time? If they are static you can encode the values as properties in the proxy. That would allow you to avoid the kvm lookup step entirely.
For other kvm related questions that may be helpful, search this forum. For example you may find
Those are good ideas, unfortunately I can’t implement them, because the KVM already exists and is used for other things, so I can’t change its “structure”. The keys and values are separated and I have to leave them that way. But they are good suggestions for other people.
Yes, the values will change over time. More specifically, some of them will gradually increase.
I will mark your first answer as a solution because it clarifies that using arrays in a KVM policy is not allowed, and explains several alternatives.