Sharedflow dynamic conditional string not working in default xml

Hi Team,

I have requirement to read multiple API proxies names and that includes request path with comma (“,”) separated from keyvaule maps as metioned below

KVM name is SF-KVM and the key name is globalvar that contains a value

apiproxyname1,apiproxyname12,apiproxyname3,apiproxyname4,/apiproxyname1/sample/json2xml

I have used a KVM policy to retrieve value and written a java script policy to construct the conditional string to execute one of the policy based on condition in a shared flow default flow.

 

var kvalue=context.getVariable("kvm-val");
var conditionStr="";
var arr="";

if(kvalue.indexOf(',') > -1) {
arr = kvalue.split(',');
for(i=0; i<=arr.length-1; i++) {
if(arr[i].indexOf('/') > -1 && arr[i].indexOf('/') === 0) {
conditionStr+="or" + " (request.path = " + arr[i].toString() + ") "
} else {
conditionStr+="or" + " (apiproxy.name = " + arr[i].toString() + ") "
}
}
} else {
if(kvalue.indexOf('/') > -1 && kvalue.indexOf('/') === 0) {
conditionStr+="or" + " (request.path = " + kvalue.toString() + ") "
} else {
conditionStr+="or" + " (apiproxy.name = " + kvalue.toString() + ")"
}
}
}
context.setVariable("condStr",conditionStr);
print(conditionStr)


I am successfully able to construct the conditional string dynamically as mentioned below and is this possible to use dynamically constructed conditional string in an shared flow default

condStr= (apiproxy.name = apiproxyname1) or (apiproxy.name =apiproxyname2) or (apiproxy.name = apiproxyname3) or (apiproxy.name = apiproxyname4) or (request.path /apiproxyname1/sample/json2xml)

 

sharedflow default xml file content as mentioned below

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SharedFlow name="default">
<Step>
<Name>kvm-policy</Name>
</Step>
<Step>
<Name>KVM-javascript</Name>
</Step>
<Step>
<Name>RaiseFault</Name>
<Condition>condStr</Condition>  this is step is not at all working
</Step>
</SharedFlow>


I have requirement to apply this shared flow on environment level using a flow-hook

I appreciate any help regarding this.

Regards
Nandeesha

Solved Solved
1 1 208
1 ACCEPTED SOLUTION

It is not possible to have a dynamic condition in Apigee DSL.  You cannot do this: 

 

<Step> 
  <Name>RaiseFault-1</Name>
  <Condition>variable-here</Condition> <!-- will not work -->
</Step>

 

Also, there is no ref= attribute on a Condition.  You also cannot do this :

 

<Step> 
  <Name>RaiseFault-1</Name>
  <Condition ref='variable-here'/> <!-- will not work -->
</Step>

 

The condition expression needs to be static, and must follow the syntax outlined in the Condition reference. 

If you want to have a "dynamic condition" then a good way to do it is to use the JavaScript policy, not to construct the string, but to evaluate the value and set a flag. For example

 

var kvalue = context.getVariable("kvm-val");
var result = false;
var requestPath = context.getVariable("request.path");
var proxyName = context.getVariable("apiproxy.name");

// split() will work whether there is a comma or not
kvalue.split(',')
  .forEach(function(item) {
    if ( ! result) {
      if (item.indexOf('/') === 0) {
        result = result || (requestPath === item);
      }
      else {
        result = result || (proxyName === item);
      }
    }
  });

context.setVariable('kvm_rules_matched', String(result)); // "true" or "false"

 

Then use it in a Condition: 

 

  <Condition>kvm_rules_matched = "true"</Condition>

 

If you want to use more functional idioms in your JS you can do this: 

var kvalue = context.getVariable("kvm-val");
var requestPath = context.getVariable("request.path");
var proxyName = context.getVariable("apiproxy.name");
var result =
  kvalue
  .split(',')
  .find(function(item) {
    return ((item.indexOf('/') === 0)  && (requestPath === item)) ||
      ((item.indexOf('/') === -1) && (proxyName === item));
  });

context.setVariable('kvm_rules_matched', String(!!result)); // "true" or "false"

That feels more readable to me, but YMMV.

 

View solution in original post

1 REPLY 1

It is not possible to have a dynamic condition in Apigee DSL.  You cannot do this: 

 

<Step> 
  <Name>RaiseFault-1</Name>
  <Condition>variable-here</Condition> <!-- will not work -->
</Step>

 

Also, there is no ref= attribute on a Condition.  You also cannot do this :

 

<Step> 
  <Name>RaiseFault-1</Name>
  <Condition ref='variable-here'/> <!-- will not work -->
</Step>

 

The condition expression needs to be static, and must follow the syntax outlined in the Condition reference. 

If you want to have a "dynamic condition" then a good way to do it is to use the JavaScript policy, not to construct the string, but to evaluate the value and set a flag. For example

 

var kvalue = context.getVariable("kvm-val");
var result = false;
var requestPath = context.getVariable("request.path");
var proxyName = context.getVariable("apiproxy.name");

// split() will work whether there is a comma or not
kvalue.split(',')
  .forEach(function(item) {
    if ( ! result) {
      if (item.indexOf('/') === 0) {
        result = result || (requestPath === item);
      }
      else {
        result = result || (proxyName === item);
      }
    }
  });

context.setVariable('kvm_rules_matched', String(result)); // "true" or "false"

 

Then use it in a Condition: 

 

  <Condition>kvm_rules_matched = "true"</Condition>

 

If you want to use more functional idioms in your JS you can do this: 

var kvalue = context.getVariable("kvm-val");
var requestPath = context.getVariable("request.path");
var proxyName = context.getVariable("apiproxy.name");
var result =
  kvalue
  .split(',')
  .find(function(item) {
    return ((item.indexOf('/') === 0)  && (requestPath === item)) ||
      ((item.indexOf('/') === -1) && (proxyName === item));
  });

context.setVariable('kvm_rules_matched', String(!!result)); // "true" or "false"

That feels more readable to me, but YMMV.