Unable to get pass iterate mediator in wso2 - api

I am writing an iterate mediator, the code is going in the sequence written in that iterate mediator, it is completing too (read through logs) however, it is not going to next step. Please help me with what wrong am I doing.
<iterate expression="//mpesa/prov">
<target>
<sequence>
<sequence key="ProvMapperQueue"/>
</sequence>
</target>
</iterate>
<log level="custom">
<property name="After" value="Sequence"/>
</log>
It is now printing the logs neither is API getting a response, its stuck after sequence last line is logged.
For further information copying the sequence below too:
<sequence name="ProvMapperQueue" onError="ProvMapperQueue_Error" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="ProvMapperQueue Sequence" value="Started"/>
</log>
<property name="messageType" scope="axis2" type="STRING" value="text/xml"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<call>
<endpoint key="OBD_EP"/>
</call>
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="After Calling" value=" ProvMapperQueue EP"/>
<property name="ProvMapperQueue Sequence" value="Ended"/>
</log>
<respond/>
</sequence>
Logs printing are below :
[2023-01-24 00:14:07,883] INFO {LogMediator} - {api:OBD} Msisdn = 110000171, ProvMapperQueue Sequence = Started
[2023-01-24 00:14:07,893] INFO {TimeoutHandler} - This engine will expire all callbacks after GLOBAL_TIMEOUT: 120 seconds, irrespective of the timeout action, after the specified or optional timeout
[2023-01-24 00:14:08,181] INFO {LogMediator} - {api:OBD} Msisdn = 110000171, After Calling = ProvMapperQueue EP, ProvMapperQueue Sequence = Ended
[2023-01-24 00:17:06,839] INFO {SourceHandler} - Writer null when calling informWriterError
[2023-01-24 00:17:06,841] WARN {SourceHandler} - STATE_DESCRIPTION = Socket Timeout occurred after accepting the request headers and the request body, INTERNAL_STATE = REQUEST_DONE, DIRECTION = REQUEST, CAUSE_OF_ERROR = Connection between the client and the EI timeouts, HTTP_URL = /obd/prov/msisdn/110000171, HTTP_METHOD = GET, SOCKET_TIMEOUT = 180000, CLIENT_ADDRESS = /127.0.0.1:59198, CONNECTION http-incoming-4
Any help would mean a lot.

I think the problem is with the <respond/> mediator that you have added towards the end of the ProvMapperQueue sequence. This will stop further processing of a message and send the message back to the client[1]. That means, after it, the rest of the sequence logic will not be executed including the log mediator outside the iterate mediator.
[1] - https://docs.wso2.com/display/EI611/Respond+Mediator

Few issues with your integration. You need to remove the respond mediator from the Iterate sequence, as responding per iteration doesn't make sense. So, I believe what you need is to iterate over the entries and once done, respond back to the client. In order to wait for all the Iterations to finish you need to couple the iterate mediator with an aggregate mediator. Hence update the sequences like below.
<sequence name="ProvMapperQueue" onError="ProvMapperQueue_Error" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="ProvMapperQueue Sequence" value="Started"/>
</log>
<property name="messageType" scope="axis2" type="STRING" value="text/xml"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<call>
<endpoint key="OBD_EP"/>
</call>
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="After Calling" value=" ProvMapperQueue EP"/>
<property name="ProvMapperQueue Sequence" value="Ended"/>
</log>
</sequence>
<iterate expression="//mpesa/prov" id="iterateid">
<target>
<sequence>
<sequence key="ProvMapperQueue"/>
</sequence>
</target>
</iterate>
<aggregate id="iterateid">
<completeCondition>
<messageCount max="-1" min="-1"/>
</completeCondition>
<onComplete expression="$body/*[1]">
<payloadFactory media-type="xml">
<format>
<payload xmlns="">
<response>Done</response>
</payload>
</format>
<args/>
</payloadFactory>
<respond/>
</onComplete>
</aggregate>
Update
The issue is you have set the OUT_ONLY property in your sequence hence the aggregate is never completed since callbacks are not registered. Instead of Iterate Mediator use the Foreach Mediator for your usecase. Check the example below.
<foreach expression="//mpesa/prov">
<sequence>
<sequence key="ProvMapperQueue"/>
</sequence>
</foreach>
<log level="custom">
<property name="After" value="Sequence"/>
</log>
<payloadFactory media-type="xml">
<format>
<payload xmlns="">
<response>Done</response>
</payload>
</format>
<args/>
</payloadFactory>
<respond/>

Related

wso2 ei 6.5 SOAP Client and REST Service The parameter received is XML Rest need to json

<proxy xmlns="http://ws.apache.org/ns/synapse"
name="ctc"
startOnLoad="true"
statistics="enable"
trace="disable"
transports="http,https">
<target>
<inSequence>
<log>
<property name="******" value="---ctc---"/>
</log>
<property xmlns:saop="http://j2ee.netbeans.org/wsdl/EsbJyBpel/src/saopWSDL"
expression="$body//saop:upload/xml"
name="request_msg"/>
<log>
<property expression="json-eval($)" name="request_msg"/>
</log>
<property name="messageType"
scope="axis2"
type="STRING"
value="application/json"/>
<script language="js">mc.setPayloadJSON(
{
"Code" : "10",
"Price" : "11"
});</script>
<property name="HTTP_METHOD" scope="axis2" value="POST"/>
<property name="messageType"
scope="axis2"
type="STRING"
value="application/json"/>
<property name="Content-Type"
value="application/json"
scope="transport"
type="STRING"/>
<send>
<endpoint>
<address format="pox" uri="http://192.16.110.142:8081/dqcsweb/ES/test"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<log>
<property expression="json-eval($)" name="res_msg"/>
</log>
<send/>
</outSequence>
</target>
</proxy>
The XML structure that the restful service log prints;
How do You convert an XML structure to JSON?
I used script and payloadFactory, output the JSON string in the ESB, and the print log in the invoked service is still XML
input:
enter image description here
The message received by the service(http://192.16.110.142:8081/dqcsweb/ES/test):
<jsonObject><Code>10</Code><Price>11</Price></jsonObject>
expectations:
{
"code":"10",
"Price":"11"
}
Can you change the format of the endpoint invoked to rest. Please refer to the follwoing sample configuration.
<send>
<endpoint>
<address format="rest" uri="http://192.16.110.142:8081/dqcsweb/ES/test"/>
</endpoint>
</send>
The used pox format results in the message transformed into plain old XML format. Please refer to the documentation [1] to further clarify this.
[1]-https://docs.wso2.com/display/EI611/Address+Endpoint
Update
Can you enable wire logs by uncommenting the following [2] in log4j.properties file. You need to perform a server restart to enable this. This allows you to see the request sent out of the EI server. Please check if the request going out of the EI contains the necessary payload.
log4j.logger.org.apache.synapse.transport.http.wire=DEBUG
[2]-https://docs.wso2.com/display/ESB500/Debugging+Mediation#DebuggingMediation-Viewingwirelogs

To Fetch elements from enclosingElementProperty of aggregation in WSO2 ESB/EI

I am performing Iterate and Aggregation operation in wso2 EI. i want to fetch element values from aggregation response, OUTSEQUENCE log not printed after aggregation.Can anyone please help me to find this solution?
ProxyCode:
<proxy name="VBReadFromEmailBody" startOnLoad="true" transports="http https" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<iterate expression="//jsonArray/jsonElement" id="LDVid" sequential="true">
<target>
<sequence>
<sequence description="VBEmail_LDVNonQualifiedLead_Sequence" key="VBEmail_LDVNonQualifiedLead_Sequence"/>
</sequence>
</target>
</iterate>
<property name="Aggregated_Responses" scope="default">
<jsonObject/>
</property>
<aggregate id="LDVid">
<completeCondition>
<messageCount max="-1" min="-1"/>
</completeCondition>
<onComplete enclosingElementProperty="Aggregated_Responses" expression="$body/*[1]" xmlns:ns="http://org.apache.synapse/xsd">
<log level="full"/>
<loopback/>
</onComplete>
</aggregate>
</case>
<default/>
</switch>
</inSequence>
<outSequence>
<log level="custom">
<property name="======OUTSEQUENCE=======" value="CALLED"/>
</log>
<log level="full"/>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<foreach expression="//jsonValue" id="foreach_id">
<sequence>
<log level="custom">
<property expression="json-eval($.)" name="====each payload===="/>
</log>
<script language="js"><![CDATA[var log = mc.getServiceLog();
payload = mc.getPayloadJSON().toString();log.info("Logging payload;;;;" + payload); payloadRemoveSlash = payload.replace("\\", ""); mc.setProperty('payloadRemoveSlash',payloadRemoveSlash);]]></script>
</sequence>
</foreach>
<!--
DB Tracing (Response values stored in DB)-->
</outSequence>
</target>
</proxy>
Aggregated Response:
[2020-04-25 14:39:42,741] [] INFO - LogMediator To: http://www.w3.org/2005/08/addressing/anonymous, WSAction: , SOAPAction: , MessageID: urn:uuid:516c93bf-fb2d-46af-8cc8-2b3e56a5e
7ef, Direction: response, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><jsonObject><jso
nValue>"{\"transactionId\":null,\"timestamp\":\"2020-04-25 19:09:41\",\"OpportunityId\":\"0065500000FyUJOAA3\",\"message\":\"Insert/Update success\",\"Lead\":{\"attributes\":{\"typ
e\":\"Lead\",\"url\":\"/services/data/v48.0/sobjects/Lead/00Q5500000AuBvGEAV\"},\"Company\":\"N/A\",\"Email\":\"jaxonstevens18#gmail.com\",\"Lead_Type__c\":\"Internet\",\"LeadSourc
e\":\"LDV i-Motor - Get a Quote\",\"FirstName\":\"Jaxon\",\"Account__c\":\"0015500000k8ow5AAA\",\"LastName\":\"Stevens\",\"Contact__c\":\"0035500000h2R5yAAE\",\"Id\":\"00Q5500000Au
BvGEAV\",\"MobilePhone\":\"+61 423 927 100\"},\"errorCode\":\"200\",\"appraisalId\":null}"</jsonValue><jsonValue>"{\"transactionId\":null,\"timestamp\":\"2020-04-25 19:09:42\",\"Op
portunityId\":\"0065500000FyUJYAA3\",\"message\":\"Insert/Update success\",\"Lead\":{\"attributes\":{\"type\":\"Lead\",\"url\":\"/services/data/v48.0/sobjects/Lead/00Q5500000AuBvLE
AV\"},\"Company\":\"N/A\",\"Email\":\"steveross01#bigpond.com\",\"Lead_Type__c\":\"Internet\",\"LeadSource\":\"LDV Facebook - Book a Test Drive\",\"FirstName\":\"Stephen\",\"Accoun
t__c\":\"0015500000k8opxAAA\",\"LastName\":\"Ross\",\"Contact__c\":\"0035500000h2R1wAAE\",\"Id\":\"00Q5500000AuBvLEAV\",\"MobilePhone\":\"+61 414 404 774\"},\"errorCode\":\"200\",\
"appraisalId\":null}"</jsonValue><jsonValue>"{\"transactionId\":null,\"timestamp\":\"2020-04-25 19:09:42\",\"OpportunityId\":\"0065500000FyUJTAA3\",\"message\":\"Insert/Update succ
ess\",\"Lead\":{\"attributes\":{\"type\":\"Lead\",\"url\":\"/services/data/v48.0/sobjects/Lead/00Q5500000AuBvQEAV\"},\"Company\":\"N/A\",\"Email\":\"dunleavy2010#hotmail.com\",\"Le
ad_Type__c\":\"Internet\",\"LeadSource\":\"LDV i-Motor - Get a Quote\",\"FirstName\":\"Brendan\",\"Account__c\":\"0015500000k8oVhAAI\",\"LastName\":\"Dunleavy\",\"Contact__c\":\"00
35500000h2Ql6AAE\",\"Id\":\"00Q5500000AuBvQEAV\",\"MobilePhone\":\"+61 449 819 834\"},\"errorCode\":\"200\",\"appraisalId\":null}"</jsonValue></jsonObject></soapenv:Body></soapenv:
Envelope>
Instead of using <send/> inside OnComplete, try using <loopback/>. It might resolve the issue.

How to trigger an error in a WSO2 sequence?

I would like to create a input sequence where I check a param with a switch mediator. If the value of the param does not correspond to a specific string, then an error should be thrown and move the flow in the Fault sequence.
For example, I created this sequence:
<sequence name="testEquivalence" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<switch source="$ctx:uri.var.myParam">
<case regex="hello">
<log description="DISPLAY" level="full">
<property name="value" value="RIGHT VALUE FOR THE PARAM myParam"/>
</case>
<default>
<log description="FAULT" level="full">
<property name="FAULT" value="WRONG VALUE FOR THE PARAM myParam"/>
</log>
<makefault version="pox">
<reason value="Wrong value"/>
<detail expression="'Wrong value. Try with hello.'"/>
</makefault>
</default>
</switch>
</sequence>
As you can see, I want to display a log saying "RIGHT VALUE FOR THE PARAM myParam" if it is OK. Or, I would like to display a log and then stop the process in the default part to pass in the Fault sequence.
However, I created a makefault mediator to "modelize" my fault but is it possible to replace it by something more... executive to stop the process and redirect the flow in the Fault sequence like if an exception was thrown?
There is no way to throw an exception in WSO2 ESB/EI. Generally after creating a SOAPFault you want to return this to the caller of the service. A Solution is to use the Response Mediator after the Fault mediator:
<sequence name="testEquivalence" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<switch source="$ctx:uri.var.myParam">
<case regex="hello">
<log description="DISPLAY" level="full">
<property name="value" value="RIGHT VALUE FOR THE PARAM myParam"/>
</case>
<default>
<log description="FAULT" level="full">
<property name="FAULT" value="WRONG VALUE FOR THE PARAM myParam"/>
</log>
<makefault version="pox">
<reason value="Wrong value"/>
<detail expression="'Wrong value. Try with hello.'"/>
</makefault>
<respond/>
</default>
</switch>
</sequence>

how to get the response of the rest api and pass that response to another service in wso2 esb?

<resource methods="GET" uri-template="/getTypeCodes" faultSequence="service_error_handler_">
<inSequence>
<log level="custom">
<property name="CommonService" value="*************getTypeCodes called**************"/>
<property name="Request Payload" expression="get-property('JSON_OBJECT')"/>
</log>
<property name="HTTP_METHOD" value="GET" scope="axis2" type="STRING"/>
<property name="messageType" value="application/json" scope="axis2" type="STRING"/>
<sequence key="oauthMediationService"/>
<property name="uri.var.servicename" value="commonservice"/>
<send>
<endpoint>
<address uri="http://localhost:8080/rest/commonservice/getTypeCodes" format="rest"/>
</endpoint>
</send>
<log level="custom">
<property name="getTypeCodeResponse" expression="$body"/>
</log>
</inSequence>
<outSequence>
<send/>
</outSequence>
From the above rest example configuration i am calling the service in endpoint. After calling the endpoint i need to get the response and send that response to the the another endpoint based on condition.
You can use following configuration to call to reset service and get a response. In below sample I'm using HTTP endpoint
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="peoplePutProxy"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<property name="HTTP_METHOD" value="GET" scope="axis2"/>
<property name="messageType"
value="application/x-www-form-urlencoded"
scope="axis2"/>
<send>
<endpoint>
<http method="post"
uri-template="http://localhost:8080/rest/api/people?email={uri.var.email}&firstName={uri.var.fname}&lastName={uri.var.lname}"/>
<property name="uri.var.fname" value="dhar"/>
<property name="uri.var.email" value="kasun#gmail.com"/>
<property name="uri.var.lname" value="kasun"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full"/>
<property name="messageType" value="text/xml" scope="axis2"/>
<send/>
</outSequence>
</target>
<description/>
</proxy>
Http end point is where users can specify an URI Template which can dynamically populate final URI for the RESTful service invocation. Also, users can manipulate HTTP method of the outgoing request.
Please refer [1] for more information on http endpoint
[1]. http://docs.wso2.org/display/ESB470/HTTP+Endpoint
Your requirement is called 'Service Chaining'. This blog post explains how to achieve service chaining in WSO2 ESB. Go through the other article linked at the start of that blog to get a better understanding. They provide a complete example of service chaining.
Basically you can specify a sequence as the receiver of the response in a send mediator as follows.
<send receive="RespSequence">
<endpoint>
<address uri="http://localhost:8080/rest/commonservice/getTypeCodes" format="rest"/>
</endpoint>
</send>
In this case the response from calling the endpoint will be directed to RespSequence. So in that sequence you can specify the other endpoint.Refer Send Mediator doc for more info. Use Switch Mediator to check for conditions.

WSO2 ESB Store and Forward Processor not obeying endpoint message format

We have been testing the message processors and queues on wso2 esb. We have been using the sampling processor quite successfully to just log data to a DB. This POX end to end. The sampling processor correctly dequeues a message and sends it to the endpoint. The endpoint is defined as POX and non-chunked, and all this works well.
We decided to try the store and forward processor as we wanted to test out the guaranteed delivery mechanism. So we created a new processor and defined it as store and forward. In the main sequence that stores the message, we added the target.endpoint property before storing the message. The property was set to the same endpoint that was being used in the sampling scenario.
However - what have found is that in this mode, the message transformation does not happen correctly. The content type is set to text/html and the output is chunked. This causes our service to return a 415 error.
We have tried adding messageType, contentType etc to multiple place, to the axis http sender transport, etc, but it seems to make no difference at all.
Any guidance on this would be appreciated
Define the following property in the sequence before sending to the endpoint
<property name="DISABLE_CHUNKING" value="true" scope="axis2"/>
The JS code below simply inserts the messageID into the return payload to the caller. Using this with a sampling processor and sequence that simply sends to the same endpoint works fine.
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
<registry provider="org.wso2.carbon.mediation.registry.WSO2Registry">
<parameter name="cachableDuration">15000</parameter>
</registry>
<endpoint name="test_e">
<address uri="http://192.168.45.168:8080/cgi-bin/esbcgi.pl" format="pox"/>
<property name="DISABLE_CHUNKING" value="true" scope="axis2"/>
</endpoint>
<sequence name="fault" trace="enable">
<log level="full">
<property name="MESSAGE" value="Executing default 'fault' sequence"/>
<property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
<property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
</log>
<drop/>
</sequence>
<sequence name="main" onError="fault" trace="enable">
<in>
<log level="full"/>
<property name="OUT_ONLY" value="true"/>
<property name="FORCE_HTTP_1.0" value="true" scope="axis2"/>
<script language="js">
var message = mc.getMessageID();
var messageId = message.substring(9,45);
var payload = mc.getPayloadXML().*;
mc.setPayloadXML(
<payload> <messageId>{messageId}</messageId>{payload}
</payload>);
</script>
<switch xmlns:ns="http://org.apache.synapse/xsd" xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:ns3="http://org.apache.synapse/xsd" source="get-property('To')">
<case regex=".*/TEST/.*">
<property name="target.endpoint" value="test_e" scope="default"/>
<store messageStore="TEST"/>
</case>
<default/>
</switch>
<property name="OUT_ONLY" value="false"/>
<script language="js">var serviceMessageId = mc.getMessageID();
mc.setPayloadXML(
<tag xmlns="http://tagcmd.com">
<messageId>{serviceMessageId}</messageId> </tag>);
</script>
<send>
<endpoint key="MessageService"/>
</send>
</in>
<out>
<script language="js">
var messagePayload= mc.getPayloadXML().*.*;
mc.setPayloadXML(
<eventResponse> <messageId>{messagePayload}</messageId> </eventResponse>);
</script>
<send/>
</out>
<description>The main sequence for the message mediation</description>
</sequence>
<messageStore class="org.wso2.carbon.message.store.persistence.jms.JMSMessageStore" name="TEST">
<parameter name="java.naming.factory.initial">org.apache.qpid.jndi.PropertiesFileInitialContextFactory</parameter>
<parameter name="java.naming.provider.url">repository/conf/jndi.properties</parameter>
<parameter name="store.jms.destination">APP8</parameter>
</messageStore>
<messageProcessor class="org.apache.synapse.message.processors.forward.ScheduledMessageForwardingProcessor" name="test_p2" messageStore="TEST">
<parameter name="max.deliver.attempts">1</parameter>
</messageProcessor>
</definitions>