Error in Integration Studio when calling endpoint that returns a lot of data - wso2

I am trying to call a rest api that returns a maximum of 1000 data in wso2 integration studio and list its results in the script mediator. It does not work when the limit parameter is set to a value close to 1000. I can fetch 500 pieces of data. But I can't fetch more. How can I get this to work when there is too much data?
The error I got:
The script engine returned an Exception executing the external js script : null function mediate java.lang.IllegalArgumentException: out of range index
Here is my sample work:
<resource methods="GET" url-mapping="/GetTotalBuildingCountAndArea">
<inSequence>
<call>
<endpoint>
<http method="get" uri-template="http://localhost/entities?type=Building&limit=800">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<script language="js"><![CDATA[
var buildings = mc.getPayloadJSON();
mc.setPayloadJSON(JSON.stringify(buildings));
]]></script>
<property name="messageType" scope="axis2" type="STRING"
value="application/json"/>
<jsontransform description="Json Convert">
<property name="synapse.commons.json.output.autoPrimitive" value="true"/>
<property name="synapse.commons.enableXmlNullForEmptyElement"
value="false"/>
</jsontransform>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>

This is a limitation of Script Mediator. The documentation has this to say.
The Micro Integrator uses Rhino engine to execute JavaScripts. Rhino
engine converts the script to a method inside a Java class. Therefore,
when processing large JSON data volumes, the code length must be less
than 65536 characters, since the Script mediator converts the payload
into a Java object. However, you can use the following alternative
options to process large JSON data volumes.
Achieve the same functionality via a Class mediator .
If the original message consists of repetitive sections, you can use the Iterate mediator to generate a relatively small payload using
those repetitive sections. This will then allow you to use the Script
mediator.
The Script Mediator supports using Nashorn to execute JavaScripts, in addition to its default Rhino engine.
It's best to handle this in such a way you altogether avoid the issue. But you can try the third option mentioned above as well. In the Script mediator try changing the language to nashornJS.
<script language="nashornJS">
.
.
.

Related

Remove activityid Parameter from response Header in WSO2- API Manager

As you know, by default, WSO2 add a "activityid" Parameter to each response header which would be passed from API-Manager.
Reference:
https://docs.wso2.com/display/EMM210/Getting+Operation+Details+by+the+Activity+ID
For some reason, I need to remove this parameter from the response for client. As I searched, I find out the following link
https://apim.docs.wso2.com/en/4.0.0/deploy-and-publish/deploy-on-gateway/api-gateway/message-mediation/removing-specific-request-headers-from-response/
So I added following code into Main.XML and Fault.XML, However it doesn't work
<property name="activityid" scope="transport" action="remove"/>
I also add the following property to the data flow of a specific API through Integrator Studio. However it doesnt work
<resource methods="POST" uri-template="/attachment">
<inSequence>
<call>
<endpoint key="attachment"/>
</call>
<send/>
</inSequence>
<outSequence>
<property action="remove" name="TRANSPORT_HEADERS" scope="default"/>
<property action="remove" name="activityid" scope="default"/>
</outSequence>
<faultSequence/>
</resource>
Anybody can Give me some advice about this matter??
You can use the message mediation for API Manager. Add the above property mediator to the response path 1 of the API.
Under runtime configurations of the API, there is a message mediation section for both request and response paths. Here you can upload a mediation sequence which will be executed in the request flow as well as response flow. You can save the mediation you need to an xml file and upload the file for the response flow.
1 - https://apim.docs.wso2.com/en/4.0.0/deploy-and-publish/deploy-on-gateway/api-gateway/message-mediation/changing-the-default-mediation-flow-of-api-requests/

How to read a property injected from file.properties in WSO2 - micro integrator?

Is there a way to read the properties from file in wso2 using property mediator?
I'm injecting an address uri from the file.properties, and passing the file path as -Dproperties.file.path argument to the startup script, it is able to resolve the varibale only within the address endpoint's uri attribute using the syntax $FILE:variableName as below:
<call>
<endpoint>
<address uri="$FILE:uploadPath">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
</call>
But I also have the need to use the same property, do a minor transformation and pass it to a class mediator,
I've tried the below approaches and none of them are working.
<log level="custom">
<property expression="$FILE:uploadPath" name="file-path-1"/>
<property expression="$ctx:uploadPath" name="file-path-2"/>
<property expression="$axis2:uploadPath" name="file-path-3"/>
<property expression="$trp:uploadPath" name="file-path-4"/>
<property expression="$axis2:POST_TO_URI" name="POST_TO_URI"/>
</log>
Below are the versions of OS and tools that I'm using.
OS: Mac os catalina,
WSO2: micro-integrator 1.2.0, Integration sutdio - 7.1.0
Some time ago, i was struggling with similar issue, to try using $FILE: in dockered microintegrator . After checking sourcecode i realized that there is no implemented reading in property mediator, and that works only in endpoints... I belive that is because of security reason?
But, there is some workaround, which I'm not a big fan. You could use Property and ScriptMediator:
<property xmlns:ns="http://org.apache.synapse/xsd" name="propPath" expression="get-property('system','properties.file.path')" scope="default" type="STRING"/>
<script language="js"><![CDATA[
var path = java.nio.file.Paths.get(mc.getProperty('propPath'));
var fromFile = java.nio.file.Files.readAllLines(path, java.nio.charset.StandardCharsets.UTF_8);
mc.setProperty('line1',fromFile.get(0).toString());
mc.setProperty('line2',fromFile.get(1).toString());
]]></script>
Of course you got full line, but if you tweak this ScriptMediator, you can have what you want in separate properties.

In wso2 esb how to get a single number(integer) value

In wso2 ESB after calling an endpoint I am getting the response as number(ex: 78) with header application/json, if without processing the response if i send in out sequence it works fine i'll get the same response. But if I include any mediators for processing in between it'll throw exceptions like Could not save JSON payload. Invalid input stream found. A single string or number is not valid in some cases So, it may throwing the exception but this bug is resolved in wso2 EI 6.2.
So now I am able to process the response but if I use script mediator to get that value it shows {}. If i use json-eval($.) then also i am not able to get the value, also with xpath i am not able to get.
So how to get that response(the value in number) for further processing in wso2 ei, by using script mediator or by using json path.
If you are certain that the response only contains a number with the content-type header with application/json. you can take the value to a property as below.
<property name="RESPONSE_NUMBER" expression="//jsonValue" scope="default" type="INTEGER"/>
When you need this value somewhere else in the mediation flow you can take the value from the property(in this case RESPONSE_NUMBER) as below.
$ctx:RESPONSE_NUMBER
Here is a sample API which demonstrates how you can take the response value and use it in the mediation flow.
<api xmlns="http://ws.apache.org/ns/synapse" name="SampleAPI" context="/getNumber">
<resource methods="GET">
<inSequence>
<send>
<endpoint>
<http method="GET" uri-template="http://www.mocky.io/v2/5b02cc2c3000006600cee384"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<property name="RESPONSE_NUMBER" expression="//jsonValue" scope="default" type="INTEGER"/>
<payloadFactory media-type="json">
<format>{"Id": $1}</format>
<args>
<arg evaluator="xml" expression="$ctx:RESPONSE_NUMBER"/>
</args>
</payloadFactory>
<send/>
</outSequence>
</resource>
</api>
You can call the API with below curl command:
curl -v http://localhost:8280/getNumber

WSO2 guaranteed delivery message In memory store

Trying to make workable solution for guaranteed delivery In memory.
Create InMemoryStore InMemMessageStore, create and point InsertInvoice
create API so code looking like this :
Sequence:
<?xml version="1.0" encoding="UTF-8"?> <sequence name="InMMSsequence" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property name="STATE" value="message is sent to InMemMessageStore"/>
</log>
<property name="FORCE_SC_ACCEPTED" scope="axis2" type="STRING" value="True"/>
<axis2ns12:store messageStore="InMemMessageStore" xmlns:axis2ns12="http://ws.apache.org/ns/synapse"/> </sequence>
my API looks like :
<resource methods="POST" uri-template="/sendMessage">
<inSequence>
<sequence key="InMMSsequence"/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
Message Processor :
<messageProcessor name="MySMessageProcessor" class="org.apache.synapse.message.processor.impl.forwarder.ScheduledMessageForwardingProcessor" targetEndpoint="InsertInvoice" messageStore="InMemMessageStore" xmlns="http://ws.apache.org/ns/synapse">
<parameter name="interval">1000</parameter>
<parameter name="client.retry.interval">1000</parameter>
<parameter name="max.delivery.attempts">4</parameter>
<parameter name="is.active">true</parameter>
<parameter name="max.delivery.drop">Disabled</parameter>
<parameter name="member.count">1</parameter>
</messageProcessor>
And point :
<endpoint xmlns="http://ws.apache.org/ns/synapse"
name="InsertInvoice">
<http uri-template="http://xxxx.xxx.xxx.xxx/InsertInvoiceVehicleList"
method="post">
<suspendOnFailure>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
<retryDelay>0</retryDelay>
</markForSuspension> </http> </endpoint>
PROBLEMS:
over PostMan I'm sending the request in JSON format but when I open InMemMessageStore message is in XML ?!? Why?
Endpoint expecting message in JSON format. Probably this is the reason of failure BUT on log I see something like
Failed to send the message through the fault sequence. Sequence name does not Exist.
Is the fault sequence mandatory or it is complaining because I don't have any default error sequence defines at all ?
also
Unable to sendViaPost to url[http://xxx.xxx.xx.xx/InsertInvoiceVehicleList/sendMessage]
Why the 'sendMessage' (This is uritemplate that is defined in API is added on endpoint url ?!?!)
so : Biggest issue here is how to keep message in JSON format and how to keep endpoint url intact ...
I found the problem and I wanted to share it with others ...
1. call end point from API adds postfix on end gives the error
By default, URI template 'sendMessage' will get appended to the target URL when sending messages out. You need to use following property in your sequence to remove URI template from target URL
<property action="remove" name="REST_URL_POSTFIX" scope="axis2"/>.
2. message processor fails to send message to end point
My end point was api .net web service and issue was with HTTP 1.1 chunking,had to disable it since .NET service doesn’t support it.
This setting is in axis2_blocking_client.xml and axis2_client.xml
<parameter name="Transfer-Encoding">chunked</parameter>
3. message processor fails to send message to end point
my seccond End point was servicestack web service and I used end point like
http://xxxx.xxx.xxx.xxx/TMSALSvc/UpdateStatus
but problem was that I needed to specify the reponce format. Once when I put a EndPoint delaration like
http://xxx.xxx.xxx.xx/TMSALSvc/json/reply/UpdateStatus
everything forked
I hope that this can same some times for other facing the same issues

Error with WSO2 ESB when trying to connect to Jira and ElasticSearch

I have and scenario where I want to extract dynamically Issues from Jira in order to save them on ElasticSearch. I use a custom Proxy Service that connect with Jira (via Jira connector), get a project (first I want to save the project's information) and pass this information to Elastic. Following is the in Sequence of the proxy service:
<?xml version="1.0" encoding="UTF-8"?>
<inSequence xmlns="http://ws.apache.org/ns/synapse">
<property expression="json-eval($.username)" name="username"/>
<property expression="json-eval($.password)" name="password"/>
<property expression="json-eval($.uri)" name="uri"/>
<property expression="json-eval($.id)" name="id"/>
<property expression="json-eval($.uriEl)" name="uriEl"/>
<property expression="json-eval($.indexName)" name="indexName"/>
<property expression="json-eval($.type)" name="type"/>
<property expression="json-eval($.message)" name="message"/>
<jira.init>
<username>{$ctx:username}</username>
<password>{$ctx:password}</password>
<uri>{$ctx:uri}</uri>
</jira.init>
<jira.getProject>
<projectIdOrKey>{$ctx:id}</projectIdOrKey>
</jira.getProject>
<property expression="json-eval($.project)" name="project"
scope="default" type="STRING"/>
<elasticsearch.init>
<apiUrl>{$ctx:uriEl}</apiUrl>
</elasticsearch.init>
<elasticsearch.createDocumentWithIndex>
<indexName>{$ctx:indexName}</indexName>
<type>{$ctx:type}</type>
<message>{$ctx:message}</message>
<body>{$ctx:project}</body>
</elasticsearch.createDocumentWithIndex>
<respond/>
</inSequence>
And here is the sample request:
{
"username":"MyName",
"password":"AnStrongPassword",
"uri":"JiraURL",
"id":"MyProject",
"uriEl":"http://localhost:9200",
"indexName":"jira",
"type":"project",
"message":"Testing"
}
The other parameters (Endpoint, out Sequence and Fault Sequence) are by default.
The problem is that when I try to send this request via 'Try the Test service' option on WSO2 ESB, i get the following error:
Error connecting to the Tryit ajax proxy
I have tested the same code but only using the Jira connection (without get a project or connect to Elastic), and the same error occurs.
Looking to this error, I suppose that the problem is before to read the JSON request, but I don't know if it is related to the endpoint (I think that it is not necessary an endpoint for this scenario).
Thanks in advance.
This problem is totally independent of the jira connector etc. Problem is with the "try it" tool. This tool is not that much recommended for testing purposes. Instead of that, try invoking the proxy service via soap ui.
If you share a screenshot when the try it error occurs, I'll be able to comment on that as well.
After a few days I have found another solution to my problem without using proxy services. To connect ESB with Jira, I created this API on ESB:
<api xmlns="http://ws.apache.org/ns/synapse" name="transport_service" context="/transport_service">
<resource methods="GET">
<inSequence>
<jira.init>
<uri>MyURL</uri>
<username>MyUser</username>
<password>3MyPass</password>
</jira.init>
<jira.searchJira>
<query>project=MyProject</query>
<maxResults>50000</maxResults>
<fields>MyField1,MyField2,etc</fields>
</jira.searchJira>
<respond/>
</inSequence>
<outSequence>
<log level="full"/>
<property name="messageType" value="application/xml" scope="axis2"/>
<send/>
</outSequence>
</resource>
</api>
The command to call this API is simple:
curl -v -X GET http://localhost:8280/transport_service > jira-db.json
Finally, if you want to insert this json on elastic, you can follow the typical PUT via curl:
curl -XPUT 'http://localhost:9200/jira/jira/1' -d #jira-db.json
Additionally, you can write both commands on a daily bash script (using your scheduled task list), getting the same result that scheduling your proxy service on WSO2ESB:
#!/bin/bash
curl -v -X GET http://localhost:8280/transport_service > jira-db.json
curl -XPUT 'http://localhost:9200/jira-dev/jira/1' -d #jira-db.json
echo "Daily load completed"