I'm trying to get a wso2 foreach loop to work.
<property expression="$ctx:xmlTransform"
Value of $ctx:xmlTransform :
<magasin>
<codeMagasin>20019</codeMagasin>
</magasin>
<magasin>
<codeMagasin>20020</codeMagasin>
</magasin>
<magasin>
<codeMagasin>20021</codeMagasin>
</magasin>
Loop :
<foreach expression="$ctx:xmlTransform//magasin" xmlns:ns="http://org.apache.synapse/xsd">
<sequence>
<log category="ERROR">
<property expression="tessst" name="----Test foreach loop----"/>
</log>
</sequence>
</foreach>
I'm never going inside the loop.
Any ideas ? Thanks a lot.
You need to check if you are adding the correct XPATH expression for the for loop. You can do this by adding a log mediator.
<log level="custom">
<property expression="$ctx:xmlTransform" name="----log----"/>
</log>
This need to print the following in order for the for loop to work. Otherwise there is an issue with the XPATH expression you have used.
INFO {org.apache.synapse.mediators.builtin.LogMediator} - ----log---- = <magasin>
<codeMagasin>20019</codeMagasin>
</magasin><magasin>
<codeMagasin>20020</codeMagasin>
</magasin><magasin>
<codeMagasin>20021</codeMagasin>
</magasin>
For example if you need to get the content from a request, the XPATH need to be modified as <foreach expression="$body//magasin">. I have sent the following payload from a postman request and it seems to be working for me without any issue. Therefore I am suspecting that the issue is with the XPATH expression you used.
Postman request body
<xmlTransform>
<magasin>
<codeMagasin>20019</codeMagasin>
</magasin>
<magasin>
<codeMagasin>20020</codeMagasin>
</magasin>
<magasin>
<codeMagasin>20021</codeMagasin>
</magasin>
</xmlTransform>
Proxy service
<?xml version="1.0" encoding="UTF-8"?><proxy xmlns="http://ws.apache.org/ns/synapse" name="DummyProxy" startOnLoad="true" statistics="disable" trace="disable" transports="http,https">
<target>
<inSequence>
<log level="custom">
<property expression="$body//magasin" name="----log----"/>
</log>
<foreach expression="$body//magasin">
<sequence>
<log>
<property name="----Test foreach loop----" value="tessst"/>
</log>
</sequence>
</foreach>
<respond/>
</inSequence>
</target>
<description/>
</proxy>
Maybe the problem is that "magasin" nodes are not enclosed in one parent element. Try to wrap it with some parent element (ex. box), replace body with the one with parent element and then run the loop.
<enrich>
<source type="inline" clone="true">
<ns:box xmlns:ns="http://namespace"/>
</source>
<target type="property" property="box"/>
</enrich>
<enrich>
<source clone="true" xpath="$ctx:xmlTransform"/>
<target action="child" xpath="$ctx:box"/>
</enrich>
<enrich>
<source type="property" clone="true" property="box"/>
<target action="replace" type="body"/>
</enrich>
<foreach expression="//ns:box/magasin" xmlns:ns="http://namespace">
<sequence>
<log category="ERROR">
<property expression="tessst" name="----Test foreach loop----"/>
</log>
</sequence>
</foreach>
Related
I'm trying to send a put request to my backend api, but I need a token and its working on the get request so the problem isn't with the token but when I make the request the response is 202 accepted and don't update the database.
Here is the code
<resource methods="PUT" uri-template="/Nurse">
<inSequence>
<enrich>
<source clone="true" type="body"/>
<target property="payload" type="property"/>
</enrich>
<property action="remove" name="REST_URL_POSTFIX" scope="axis2"/>
<call blocking="true" description="">
<endpoint>
<address format="get" uri="http://192.168.20.1:8280/loginAPI/login"/>
</endpoint>
</call>
<property expression="json-eval($.accessToken)" name="token" scope="default" type="STRING"/>
<property expression="fn:concat('Bearer ',$ctx:token)" name="Authorization" scope="transport" type="STRING"/>
<enrich description="Restore original payload">
<source property="payload" type="property"/>
<target type="body"/>
</enrich>
<send>
<endpoint key="PutNurseEp"/>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence/>
</resource>
Can anyone help what is the problem here?
Solved the question, the error was on the postman request, I was adding a space on the beggining of the url
Input request :
[
{
"id" : "1",
"make" : "NAHB"
},
{
"id" : "2",
"make" : "Honda"
},
{
"id" : "3",
"make" : "Samsung"
}
]
I am using iterate, to send each element of above array as request to a backend service( In myactual project this is not so simple service i.e. its reponse is very complex with lots of arrays and sub-arrays(child arrays)in it . for better understanding of issue I kept it like this ).
The responses of the backend service are aggregated in one soap xml by AggregateMediator.
Below is response from AggregateMediator
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<Information>
<jsonObject>
<id>3</id>
<name>Mobile</name>
<model>S8</model>
</jsonObject>
<jsonObject>
<id>2</id>
<name>Car</name>
<model>Amaze</model>
</jsonObject>
<jsonObject>
<id>1</id>
<name>Home</name>
<area>5000sqft</area>
</jsonObject>
</Information>
</soapenv:Body>
</soapenv:Envelope>
I want to enrich above response from AggregateMediator like below using input request.
i.e. I want to merge input request and output of backend service.(id is common between them.)
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<Information>
<jsonObject>
<id>3</id>
<name>Mobile</name>
<model>S8</model>
<make>Samsung</make>
</jsonObject>
<jsonObject>
<id>2</id>
<name>Car</name>
<model>Amaze</model>
<make>Honda</make>
</jsonObject>
<jsonObject>
<id>1</id>
<name>Home</name>
<area>5000sqft</area>
<make>NAHB</make>
</jsonObject>
</Information>
</soapenv:Body>
</soapenv:Envelope>
I kept input request array in a property before calling backend services and was able to access it in response flow.
but the problem is "both request and response are arrays". How could I run two foreach on two different arrays simultaneously and also match their id before updating each array element of response.
foreachTest.xml :
<?xml version="1.0" encoding="UTF-8"?>
<api context="/foreschTest" name="foreachTest" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST GET" uri-template="/hi">
<inSequence>
<log level="full"/>
<log level="custom">
<property expression="//jsonArray" name="message"/>
</log>
<property expression="//jsonArray" name="req" scope="default" type="STRING"/>
<foreach expression="//jsonArray/jsonElement" id="Loop">
<sequence>
<property expression="get-property('Loop_FOREACH_COUNTER')" name="countid" scope="default" type="STRING"/>
<!-- <enrich>
<source clone="true" property="INCOMING_REQUEST" type="property"/>
<target type="body"/>
</enrich>
<enrich>
<source clone="true" type="inline">
<id xmlns="">Y</id>
</source>
<target action="sibling" xpath="//jsonElement"/>
</enrich> -->
<!--<enrich>
<source clone="true" type="property" property="INCOMING_REQUEST"></source>
<target action="replace" type="body"></target>
</enrich> -->
<!-- Temporily commented <enrich>
<source clone="true" type="inline">
<uniqueId xmlns="">Y</uniqueId>
</source>
<target action="child" xpath="//jsonElement/data[2]"/>
</enrich>
<enrich>
<source clone="true" property="countid" type="property"/>
<target xpath="//jsonElement/data[2]/uniqueId"/>
</enrich> -->
<log level="custom">
<property expression="get-property('countid')" name="mgs7"/>
</log>
<log description="" level="custom">
<property expression="get-property('Loop_FOREACH_ORIGINAL_MESSAGE')" name="mgs5"/>
<property expression="get-property('Loop_FOREACH_COUNTER')" name="mgs6"/>
<property expression="//jsonElement" name="msg8"/>
</log>
<log description="" level="custom">
<property expression="//jsonElement/data[0]" name="msg9"/>
<property expression="//jsonElement/data[1]" name="msg10"/>
<property expression="//jsonElement/data[2]" name="msg11"/>
</log>
</sequence>
</foreach>
<iterate expression="//jsonArray/jsonElement" id="1">
<target>
<sequence>
<log level="custom">
<property name="msg2" value=""Inside iterate""/>
</log>
<log level="full"/>
<send>
<endpoint key="modifyAgrRespEP"/>
</send>
</sequence>
</target>
</iterate>
</inSequence>
<outSequence>
<property name="info" scope="default">
<Information xmlns=""/>
</property>
<aggregate id="1">
<completeCondition>
<messageCount max="-1" min="-1"/>
</completeCondition>
<onComplete enclosingElementProperty="info" expression="//jsonObject">
<log level="custom">
<property name="msg3" value=""Inside Aggr""/>
</log>
<log level="full"/>
<foreach expression="//Information/jsonObject">
<sequence>
<log level="custom">
<property name="msg4" value=""Inside Foreach""/>
</log>
<property expression="$body" name="agr" scope="default" type="STRING"/>
<log level="custom">
<property expression="get-property('agr')" name="agr"/>
</log>
<!-- <log level="full"/> -->
</sequence>
</foreach>
</onComplete>
</aggregate>
</outSequence>
<faultSequence/>
</resource>
</api>
modifyAgrRes.xml :
<?xml version="1.0" encoding="UTF-8"?>
<api context="/mod" name="modifyAgrRes" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST GET" uri-template="/aggr">
<inSequence>
<log level="custom">
<property name="message" value=""Inside Modify Service *************************""/>
</log>
<log level="custom">
<property expression="//jsonObject" name="location"/>
</log>
<switch source="//jsonObject/id">
<case regex="1">
<enrich>
<source clone="true" type="inline">
<name xmlns="">Home</name>
</source>
<target action="child" xpath="//jsonObject"/>
</enrich>
<enrich>
<source clone="true" type="inline">
<area xmlns="">5000sqft</area>
</source>
<target action="child" xpath="//jsonObject"/>
</enrich>
</case>
<case regex="2">
<enrich>
<source clone="true" type="inline">
<name xmlns="">Car</name>
</source>
<target action="child" xpath="//jsonObject"/>
</enrich>
<enrich>
<source clone="true" type="inline">
<model xmlns="">Amaze</model>
</source>
<target action="child" xpath="//jsonObject"/>
</enrich>
</case>
<case regex="3">
<enrich>
<source clone="true" type="inline">
<name xmlns="">Mobile</name>
</source>
<target action="child" xpath="//jsonObject"/>
</enrich>
<enrich>
<source clone="true" type="inline">
<model xmlns="">S8</model>
</source>
<target action="child" xpath="//jsonObject"/>
</enrich>
</case>
<default/>
</switch>
<log level="custom">
<property expression="//jsonObject" name="msg20"/>
</log>
<enrich>
<source clone="true" xpath="//jsonObject"/>
<target type="body"/>
</enrich>
<log level="full"/>
<respond/>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence/>
</resource>
</api>
Here is a high-level answer; I guess you can work the details out for yourself:
Copy the input ($body) to a new property (inputBody) at the
beginning
Transform $ctx:inputBody to XML - see this URL for an example:
https://docs.wso2.com/display/ESB481/Sample+440%3A+Converting+JSON+to+XML+Using+XSLT
Do all intermediate processing steps
Loop through the $ctx:inputBody property, and for each row,
Get the /id (currentId) and /make (currentMake) into new properties
Use the Enrich mediator to add a child
/Information/jsonObject[id=$ctx:currentId]/make with value set to
$ctx:currentMake
Convert back to JSON if necessary.
I hope that helps.
We have a web service which is creating a record in a database table and gives response/output as "SUCCESS" after successful insertion in SOAP UI
We have developed a Project in Developer Studio and called this webservice using AddressEndPoint, and deployed CAR file on ESB Server
The webservice is calling successfully via ESB and records are inserting in the tables but we are unable to log "SUCCESS" status anywhere we tried to use log mediator after CALL(AddressEndPoint) Mediator but it is not logging webservice response.
Below is my Source:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="EslSfaOFAOMSOIntegrationPS"
startOnLoad="true"
statistics="disable"
trace="disable"
transports="http,https">
<target>
<inSequence>
<call>
<endpoint>
<address format="soap11"
uri="http://10.1.6.175:9763/services/EslSfaOMSODataService.SOAP11Endpoint/"/>
</endpoint>
</call>
<log level="full"/>
<datamapper config="gov:datamapper/EslSfaOFAOMSOIntegrationMapping.dmc"
inputSchema="gov:datamapper/EslSfaOFAOMSOIntegrationMapping_inputSchema.json"
inputType="XML"
outputSchema="gov:datamapper/EslSfaOFAOMSOIntegrationMapping_outputSchema.json"
outputType="XML"/>
<log description="" level="full"/>
<header name="Authorization"
scope="transport"
value="Basic cHdjLmV0aXNhbGF0OkZlcmd1c29uMTIz"/>
<log level="full"/>
<call>
<endpoint>
<address format="soap11"
uri="https://eere-test.scm.ap1.oraclecloud.com:443/soa-infra/services/default/DooDecompReceiveOrderExternalComposite/ReceiveOrderRequestService"/>
</endpoint>
</call>
<enrich>
<source clone="true" type="body"/>
<target property="ReceiveOrderServiceResponseMessage" type="property"/>
</enrich>
<log level="custom">
<property expression="get-property('ReceiveOrderServiceResponseMessage')"
name="moidSiddiqui"/>
</log>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</target>
<description/>
</proxy>
I use this property after my call mediator to get the status
<log>
property xmlns:ns="http://org.apache.synapse/xsd" name="Status"
expression="get property('axis2','HTTP_SC')"/>
</log>
You can find more information here
https://docs.wso2.com/display/ESB460/HTTP+Transport+Properties
To obtain the response of the service I use
<enrich>
<source clone="true" type="body"/>
<target property="Ouput_Respose_Service" type="property"/>
</enrich>
<log level="custom" separator=",">
<property expression="get-property('Ouput_Respose_Service')" name="Service_Response"/>
</log>
I am struggling to figure out how to preserve a payload so that it is available after calling a web service within a sequence.
For example in the following sequence, after the “call” mediator fires the payload changes to what has been returned by the web service.
What I am looking to do is to enrich the original payload with the data that has been returned from the web service call.
All help is very much appreciated.
<log level="full"/>
<payloadFactory media-type="xml">
<format>
<Flight xmlns="">
<location_id>$1</location_id>
<FlightDistance/>
<Aircraft>
<AircraftAbbr/>
<LandingDistance/>
<TakeoffDistance/>
<AircraftRange/>
<AirframeHours/>
</Aircraft>
<Runways>
<Airport/>
</Runways>
</Flight>
</format>
<args>
<arg evaluator="xml" expression="get-property('OriginAirport')"/>
</args>
</payloadFactory>
<log level="full">
<property expression="get-property('OriginalPayload')" name="OriginalPayload"/>
</log>
<call blocking="true" description="">
<endpoint key="GetRunways"/>
</call>
<foreach expression="//d:Entries/d:Entry" id="feid" xmlns:d="http://ws.wso2.org/dataservice">
<sequence>
<log description="" level="full">
<property name="marker" value="marker"/>
</log>
<property expression="$body/Entry/runway_length" name="RunwayLength" scope="default" type="STRING"/>
<enrich>
<source clone="true" property="RunwayLength" type="property"/>
<target action="child" property="RunwayLength" type="property"/>
</enrich>
<log>
<property expression="get-property('RunwayLength')" name="PropertyValue"/>
</log>
</sequence>
</foreach>
use enrich mediator and store the payload in to property
<enrich>
<source type="body"/>
<target type="property" property="REQUEST_PAYLOAD"/>
</enrich>
https://docs.wso2.com/display/ESB481/Enrich+Mediator
To complete #Jenananthan answer:
Store original payload in a property
Call the webservice
Restore the original payload to body:
<enrich>
<source clone="false" type="property" property="ORIGINAL_PAYLOAD"/>
<target action="replace" type="body"/>
</enrich>
My desired sequence is the following:
Read message from queue
Transform
Make an SOAP call
Output SOAP response to another queue
Steps 1,2,3 work fine but when the message sent in Step 4, that I'm intending to contain the SOAP response, is empty. What am I doing wrong?
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="JmsToWsdlJms" transports="https,http,jms" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<enrich>
<source type="body" clone="true"/>
<target type="property" property="jms_body_text"/>
</enrich>
<property name="jms_body_text"
expression="get-property('jms_body_text')"
scope="default"/>
<xslt key="jmsMsgToSoapMsg_xslt">
<property name="jms_text" expression="get-property('jms_body_text')"/>
</xslt>
<log level="full">
<property name="After transformation" value="****"/>
</log>
<send>
<endpoint key="axisStockQuote"/>
</send>
<log level="full">
<property name="After callout" value="****"/>
</log>
<property name="OUT_ONLY" value="true"/>
<send>
<endpoint key="jmsQueue2"/>
</send>
</inSequence>
</target>
<parameter name="transport.jms.ContentType">
<rules>
<jmsProperty>contentType</jmsProperty>
<default>text/plain; charset=ISO-8859-1</default>
</rules>
</parameter>
<parameter name="transport.jms.DestinationType">queue</parameter>
<parameter name="transport.jms.Destination">cn=tro_Q_JMS1</parameter>
</proxy>
You can use 'send receive' instead of the send mediator. Something like,
<send receive="jmsQueue2Sequence">
<endpoint key="axisStockQuote"/>
</send>
So that the response of axisStockQuote will be sent to the jmsQueue2Sequence. Refer [1] for more info.
[1] https://docs.wso2.com/display/ESB481/Send+Mediator