I have a requirement to parse JSON response which contain array of products(P1,P2,P3,etc.). Each product contains multiple information like name, type, cost, etc.
I need to read each product one by one and append additional data got from the another service into an new JSON output. I am thinking of using ForEach component of WSO2 ESB to iterate each product one by one.
Problem is that ForEach component uses ForEachExpression which expects XML expression in the configuration.
Please suggest on the method to parse array of JSON response one by one in WSO2 ESB.
/Abhishek
Can use both Iterate or ForEach mediator for iterating the JSON array, since both are content aware mediators and support JSON.
Which one to use depends upon the specific usecase as Iterate provides the capability to use call / callout / send mediators in the sequence whereas ForEach doesn´t allow it.
For the below given sample JSON request, the following iteration works and the JSON array and objects can be referred like the same.
{
"products":[
{
"product":{
"id":"1234",
"size":"20",
"quantity":"1",
"price":"990",
"type":"Electronics",
"store":{
"id":"001"
}
}
}
]
}
<iterate expression="//products" id="PRD_ITR">
<target>
<sequence>
<sequence key="Product_Enrich_Sequence_s"/>
<!-- For example, Switching sequence based on the product type -->
<switch source="//products/product/type">
<case regex="Computer">
<sequence key="Computer_Product_Enrich_Sequence_s"/>
</case>
<case regex="Mobile">
<sequence key="Mobile_Product_Enrich_Sequence_s"/>
</case>
<case regex="Grocery">
<sequence key="GR_Product_Enrich_Sequence_s"/>
</case>
<default>
<!-- default stuff --!>
</default>
</switch>
</sequence>
</target>
</iterate>
FYR
https://docs.wso2.com/display/ESB490/Iterate+Mediator
https://docs.wso2.com/display/ESB490/ForEach+Mediator
Note: tested in WSO2 ESB 4.9.0
Related
I'm pretty new on WSO2 IE and I'm trying to use a SOAP request to call a REST API.
This first part is OK but one of my API's needs to receive an attribute into its PATH or QUERY parameters. The attribute is sent by the soap call in it's body.
The question is, how can i get this body attribute and pass it in the PATH/QUERY param of the URL dynamically before i send it?
Picture of my architecture
Your requirement is to construct a dynamic URL. This can be easily done with the ESB Server. Here we have different options to construct this dynamic URL. Following is a sample proxy service that was created to achieve this.
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="sample_proxy"
startOnLoad="true"
statistics="disable"
trace="disable"
transports="http,https">
<target>
<inSequence>
<log level="custom">
<property expression="$body//target" name="Target endpoint"/>
</log>
<property name="uri.var.host" value="http://localhost:8280"/>
<property name="uri.var.context" value="services"/>
<property expression="$body//target" name="uri.var.resourcepath"/>
<call>
<endpoint>
<http method="GET"
uri-template="{uri.var.host}/{uri.var.context}/{uri.var.resourcepath}"/>
</endpoint>
</call>
<respond/>
</inSequence>
</target>
<description/>
</proxy>
We are sending the following request to this proxy service.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<target>sample_path</target>
</soapenv:Body>
</soapenv:Envelope>
In the above proxy service what we have done is construct the dynamic URL with the parameters from the soap message please refer to the blog post [1] to further clarify regarding dynamic URLs.
Here in order to extract the parameters from the body, we have used XPaths. Please refer to the documentation [2] to further clarify regarding XPaths. We have extracted the value inside the target element and added it to the end of the URL. Thus this will invoke the http://localhost:8280/services/sample_path from the ESB server.
If you are interested in constructing the URL with query parameters you can do that by concatenating the required URL and using an address endpoint [1].
[1]-https://dzone.com/articles/constructing-dynamic-endpoint-urls-in-wso2-esb
[2]-https://docs.wso2.com/display/EI6xx/Accessing+Properties+with+XPath#AccessingPropertieswithXPath-$ctx
I'm trying to use recipientList to send to multiple JMS endpoints. I'm using ActiveMQ as message broker. My problem is: Whether I set the URL as a one single node of ActiveMQ it works perfectly when I set a failover endpoint comma separated I just get that it splits the comma inside the failover URL. Is there a way I can skip this split of commas character inside the failover?
This works:
jms:/myQueue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://myIP:61616&transport.jms.DestinationType=queue
But this doesn't work because it splits the comma.
jms:/myQueue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=failover:(tcp://myIP:61616,tcp://myIP2:61616)&transport.jms.DestinationType=queue
In my case I concatenate multiple uris like the ones above with ',' for making the recipientList work, but the comma inside the failover is making it fail.
Is there a work-around?
Thanks,
Antonio
You can try like below instead of comma
<send>
<endpoint key="jmsMBendpoint1"/>
</send>
<send>
<endpoint key="jmsMBendpoint2"/>
</send>
or you can use Recipienlist endpoint to send a single message to multiple endpoints. After defining recipient list store taht as localentry and provide that as endpoint key.
for more
WSO2 ESB send to multiple endpoints
I don't know what is the workaround with recipientlist but an other way to achieve your need is :
<property name="EIP_LIST" type="OM">
<list xmlns="">
<epr>jms:/myQueue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=failover:(tcp://myIP:61616,tcp://myIP2:61616)&transport.jms.DestinationType=queue</epr>
<epr>jms:/myQueue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=failover:(tcp://myIP3:61616,tcp://myIP4:61616)&transport.jms.DestinationType=queue</epr>
</list>
</property>
<iterate expression="$ctx:EIP_LIST//epr">
<target>
<sequence>
<header name="To" expression="$body/epr"/>
<send/>
</sequence>
</target>
</iterate>
You just have to dynamically compose the content of EIP_LIST
I want to get a URI VAR value from request to call correct case in switch in WSO2 ESB API resource, like this:
<api name="apk" context="/apk"><resource methods="GET" uri-
template="/apk/{appName}"><inSequence><header name="App"
scope="transport" action="remove"/><switch source="get-
property('uri.var.appName')"><case regex="BEBE"><send><endpoint><http
method="GET" uri-template="http://localhost/apk/Bebe.apk></http>
</endpoint></send></case><case regex="CITAS"><send><endpoint><http
method="GET" uri-template="http://localhost/apk/Citas.apk></http>
</endpoint></send></case></switch></inSequence></resource></api>
In switch, source="get-property('uri.var.appName')" it's not correct.
Can I get this value using $url SynapseXpath valiables like $url?
What you have done is correct. Please try the same with a log mediator and see whether you get the value properly.
<log level="custom">
<property name="AppName" expression="get-property('uri.var.appName')"/>
</log>
Alternatively you can assign this to a property and use that inside your switch mediator.
I have the config with development and production sections. This sections contain the URLs of backends. In my inSequence i need it to Callout to these backends several times per request.
<config>
<env>prod</env>
<backend env="prod">http://localhost:1234/</backend>
<backend env="dev">http://localhost:2345/</backend>
</config>
I read this config from Local Entry (as XML) and want to set Callout's URL as an Property.
I don't want to hardcode these backends inside my code with "Switch" statement, because it's possible to use more than two environments.
Could you please show me an example?
Thank you.
You can read xml file in registry. Simply define property of OM type like this:
<property name="test" expression="get-property('registry','conf:/test.xml')" scope="default" type="OM" />
Then you can see the value by logging like this:
<log level="custom"> <property name="test.b" expression="$ctx:test//b" /> </log>
And in the xml file that you have put in the root of registry, you would fill it like:
<a>Hello<b>WSO2</b></a>
I have learned it from this link.
I found the answer. According to source of Callout mediator:
CalloutMediator.java
It uses "To" header if URL is not specified.
Can some one point me to a working example of xsl transformation using the proxy services xslt mediator option.
Basically, my requirement is, i will have a request where i will get some data which determines the routing and after that from other elements of requested data i have to re frame soap request to trigger another bpel service.
Please let me know the better approach to this.
You can very well use XSLT transformation in your sequence, using XSLT Mediator.
In your sequence file you can specify the XSLT file to tranform the request. Sample sequence code snippet:
<sequence xmlns="http://ws.apache.org/ns/synapse" name="SampleInterceptorSequence">
<in>
<log level="full" category="DEBUG">
<property name="sequence" value="inSequence-Request Before XSLT" />
</log>
<xslt key="RequestTranformerXSLT" />
<log level="full" category="DEBUG">
<property name="sequence" value="inSequence-Request After XSLT" />
</log>
<send>
<endpoint key="MyActualServiceEPR" />
</send>
</in>
Your xslt would contain the style for the actual request to be formed for hitting the end point reference.
Further if you can check this nice article of web service chaining to get a real time idea of xslt mediation.
Web Service Chaining from WSO2 ESB Developers
Hope this helps.
Thanks.
Find the sample below..
http://wso2.org/project/esb/java/4.0.0/docs/samples/message_mediation_samples.html#Sample8