wso2 esb iterate mediator thread safe? - wso2

I have below iterate Seq,
<iterate attachPath="//Test"
expression="///Test" preservePayload="true">
<target>
<sequence>
<header name="Action" scope="default" value="action1"/>
<send>endpoint 1</send>
</sequence>
</target>
<target>
<sequence>
<header name="Action" scope="default" value="action2"/>
<send>endpoint 2</send>
</sequence>
</target>
</iterate>
so does the "Action" is thread safe in each iterate target\seq.
if so, in"aggregate", can i access the property/header inside the target\seq?

I am not sure whether its thread safe. But to workaround your doubt, I think the following information would help.
There is a property called "Sequential Mediation" in the iterate mediator. If it is set to true, it will process the iterated messaged sequentially. See the following documentation.
https://docs.wso2.com/display/ESB490/Iterate+Mediator

Related

How to call blocking mediator results to out sequence

I am having a problem with call blocking mediator in a WSO2 Esb proxy service.And i'm currently using wso2 4.9.0.
I am going to call multiple WSO2 ESB Sequence mediator using under the call mediator (using filter statement). This will loop by following XML tag format. Based on the results. I need to call out sequence according to this xml tag value.
Here is my In Sequence:
<call blocking="true">
<endpoint key="CommonEPR"/>
</call>
<filter regex="02" source="json-eval($.responsecode) xmlns:ns="http://org.apache.synapse/xsd">
<then>
<log level="full">
<property
name="CALLCommonAPI" value="MESSAGE"/>
</log>
<sequence name="CommonOutSequence">
<log/>
<out>
<sequence key="CommonOutSequence"/>
<send/>
</out>
</sequence>
</then>
</filter>
What i need is send to results to CommonOutSequence, yes i know its not possible in call mediator send to out sequence.can any one tell me possible way to send out Sequence using call mediator.
I'm not really clear about your requirement, but if you want to move to the outflow at some point, you can call the <loopback/> mediator[1].
Updated as per the 1st comment:
Doesn't this work?
<filter regex="02" source="json-eval($.responsecode) xmlns:ns="http://org.apache.synapse/xsd">
<then>
<log level="full">
<property name="CALLCommonAPI" value="MESSAGE"/>
</log>
<sequence key="CommonOutSequence"/>
<respond/>
</then>
</filter>
[1] https://docs.wso2.com/display/ESB490/Loopback+Mediator

What is the best way to iterate inside WSO2 EI?

After reading of WSO2 EI References, I still confuse about how use iterators inside a EI sequence.
In my case I have a payload like this....
{
...
"array": [
{"cpf": "12345678911"},
{"cnpj":"12345678912346"}
]
}
So I have to iterate to check if those guys exist using another web services. in order to achieve that flow, I am using the iterate mediator to split the message and then building the logic to make those validations as follows..
The code that implements this image is following:
<iterate description="" expression="//jsonObject/array" id="myid">
<target>
<sequence>
<property expression="json-eval($.array.cpf)" name="tipoCPF" scope="default" type="STRING"/>
<filter description="" xpath="boolean(get-property('tipoCPF'))">
<then>
<property expression="json-eval($.array.cpf)" name="uri.var.cpf" scope="default" type="STRING"/>
<call>
<endpoint>
<http method="get" uri-template="http://endpoint/service/{uri.var.cpf}"/>
</endpoint>
</call>
<filter regex="200" source="get-property('axis2','HTTP_SC')">
<then/>
<else>
<payloadFactory description="" media-type="json">
<format>{
"code":"400",
"error":"CPF inexistente"
}</format>
<args/>
</payloadFactory>
<property name="HTTP_SC" scope="axis2" type="STRING" value="400"/>
<respond/>
</else>
</filter>
</then>
<else>
<property expression="json-eval($.array.cnpj)" name="tipoCNPJ" scope="default" type="STRING"/>
<filter xpath="boolean(get-property('tipoCNPJ'))">
<then>
<property expression="json-eval($.array.cnpj)" name="uri.var.cnpj" scope="default" type="STRING"/>
<header name="Authorization" scope="transport" value="Basic Y29yZS5jb25zdWx0aW5nOm8xNXRyZWI="/>
<call>
<endpoint>
<http method="get" uri-template="http://endpoint/service/cnpj/{uri.var.cnpj}"/>
</endpoint>
</call>
<filter regex="200" source="get-property('axis2','HTTP_SC')">
<then/>
<else>
<payloadFactory media-type="json">
<format>{
"code":"400",
"error":"CNPJ inexistente"
}</format>
<args/>
</payloadFactory>
<property name="HTTP_SC" scope="axis2" type="STRING" value="400"/>
<respond/>
</else>
</filter>
</then>
<else>
<call>
<endpoint>
<http method="get" uri-template="http://endpoint/service/info"/>
</endpoint>
</call>
</else>
</filter>
</else>
</filter>
</sequence>
</target>
</iterate>
This iterator work as part inside of the an 'insequence'. The 'Insequence' is deigned to allow to insert new contracts information inside the Database.
Problem: after add this iterator, the service starts to make duplicated insertions inside Database. It´s looks like the iteration don´t finish in the edge of tags 'iterator'. It´s like the iteration continues to the rest of insequence.
Try: In order to solve this problem i try to add an aggregator mediator after the iterator. But or doesn't have any effect end the duplicated insert persist, or I receive an error message.
So What is the correct whey to make this iterations inside WSO2 EI?
As you have mentioned, Iteration will occur even outside the iterate tag, until the Aggregate mediator is used. To resolve this issue, you need to add the aggregate mediator inside the iterate mediator. This will stop the iteration within the iterator tag itself.
For your use case, you may need to set continueParent="true" in the IterateMediator, so that the mediation will continue after the iterate mediator for the insertion Operation in database.
Thanks for the helping Arunan!
After your answer I try to add the Aggregator as follows
The config of aggregator is following:
...
<aggregate id="NIRO">
<completeCondition>
<messageCount max="-1" min="-1"/>
</completeCondition>
<onComplete expression="//jsonObject">
<log description="" level="full" separator=";">
<property expression="json-eval($.)" name="jsonObject"/>
</log>
</onComplete>
</aggregate>
</sequence>
</target>
</iterate>
As you sad I change the iterator property 'Continue Parent' to 'true'. But the problem persists....
As proposed in the other answer, you need to
use an Aggregate mediator to close the iteration
If and only if the Iterator is set to continueParent="true"
However, I am not sure that putting it inside the <iterate> works. Here is a working solution using an Aggregate mediator right after your Iterator.
<sequence>
<iterate continueParent="true" description="" expression="//jsonObject/array" id="myid">
<target>
<your_sequence />
</target>
</iterate>
<aggregate>
<completeCondition>
<messageCount max="-1" min="-1" />
</completeCondition>
<onComplete enclosingElementProperty="//jsonObject/array" expression="/whatever/you/want"/>
</aggregate>
</sequence>
Notice expression="//jsonObject/array" you used in your Iteration, you'll need to use it in the Aggregator's enclosingElementProperty. This is how your EI will know from which iterator it should aggregate from (not 100% sure about this point, more of an empirical consideration).

WSO2 JSON Array Processing

I have a json array (see below) which is logged in my wso2 sequence.
Payload: [{"id":"346","sys":"8","name":"A bldg"},{"id":"345","sys":"8","name":"bbldg 3"}
}]
Now I want to iterate the array. How do I do that? I want to log name for each row for now. I tried few options but it is not working, any help appreciated!.
My sequence looks like this:
<sequence name="a3" trace="enable" xmlns="http://ws.apache.org/ns/synapse">
<property expression="json-eval($.payload)" name="array"
scope="default" type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<foreach expression="//array/*" sequence="" xmlns:ns="http://org.apache.synapse/xsd"/>
<respond/>
</sequence>
As you have a JSON input so when it comes inside an ESB the format is changed to xml by default, so as i see that the json input is [{"id":"346","sys":"8","name":"A bldg"},{"id":"345","sys":"8","name":"bbldg 3"} }] , ESB will add a root element while converting it into XML.
Now you can use an XSLT to fetch the name or you can use an iterate mediator, which ever suits you best.
Don't take the payload to a property instead directly iterate as below,
<foreach expression="//payload">
<sequence>
<log>
<property expression="//name" name="name" scope="default" type="STRING"/>
</log>
</sequence>
</foreach>

why call is not working in wso2 esb

I have a problem with wso2 esb.
I wrote a proxy and in that I call an endpoint to do some changes on original input. but the log before call and after call is the same(it should be different). It seems the call is not working at all.when I send respone to outsequence it is null. Can any one say why this happen? (I have tested my endpoint in soupUI)
this is my proxy:
<inSequence>
<property name="transport.vfs.ReplyFileName" value="GET" scope="transport"/>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<smooks config-key="smooks-csv1">
<input type="text"/>
<output type="xml"/>
</smooks>
<iterate continueParent="true"
preservePayload="true"
attachPath="//csv-set"
expression="//csv-set/search"
sequential="true">
<target>
<sequence>
<xslt key="gov:/first.xsl"/>
<xslt key="gov:/second.xsl"/>
**<log level="full"/>
<call blocking="true">
<endpoint>
<address uri="MyEndPiont"/>
</endpoint>
</call>
<log level="full"/>**
</sequence>
</target>
</iterate>
<respond/>
</inSequence>
<outSequence>
<aggregate>
<completeCondition>
<messageCount min="0" max="100"/>
</completeCondition>
<onComplete expression="//Guest">
</onComplete>
</aggregate>
</outSequence>
Try this. List of changes:
Removed respond mediator.
Replaced call by send.
Added send in out sequence.
<inSequence>
<property name="transport.vfs.ReplyFileName" value="GET" scope="transport"/>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<smooks config-key="smooks-csv1">
<input type="text"/>
<output type="xml"/>
</smooks>
<iterate continueParent="true"
preservePayload="true"
attachPath="//csv-set"
expression="//csv-set/search"
sequential="true">
<target>
<sequence>
<xslt key="gov:/first.xsl"/>
<xslt key="gov:/second.xsl"/>
<log level="full"/>
<send>
<endpoint>
<address uri="MyEndPiont"/>
</endpoint>
</send>
</sequence>
</target>
</iterate>
</inSequence>
<outSequence>
<aggregate>
<completeCondition>
<messageCount min="0" max="100"/>
</completeCondition>
<onComplete expression="//Guest">
</onComplete>
</aggregate>
<send />
</outSequence>
Try blocking="false". Please note that making this change does not make the call mediator is asynchonus. It's synchronous regardless of whether blocking is true or false. Blocking is just an implementation detail.
The Call mediator is used to send messages out of the ESB to an
endpoint. You can invoke services either in blocking or non-blocking
manner.
When you invoke a service in non-blocking mode, the underlying worker
thread returns without waiting for the response. In blocking mode, the
underlying worker thread gets blocked and waits for the response after
sending the request to the endpoint. Call mediator in blocking mode is
very much similar to the Callout mediator.
In both blocking and non-blocking modes, Call mediator behaves in a
synchronous manner. Hence, mediation pauses after the service
invocation and resumes from the next mediator in the sequence when the
response is received. Call mediator allows you to create your
configuration independent from the underlying architecture.
Quoted from https://docs.wso2.com/display/ESB500/Call+Mediator

WSO2 ESB - Iterator / Loop

Is it possible to Iterate through the elements of the xml file and call the sequence for each iteration without a send mediator within the Iterator. [Similar to Iterator Mediator without Send Mediator within it]
XML File:
<?xml version="1.0" encoding="UTF-8"?><Files><File>testValue1</File><File>testValue2</File></Files>
Expected Iterator:
<iterate xmlns:ns="http://org.apache.synapse/xsd" expression="$ctx:test//File" id="UTMIterator" sequential="true">
<target>
<sequence>
<property name="InsideSeq1" expression="//File"></property>
<class name="samples.mediators.SimpleClassMediator">
<property name="varible1" expression="$ctx:InsideSeq1"/>
</class>
<log level="custom">
<property name="text" value="***** Inside Iterator *****"></property>
</log>
</sequence>
</target>
</iterate>
Sample:
<iterate xmlns:ns="org.apache.synapse/xsd"; expression="$ctx:test//File" id="UTMIterator" sequential="true">
<target>
<sequence>
<log level="custom">
<property name="text" value="***** Inside Iterator **"></property>
<property name="InsideSeq1" expression="//File"></property>
<property name="text" value="** Inside Iterator *****"></property>
</log>
</sequence>
</target>
</iterate>
Note: Iterating the xml without the send mediator.
Any suggestion?
Yes you can. It is not a must to have send mediator.