Can we set an array in WSO2ESB? - xpath

I wish to set an array in WSO2ESB in my scenario.
I am sending two parameters to database and getting number of rows but I need only one row.
My configuration is
<target>
<sequence>
<property name="partybranchid"
expression="get-property('partybranchid')"
scope="default"
type="STRING"/>
<payloadFactory>
<format>
<p:Select_MailDetails_Op xmlns:p="http://ws.wso2.org/dataservice">
<xs:assetid xmlns:xs="http://ws.wso2.org/dataservice">$1</xs:assetid>
<xs:partybranchid xmlns:xs="http://ws.wso2.org/dataservice">$2</xs:partybranchid>
</p:Select_MailDetails_Op>
</format>
<args>
<arg expression="get-property('assetid')"/>
<arg expression="get-property('partybranchid')"/>
</args>
</payloadFactory>
<log level="full"/>
<send receive="Mail_Seq">
<endpoint>
<address uri="http://localhost:9764/services/massetparametersetdetail_DataService/"
format="soap11"/>
</endpoint>
</send>
</sequence>
</target>
and I am receiving data in this sequence:
<log><property xmlns:v="http://ws.wso2.org/dataservice" xmlns:ns="http://org.apache.synapse/xsd"
name="primarymail" action="set"
expression="//v:primarymail/text()"
scope="default"
type="STRING"/></log>
<iterate xmlns:v="http://ws.wso2.org/dataservice"
xmlns:ns="http://org.apache.synapse/xsd"
id="Mail"
expression="//v:Datalist">
<target>
<sequence>
<property xmlns:v="http://ws.wso2.org/dataservice" xmlns:ns="http://org.apache.synapse/xsd"
name="primarymail"
expression="//v:primarymail/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="assetname"
expression="//assetname/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="assetcode"
expression="//assetcode/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="activityname"
expression="//activityname/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="username"
expression="//username/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="parametername"
expression="//parametername/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="uomcode"
expression="//uomcode/text()"
scope="default"
type="STRING"/>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="tododetails"
expression="fn:concat('AssetName:',get-property('assetname'),',','AssetCode:',get-property('assetcode'),',','ActivityName:',get-property('activityname'),',','UserName:',get-property('username'),',','ParameterName:',get-property('parametername'),',','UomCode:',get-property('uomcode'))"
scope="default"
type="STRING"/>
<log><property xmlns:v="http://ws.wso2.org/dataservice" xmlns:ns="http://org.apache.synapse/xsd"
name="primarymail" action="set"
expression="//v:primarymail/text()"
scope="default"
type="STRING"/></log>
</sequence>
</target>
</iterate>
</sequence>
and I am getting response like below but I want to send a mail only once.
Here my mailid is repeating. How can I take out this mail id?
response, primarymail =
mail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.commail#myunisoft.com
How can I take single mail for this?

Your webservice response is a SOAP message and What you get in to any mediator in ESB, is that particular incoming message. You cannot directly have an array of values.
- One option is to use a class mediator and extract your desired value/s and set that value to a property in message context and use it.
- if the response payload can be altered in your scenario, return the response with a known delimiter and use xpath String operations to get your value.

Related

getting token from cognito and caching in wso2 Enterprise Intigrator

I need to get a token from Cognito but I don't know how to get it through enterprise integrator. I have client_id and client_secet and endpoint also. But I 'm not able to get the token seems I'm not calling the endpoint properly with proper parameter.
After getting the token I need to cache it till the token expires so I don't have to call again and again
here is the code I'm trying
<cache id="cache-sample" scope="per-host" collector="false" hashGenerator="org.wso2.carbon.mediator.cache.digest.DOMHASHGenerator" timeout="5000">
<implementation type="memory" maxSize="1000"/>
</cache>
<header name="client_id" scope="transport" value="XXXXXXXXXXXXXXXXX"/>
<header name="client_secret" scope="transport" value="XXXXXXXXXXXXXXXXXXX"/>
<header name="Content-Type" scope="transport" value="application/json"/>
<property name="DISABLE_CHUNKING" scope="axis2" type="STRING" value="true"/>
<call>
<endpoint>
<address uri="https://xcxxxxxxxxxx.auth.us-east-1.amazoncognito.com/oauth2/token"/>
</endpoint>
</call>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<cache scope="per-host" collector="true"/>
<respond/>
<?xml version="1.0" encoding="UTF-8"?>
<api context="/api/myService" name="myService-api" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST" uri-template="/getToken">
<inSequence>
<script language="js"><![CDATA[var payload = mc.getPayloadXML();
var log = mc.getServiceLog();
var client_id = payload..*::client_id.toString();
var client_secret = payload..*::client_secret.toString();
mc.setProperty("client_id", client_id);
mc.setProperty("client_secret", client_secret);]]>
</script>
<payloadFactory media-type="json">
<format/>
<args/>
</payloadFactory>
<property name="ContentType" scope="axis2" type="STRING" value="application/x-www-form-urlencoded"/>
<property expression="fn:concat($ctx:client_id,':',$ctx:client_secret)" name="credentials" scope="default" type="STRING"/>
<property expression="fn:concat('Basic ', base64Encode($ctx:credentials))" name="Authorization" scope="transport" type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<property name="FORCE_POST_PUT_NOBODY" scope="axis2" type="BOOLEAN" value="true"/>
<property name="DISABLE_CHUNKING" scope="axis2" type="STRING" value="true"/>
<cache
collector="false"
hashGenerator="org.wso2.carbon.mediator.cache.digest.DOMHASHGenerator"
id="cognito-token"
scope="per-host"
timeout="3600">
<onCacheHit>
<log level="custom">
<property expression="/" name="[usage-service-api]:: CHACHE HIT"/>
</log>
<respond/>
</onCacheHit>
<implementation maxSize="50" type="memory"/>
</cache>
<call>
<endpoint>
<http method="post" uri-template="https://xxxxxxxxxxx.amazoncognito.com/oauth2/token?grant_type=client_credentials"/>
</endpoint>
</call>
<property name="RESPONSE" scope="default" type="STRING" value="true"/>
<cache collector="true" id="cognito-token" scope="per-host"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
For first Call cache miss will happen in that case it will call the endpoint and store it in the cache
for the second call and onwards till the time expires for the same call it will hit the cache i.e. Cache hit then It will respond from onCacheHit mediator
<onCacheHit>
<respond/>
</onCacheHit>
and
But after cache hit it will skip any execution of any statement written after cache Mediator. So So keep it in some other sequence if you are writing in some sequence
You can have more than one resources in API.
If you want to know how to call this API then see this getting cognito acces_token with wso2 esb
<log level="custom">
<property expression="/" name="[usage-service-api]:: CHACHE HIT"/>
</log>
The above block of code logs the content of the cache on CACHE HIT

Downloaded image not viewable by using WSO2 EI file connector

I am downloading image to local folder by using WSO2 EI File Connector, Image getting downloaded successfully but it is not viewable. Anyone please help me?
getting image URL(eg. https://carsales.pxcrush.net/dealerweb/car/cil/cc5754691391091045492.jpg) from Database.
getting base64 content from imageURL
then inserting those content into local folder using file connector.
Note: Bae64 comes from API which is not included here. base64 content is correct only, because i can get exact image from this base64 by using base64 to Image converter
Added below in axis2.xml file.
<messageFormatter contentType="application/octet-stream" class="org.apache.axis2.format.BinaryFormatter"/>
<messageBuilder contentType="application/octet-stream" class="org.apache.axis2.format.BinaryBuilder"/>
Code Snippet:
<sequence name="DownloadImageFileSequnce" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property name="===DownloadImageFileSequnce" value="called=="/>
</log>
<property value="D:\Test\CarSalesStockImages" name="PATH"/>
<property expression="get-property('StockNo')" name="FOLDERNAME"/>
<property expression="get-property('eachImageName')" name="FILENAME"/>
<property expression="get-property('image_val')" name="CONTENT"/>
<!-- <property name="messageType" value="application/octet-stream" scope="axis2"/> -->
<property expression="fn:concat('file://',$ctx:PATH,'/',$ctx:FOLDERNAME,'/',$ctx:FILENAME)" name="source"/>
<log level="custom">
<!-- <property name="===CONTENT===" expression="get-property('CONTENT')"/> -->
<property name="===PATH===" expression="get-property('PATH')"/>
<property name="===FOLDERNAME===" expression="get-property('FOLDERNAME')"/>
<property name="===FILENAME===" expression="get-property('FILENAME')"/>
<property name="===source===" expression="get-property('source')"/>
</log>
<fileconnector.isFileExist>
<source>{$ctx:source}</source>
</fileconnector.isFileExist>
<property expression="json-eval($.fileExist)" name="exists" type="BOOLEAN"/>
<filter xpath="$ctx:exists">
<then>
<fileconnector.append>
<destination>{$ctx:source}</destination>
<inputContent>{$ctx:CONTENT}</inputContent>
</fileconnector.append>
<payloadFactory media-type="json">
<format>{"status":"File updated"}</format>
<args/>
</payloadFactory>
<log level="custom">
<property name="==Response==" expression="json-eval($.)"/>
</log>
</then>
<else>
<fileconnector.create>
<source>{$ctx:source}</source>
<inputContent>{$ctx:CONTENT}</inputContent>
</fileconnector.create>
<payloadFactory media-type="json">
<format>{"status":"File created"}</format>
<args/>
</payloadFactory>
<log level="custom">
<property name="==Response==" expression="json-eval($.)"/>
</log>
</else>
</filter>
</sequence>
I have found solution by using vfs instead of wso2 file connector.
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="DownloadImageFileSequnce" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property name="===DownloadImageFileSequnce" value="called=="/>
</log>
<property name="PATH" scope="default" type="STRING" value="D:\Test\CarSalesStockImages"/>
<property expression="get-property('StockNo')" name="FOLDERNAME" scope="default" type="STRING"/>
<property expression="get-property('eachImageName')" name="FILENAME" scope="default" type="STRING"/>
<property expression="get-property('image_val')" name="CONTENT" scope="default" type="STRING"/>
<payloadFactory media-type="xml">
<format>
<ns:binary xmlns:ns="http://ws.apache.org/commons/ns/payload">$1</ns:binary>
</format>
<args>
<arg evaluator="xml" expression="$ctx:CONTENT"/>
</args>
</payloadFactory>
<script language="js"><![CDATA[var binaryNode =
mc.getEnvelope().getBody().getFirstElement().getFirstOMChild();
binaryNode.setBinary(true);]]></script>
<!-- <property expression="concat($ctx:PATH,'/',$ctx:FOLDERNAME,'/',$ctx:FILENAME)" name="transport.vfs.ReplyFileName" scope="transport" type="STRING"/> -->
<property expression="concat('vfs:file:///',$ctx:PATH,'/',$ctx:FOLDERNAME,'/',$ctx:FILENAME)" name="localpath"/>
<header name="To" expression="get-property('localpath')"/>
<log level="custom">
<property expression="$ctx:localpath" name="==ReplyFileName==="/>
</log>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<property action="remove" name="REST_URL_POSTFIX" scope="axis2"/>
<property name="messageType" scope="axis2" type="STRING" value="application/octet-stream"/>
<call/>
<payloadFactory media-type="json">
<format>
{
"status": "success",
"statusMessage" : "Image downloaded"
}
</format>
<args/>
</payloadFactory>
<log level="custom">
<property expression="json-eval($.)" name="Response"/>
</log>
</sequence>

unable to get endpoint from a property in wso2 esb 5.0.0

I am trying to send a message to JMS queue, the queue name is dynamic and it will be fetched from DB.
Along with the queue name, connection factory details, initial context factory, provider url are concatenated and saved in a property (endpt) in wso2 esb.
I want to use the final concatenated string (endpt) in send mediator as endpoint, i have given endpoint type as XPATH and called the variable using $ctx:endpt (endpt is the property where i have final formed URL), and it is not working.
<?xml version="1.0" encoding="UTF-8"?>
<property
expression="fn:concat('jms://', $ctx:queueName, '?
transport.jms.ConnectionFactoryJNDIName=', $ctx:connectionFactory,'&java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory&java.naming.provider.url=', 't3://localhost:7003,localhost:7004', '&transport.jms.DestinationType=queue')"
name="endpt" scope="default" type="STRING"
xmlns="http://ws.apache.org/ns/synapse"
xmlns:ns="http://org.apache.synapse/xsd"/>
EDIT 1: Code below is the complete sequence being called from a proxy service,
I need to send $body to the endpoint defined in To header. The same worked when i define a endpt in send mediator in the insequence of proxy service, but when i call the above sequence (using sequence mediator) from the proxy service, null message is sent to JMS queue.
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="sendtoconsumer" xmlns="http://ws.apache.org/ns/synapse">
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<property expression="//*[name() = 'CONSUMER_REFERENCE']/text()"
name="topic" scope="default" type="STRING"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="fn:substring-before($ctx:topic,'//')"
name="topicval" scope="default" type="STRING"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ns="http://org.apache.synapse/xsd"/>
<property
expression="fn:substring-before(fn:substring-after($ctx:topic,'//'),'#')"
name="queueName" scope="default" type="STRING"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="fn:substring-after($ctx:topic,'#')"
name="connectionFactory" scope="default" type="STRING"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:ns="http://org.apache.synapse/xsd"/>
<log level="custom">
<property expression="$ctx:pubRequest" name="body" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="$ctx:topic" name="topic" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="$ctx:topicval" name="topicval" xmlns:ns="http://org.apache.synapse/xsd"/>
</log>
<switch source="get-property('topicval')" xmlns:ns="http://org.apache.synapse/xsd">
<case regex="mq:"/>
<case regex="java:">
<property
expression="fn:concat('jms://', $ctx:queueName, '?transport.jms.ConnectionFactoryJNDIName=', $ctx:connectionFactory,'&java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory&java.naming.provider.url=', 't3://localhost:7003,localhost:7004', '&transport.jms.DestinationType=queue')"
name="endpt" scope="default" type="STRING"/>
<log level="custom">
<property expression="$ctx:endpt" name="sendvalue"/>
</log>
<header expression="get-property('endpt')" name="To"/>
<send>
<endpoint>
<default/>
</endpoint>
</send>
</case>
<case regex="http:"/>
<default>
<log level="custom">
<property expression="$ctx:topic" name="poda"/>
</log>
</default>
</switch>
</sequence>
The Xpath Endpoint is a key-expression - i.e., points to a resource - either in the registry, or in the local Endpoints.
What you actually need is a default endpoint and a header "To" with the endpoint value:
<header name="To" expression="get-property('endpt')"/>
<send>
<endpoint>
<default/>
</endpoint>
</send>

WSO2 get value from service response

I have this rest api in WSO2 ESB:
<api xmlns="http://ws.apache.org/ns/synapse" name="RestApi" context="/rest">
<resource methods="POST GET" uri-template="/view/{symbol}" protocol="http">
<inSequence>
<log level="full"/>
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.w3schools.com/webservices/">
<soapenv:Header/>
<soapenv:Body>
<web:FahrenheitToCelsius>
<web:Fahrenheit>$1</web:Fahrenheit>
</web:FahrenheitToCelsius>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg evaluator="xml" expression="get-property('uri.var.symbol')"/>
</args>
</payloadFactory>
<property name="DISABLE_CHUNKING" value="true" scope="axis2"/>
<send>
<endpoint>
<address uri="http://www.w3schools.com/webservices/tempconvert.asmx" format="soap11"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<property name="messageType" value="application/json" scope="axis2"/>
<property name="msgbody" expression="$body" scope="default" type="STRING"/>
<log level="custom">
<property name="To" expression="get-property('msgbody')"/>
</log>
<payloadFactory media-type="json">
<format>{"Status":"evgeni"}</format>
<args/>
</payloadFactory>
<send/>
</outSequence>
<faultSequence/>
</resource>
</api>
The important part is the <outSequence></outSequence>
The property <property name="msgbody" expression="$body" scope="default" type="STRING"/> returns the response from the soap service. It looks like this:
<soap:Body xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<FahrenheitToCelsiusResponse xmlns="http://www.w3schools.com/webservices/">
<FahrenheitToCelsiusResult>4.44444444444444</FahrenheitToCelsiusResult>
</FahrenheitToCelsiusResponse>
</soap:Body>
I want to get just the value of FahrenheitToCelsiusResult (4.44444444444444). How can I do that?
I tried:
<property xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
name="msgbody"
expression="$body/soap:Body/FahrenheitToCelsiusResponse/FahrenheitToCelsiusResult"
scope="default" type="STRING"/>
but it returns an empty string.
You have to provide the namespace in the xpath expression as in below
<property expression="//ns:FahrenheitToCelsiusResult"
name="msgbody" scope="default" type="STRING"
xmlns:ns="http://www.w3schools.com/webservices/"/>
For more information please refer to this link
Thanks.
<property name="tempValue" expression="//*[local-name()='FahrenheitToCelsiusResult']" scope="default" type="STRING"/>

how to compare integer properties in filter mediation in wso2 esb?

i am new in wso2 esb and define 3 service that return integer value and use filter mediator to rout from one to another , but not correct work and in filter mode always return false
my source is :
<sequence xmlns="http://ws.apache.org/ns/synapse" name="SeqOne">
<log level="full"/>
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:m0="http://tempuri.org/" name="CParam" expression="//m0:SumSerViseResponse/m0:SumSerViseResult" scope="default" type="INTEGER"/>
<log level="custom">
<property xmlns:ns="http://org.apache.synapse/xsd" name="CParam" expression="$ctx:CParam"/>
</log>
<property name="propertyA" value="4" scope="default" type="INTEGER"/>
<log level="custom">
<property xmlns:ns="http://org.apache.synapse/xsd" name="propertyA" expression="get-property('propertyA')"/>
</log>
<property xmlns:ns="http://org.apache.synapse/xsd" name="propertyCompare" expression="$ctx:CParam > get-property('propertyA')" type="STRING"/>
<log level="custom">
<property xmlns:ns="http://org.apache.synapse/xsd" name="propertyCompare" expression="get-property('propertyCompare')"/>
</log>
<filter xmlns:ns="http://org.apache.synapse/xsd" source="get-property('propertyCompare')" regex="true">
<then>
I tried your scenario and got the same output as yours. Then looked deep into it as this was a basic functionality and as I thought I've done something similar before.
The issue here is in the type of the property. For some strange reason INTEGER does not work here. You need to have DOUBLE or STRING. Even if you have string, it will correctly cast it when you do a comparison as in here. The following worked for me.
<inSequence>
<log level="full"/>
<property xmlns:m0="http://tempuri.org/"
name="CParam"
expression="//m0:SumSerViseResponse/m0:SumSerViseResult"
scope="default"
type="DOUBLE"/>
<log level="custom">
<property name="CParam" expression="$ctx:CParam"/>
</log>
<property name="propertyA" value="4.0" scope="default" type="DOUBLE"/>
<log level="custom">
<property xmlns:ns="http://org.apache.synapse/xsd"
name="propertyA"
expression="get-property('propertyA')"/>
</log>
<property name="propertyCompare"
expression="$ctx:CParam > get-property('propertyA')"
scope="default"
type="BOOLEAN"/>
<log level="custom">
<property name="propertyCompare" expression="get-property('propertyCompare')"/>
</log>
<filter xpath="$ctx:CParam > get-property('propertyA')">
<then>
<send>
<endpoint>
<address uri="http://localhost:9000/services/SimpleStockQuoteService"/>
</endpoint>
</send>
</then>
<else>
<drop/>
</else>
</filter>
</inSequence>
following is an example done with switch mediator,
<switch source="get-property('propertyCompare')">
<case regex="1">
<log>
<property name="one" value="__________ONE__________"/>
</log>
</case>
<case regex="2">
<log>
<property name="two" value="__________TWO__________"/>
</log>
</case>
</switch>
replace the log mediators with send mediator according to your needs.

Resources