I believe it's same & there is no difference. Is there any reason why there are two ways to do same ? Any difference between them ?
$$$REWARD$$$: If someone proves there is a difference, I will reward 50 Community Points from my own account. Any takers ?
Solved! Go to Solution.
You should use context. {setVariable, getVariable }
context.session will probably be deprecated in future releases.
I've used and relied on
context.session
before (quite a lot, actually) for what I believe to be valid use-cases.
As pointed out by Carlos, a major difference is variable types and, in the case of retrieval, how a non-existent variable will evaluate to null/undefined. In my opinion though, the fundamental difference is in what Mohammed started to share.
The scope covered by
context.session
versus context.[get|set]Variable()
is completely different. Variables set to context.session
are only available to the JavaScript policies executing in the flow and do not overlap with any of the standard variables available to the Edge runtime. In other words, neither of the following lines are valid.
context.session['request.verb']; // undefined context.session.request.verb; // Cannot read property "verb" from undefined
There's no sharing across requests either; don't be fooled by the name "session" 🙂
Now, onto a use-case for when I have previously used
context.session
. Let's assume a simple proxy; with a callout for translations, some mediation/mash-up of the two responses and a final response back to the client.
var targetResponseObj = JSON.parse(context.getVariable('response.content')); targetResponseObj.foo = 'awesome bar';
var serialisedModifiedResponse = JSON.stringify(modifiedTargetResponse); context.setVariable('flow.modifiedTargetResponse', serialisedModifiedResponse);
or
context.session.modifiedTargetResponse = modifiedTargetResponse;
var modifiedTargetResponse = JSON.parse(context.getVariable('flow.modifiedTargetResponse')); var calloutResponse = JSON.parse(context.getVariable('calloutResponse.content'); modifiedTargetResponse.translated = calloutResponse; context.setVariable('response.content', JSON.stringify(modifiedTargetResponse));
or
var calloutResponse = JSON.parse(context.getVariable('calloutResponse.content')); context.session.modifiedTargetResponse.translated = calloutResponse; context.setVariable('response.content', JSON.stringify(context.session.modifiedTargetResponse));
The point here isn't a comparison of the amount of code, but rather, the number of times data is parsed/serialised within your flow. With large responses, avoiding these additional steps can reduce the work MPs have to do and the footprint per request. This can make a difference at high levels of traffic.
Another use-case, more relevant to slightly larger proxies, would be to abstract common JavaScript function definitions to a single place.
// you could have a "set-functions" policy context.session.functions.padLeft = function(str, len) {...}; context.session.functions.isNaN = function(n) {...}; context.session.functions.validateEmail = function(email) {...}; // and later use these from other JS policies context.session.functions.padLeft('pad me', 10);
We now understand why getting and setting on context.session
doesn't show in the trace tool. It's the same reason you don't see anything in the trace for
if(){}
-- it's just executing JavaScript internally.
You asked about setting, not getting. But I think the most interesting difference is on the getting side, where it would affect truthiness. When the variable you are retrieving doesn't exist, context.session returns undefined while context.getVariable returns null. That's one of those weird JavaScript things that can trip you up when you're checking for the existence of something.
On the writing side, it appears that using .session doesn't show the var in the variables section of a trace. I didn't poke beyond that to see if there are oddities. I think I'd argue for context.setVariable so I could see what's happening to it in trace. ((Although the print() function works just fine with either method to dump the content to the Output from All Transactions section of trace.))
¯\_(ツ)_/¯
Thanks @Carlos Eberhardt , I believe it's due to some legacy code / backward compatibility we ended up having two different ways to store the custom values in message context flow. Looking forward to listening the story behind it from Engineering team. @arghya das Any idea ? Especially the word "session" is confusing for me when i hear in Apigee Edge Runtime context.
Hi @Anil Sagar ,
Another difference apart from one mentioned by @Carlos Eberhardt, context.setVariable creates or sets a flow variable which you can use in further step conditions. Whereas any session variable will not be available out the context of Javascript 😞
I have not tried accessing session variables through Java Callout as there is no documentation available to refer. I believe it's only available for Javascript Callouts.
Thanks @Mohammed Zuber , +1, It was on my list to verify same using ExtractVariables policy too. Will keep you guys posted.
You should use context. {setVariable, getVariable }
context.session will probably be deprecated in future releases.
Thank you @Peter Johnson for the information. It's helpful. @docs , @sgilson , Can we update this information in docs here / point to this article / Add a note saying "Using Context.Session is discouraged" ? Thank you.
How is the deprication going? To me it seems this whole shenanigans is essentially a flawed design and should be corrected as soon as possible. Is usage of context.session "officially" now frowned upon? If yes, it should be expressed in the manual.
I've used and relied on
context.session
before (quite a lot, actually) for what I believe to be valid use-cases.
As pointed out by Carlos, a major difference is variable types and, in the case of retrieval, how a non-existent variable will evaluate to null/undefined. In my opinion though, the fundamental difference is in what Mohammed started to share.
The scope covered by
context.session
versus context.[get|set]Variable()
is completely different. Variables set to context.session
are only available to the JavaScript policies executing in the flow and do not overlap with any of the standard variables available to the Edge runtime. In other words, neither of the following lines are valid.
context.session['request.verb']; // undefined context.session.request.verb; // Cannot read property "verb" from undefined
There's no sharing across requests either; don't be fooled by the name "session" 🙂
Now, onto a use-case for when I have previously used
context.session
. Let's assume a simple proxy; with a callout for translations, some mediation/mash-up of the two responses and a final response back to the client.
var targetResponseObj = JSON.parse(context.getVariable('response.content')); targetResponseObj.foo = 'awesome bar';
var serialisedModifiedResponse = JSON.stringify(modifiedTargetResponse); context.setVariable('flow.modifiedTargetResponse', serialisedModifiedResponse);
or
context.session.modifiedTargetResponse = modifiedTargetResponse;
var modifiedTargetResponse = JSON.parse(context.getVariable('flow.modifiedTargetResponse')); var calloutResponse = JSON.parse(context.getVariable('calloutResponse.content'); modifiedTargetResponse.translated = calloutResponse; context.setVariable('response.content', JSON.stringify(modifiedTargetResponse));
or
var calloutResponse = JSON.parse(context.getVariable('calloutResponse.content')); context.session.modifiedTargetResponse.translated = calloutResponse; context.setVariable('response.content', JSON.stringify(context.session.modifiedTargetResponse));
The point here isn't a comparison of the amount of code, but rather, the number of times data is parsed/serialised within your flow. With large responses, avoiding these additional steps can reduce the work MPs have to do and the footprint per request. This can make a difference at high levels of traffic.
Another use-case, more relevant to slightly larger proxies, would be to abstract common JavaScript function definitions to a single place.
// you could have a "set-functions" policy context.session.functions.padLeft = function(str, len) {...}; context.session.functions.isNaN = function(n) {...}; context.session.functions.validateEmail = function(email) {...}; // and later use these from other JS policies context.session.functions.padLeft('pad me', 10);
We now understand why getting and setting on context.session
doesn't show in the trace tool. It's the same reason you don't see anything in the trace for
if(){}
-- it's just executing JavaScript internally.
I didn't think my answer would be so long - apologies.
Perhaps I should have shared this some other way.
Absolutely great answer @Omid Tahouri +1, As a community we always love to see more detailed answers. No need to apologies at all. Great answer again, Keep them coming !!
A note has been added to the doc. Thanks -- this is an excellent discussion.
Awesome, Thank you @wwitman , +1
Type a product name