Load flow variables with non-string values in ApiGEE - apigee

I need to save the value of the system variable "system.timestamp" into a flow variable.
(The idea is to obtain the duration of some callout policies in between)
However, I can't read it because the AssignMessage policy raises the fault:
{
"fault": {
"faultstring": "java.lang.Integer cannot be cast to java.lang.String",
"detail": {
"errorcode": "Internal Server Error"
}
}
}
Neither Long nor Integer values can be read, only strings, which is kind of strange because what would be the case of exposing variables one cannot read?
I am trying to avoid the "non elegant" Javascript policy, if that is possible at all, so here's the [very basic] AssignMessage policy I'm using to read the value:
<AssignMessage async="false" continueOnError="false" enabled="true" name="time-test">
<DisplayName>TimeTest</DisplayName>
<AssignVariable>
<Name>myvar</Name>
<Ref>system.timestamp</Ref>
</AssignVariable>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>
system.timestamp variable is documented here:
http://apigee.com/docs/api-services/reference/variables-reference#-a-class-jumplink-name-system-a-system-variables

If the AssignMessage policy doesn't work, you should be able to accomplish this using a JavaScript policy. That would allow you to convert the timestamp to whatever form it needs to be. Similarly, a JavaScript policy could be used to do any timing calculations or manipulations later on in the proxy.

Migs, this is a current limitation of the product. I also use system.timestamp in my code, and I solve this problem with a 1 or 2 line JavaScript policy that creates a new string variable named systemTimestamp. I don't know of a better solution currently.

Related

how to read variable in assign message policy in APIGee

In Apigee
given a variable in javascript policy, example: var value = 123;
how to get this variable in the assign message policy?
by using {a} in the payload message is not reachable
For the variable to be available for use in any Apigee policy, you first have to make it a flow variable. You can use Apigee's JavaScript Object Model method called context to to this (see ref here). In your JS policy, you have var {some-value} = 123;. To make this available as a flow variable,introduce this line in your JS policy after the variable assignment: context.setVariable("preferred-variable-name", some-value);
You can now access this preferred-variable-name in your AM policy as show below:
<AssignVariable>
<Name>preferred-variable-name</Name>
<Ref>preferred-variable-name</Ref>
</AssignVariable>
Just to mention it is possible to pass the value directly in the policy as well as shown below
<AssignVariable>
<Name>variable_name</Name>
<Value>123</Value>
</AssignVariable>
Read more here.
The <Name> tag can be set to any name.
You have to set the variable in the context object using context.setVariable("variable-name", value);
Refer to this variable in the assign_message policy using {variable-name}.
You can just set the context variable in jsPolicy like this:
context.setVariable("a","123");
You can use it after in any of the policies.
Ex :-
<QueryParams>
<QueryParam name="a">{a}</QueryParam>
</QueryParams>

Is there a REST API to get subfolders of the workspace in Tosca?

I am trying to build a UI based in Angular to retrieve all existing execution lists of Tosca. However, I could not find a REST API that can give the list of folders within a workspace in Tosca. Has anyone tried this route?
You can use the Search task on the projectto find all ExecutionLists.
Example:
{rest_url}/ToscaCommander/{workspace_name}/object/project/task/Search
as a post request with the xml payload:
<Parameters xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Parameter>
<Name>tqlString</Name>
<Type i:nil="true"/>
<Value>->SUBPARTS:TCFolder[Name=?"Execution"]=>SUBPARTS:ExecutionList</Value>
</Parameter>
</Parameters>
This will give you a list of object ids of the ExecustionLists contained in the Execution folder of the project. You can fetch the objects one by one with this request afterwards:
{rest_url}/ToscaCommander/{workspace_name}/object/{object_id}
Credits for this solution go to the development team of ToscaCommander - they provided it.
P.S.: as an answer for your comment:
Yes, there is a json equivalent of the body - but you do not need it. Anyway, here is the equivalent:
[{
"Name":"tqlString",
"Value":"->SUBPARTS:TCFolder[Name=?\"Execution\"]=>SUBPARTS:ExecutionList"
}]
If you want to get a json response (regardless of the request's payload's format) make sure your web.config sets AutomaticFormatSelectionEnabled to true (which should be the case). Then, in your requests, set the accept header accordingly:
Accept: application/json

HTTPTargetConnection - why proxy.pathsuffix gets appended to URL

I have created multiple target-end points based on my back-end servers. Each target end point has a fixed URL.
URL is configured as -
<HTTPTargetConnection>
<URL>https://example.com/test/</URL>
</HTTPTargetConnection>
I noticed that "proxy.pathsuffix" is automatically getting added to url (https://example.com/test/). How can I avoid this?
A bit outdated in reply - but, Assign Message works for this (to avoid JavaScript):
<AssignVariable>
<Name>target.copy.pathsuffix</Name>
<Value>false</Value>
</AssignVariable>
You'll need to create a new JavaScript callout policy in your proxy request flow. In this JavaScript callout, simply add a single line:
context.setVariable("target.copy.pathsuffix", false);

I have a requirement to make calls to two different end points in a sequence on a given call

I am trying to achieve the functionality where i have to call two different backends / target endpoints that have completely different interface in a sequence. Output of one call becomes input to the second one upon an error condition from the first call.
I would like to know how to implement this. I am new to Apigee so details will help me.
It sounds like you need to do a ServiceCallout in the request flow.
Set up your Target as whatever the second server is that you need to talk to in the normal flow. Then create a policy to callout to your first target:
<ServiceCallout name="myPolicy">
<Request clearPayload="false" variable="myRequest"/>
<Response>myResponse</Response>
<HTTPTargetConnection>
<Properties/>
<URL>http://example.com</URL>
</HTTPTargetConnection>
</ServiceCallout>
Note the Response block puts the headers and payload from the response into an object that you can then extract variables from using "myResponse" as the <Source> in the ExtractVariables policy.
Then you can build a new request for your target with the variables you set in the ExtractVariables by using an AssignMessage policy
Service Callout
http://apigee.com/docs/api-services/content/call-services-or-apis-using-servicecallout
ExtractVariables
http://apigee.com/docs/api-services/content/extract-message-content-using-extractvariables
AssignMessage
http://apigee.com/docs/api-services/content/generate-or-modify-messages-using-assignmessage

Working around the wildcard limitation in defining hierarchical APIs

Suppose I want to create the following APIs:
/movies/{movieId}/cast
/movies/{movieId}/crew
/movies/{movieId}/awards
On the recent versions of Apigee, wildcards are no longer allowed in the base URL. To achieve the ones above, we first created an API proxy /movies. We then defined three separate resources under it, each starting with a wildcard:
/*/cast
/*/crew
/*/awards
Here's a couple of questions:
Is this the only way to define wildcards in a hierarchical API structure?
Is there a way to define these into 3 separate API proxies?
Say you created an API with the basepath /movies and then consume /movies/jaws/cast. You can then crate a PreFlow policy to extract the path variable like this:
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-URI">
<DisplayName>Extract URI</DisplayName>
<FaultRules/>
<Properties/>
<URIPath>
<Pattern>/{movieid}/{function}</Pattern>
</URIPath>
</ExtractVariables>
You now have two variables, one for the variable and one for the actual service. Now you can create a Conditional Flow for each function (cast, crew, awards...) on the variable function rather than matching the path:
<Flow name="Cast">
<Description/>
<Request/>
<Response>
<Step>
<FaultRules/>
<Name>Assign-cast</Name>
</Step>
</Response>
<Condition>(function = "cast") and (request.verb = "GET")</Condition>
</Flow>
You may still need to do some magic to rewrite your target path, but your request proxy path will still be /jaws/cast but now you can run specific policies against a request for the cast of Jaws.
See http://apigee.com/docs/api-services/api/conditions-reference and http://apigee.com/docs/gateway-services/content/flow-variables-and-conditions for more info on Conditional Flow configuration.

Resources