WSO2- Error Using Clone Mediator to send message to an endpoint - proxy

I am working on WSO2 proxy service that invokes a lot of other DSS services. My requirement is to send the response of one of the DSS service on to a jms queue and at the same time continue with the exsiting flow in the proxy service i.e. continue invoking and processing the other DSS services.
I need to get the response of Simple Product Service (sequence key -if4_simpleProduct) and send it back on to the queue, but after that continue with logic that is placed in the proxy service and sequence. I tried using CLONE Mediator for the same. But my prxy service flow stops after coming in to the CLONE Meditaor flow. Below is the snippet for proxy service and sequence.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="SPE_Payload"
transports="jms" startOnLoad="true" trace="enable">
<description />
<target>
<inSequence>
<transaction action="new" />
<xslt key="StepToCommon" />
<log level="full" />
<enrich>
<source type="body" clone="true" />
<target type="property" property="MSG_PAYLOAD" />
</enrich>
<sequence key="if4_simpleProduct" />
<filter xpath="boolean (//product/simpleProduct/altPrdCodes/pn_apc_id/text())">
<enrich>
<source clone="true" xpath="//product/simpleProduct/altPrdCodes" />
<target type="property" property="ALT_PRDS" />
</enrich>
<sequence key="if4_alternateProducts" />
</filter>
....
.....
<transaction action="commit" />
</inSequence>
</target>
<parameter name="transport.jms.ContentType">application/xml</parameter>
<parameter name="transport.jms.Destination">test</parameter>
</proxy>
Given below is the code of for sequence while calling Simple Product Service
<sequence xmlns="http://ws.apache.org/ns/synapse" name="if4_simpleProduct"
onError="myErrorHandlerSeq">
<payloadFactory>
<format>
<p:O_SimpleProduct xmlns:p="http://ws.wso2.org/dataservice">
<p:PC_STEP_SKU_ID>$1</p:PC_STEP_SKU_ID>
</p:O_SimpleProduct>
</format>
<args>
<arg xmlns:m="http://wso2.org/services/product" evaluator="xml"
expression="//product/simpleProduct/step_id/text()" />
</args>
</payloadFactory>
<header name="Action" value="urn:O_SimpleProduct" />
<callout serviceURL="local://localhost/services/productEnrichment"
action="urn:O_SimpleProduct" useServerConfig="true">
<source xmlns:ns="http://org.apache.synapse/xsd" xpath="$body/child::*[fn:position()=1]" />
<target xmlns:ns="http://org.apache.synapse/xsd" xpath="$body/child::*[fn:position()=1]" />
</callout>
<clone sequential="false">
<property name="RESPONSE" value="true" />
<header name="To" action="remove" />
<target>
<endpoint>
<address
uri="jms:/step.IF04Output?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616&transport.jms.DestinationType=queue" />
</endpoint>
</target>
<target>
<filter xmlns:ns="http://org.apache.synapse/xsd" xmlns:ds="http://wso2.org/services/product"
source="//ds:result/ds:set/ds:PC_STATUS/text()" regex="0">
<then>
<log level="custom">
<property name="STATUS"
value="************DONE INSERTING SIMPLE ATTRIBUTES***************" />
</log>
</then>
<else>
<log level="full" category="ERROR">
<property name="STATUS"
value="************ERROR OCCURED WHILE INSERTING SIMPLE ATTRIBUTES. ROLLBACKING THE TRANSACTION***************" />
<property name="PC_RP_ID" expression="get-property('GEN_RP_ID')" />
</log>
<transaction action="rollback" />
<drop />
</else>
</filter>
<property xmlns:ds="http://wso2.org/services/product" name="GEN_RP_ID"
expression="//ds:result/ds:set/ds:PC_RP_ID/text()" />
<enrich>
<source type="property" clone="true" property="MSG_PAYLOAD" />
<target type="body" />
</enrich>
</target>
</clone>
</sequence>
I am struggling with the issue since last two days. tried sing Clone meditior in several places. but it does not work. Could you please provide your suggestions soon as I have a demo to go tomorrow and I need to sort it out :(
Cheers,
Aanchal

I think this is the part you are struggling;
<callout serviceURL="local://localhost/services/productEnrichment"
action="urn:O_SimpleProduct" useServerConfig="true">
<source xmlns:ns="http://org.apache.synapse/xsd" xpath="$body/child::*[fn:position()=1]" />
<target xmlns:ns="http://org.apache.synapse/xsd" xpath="$body/child::*[fn:position()=1]" />
</callout>
<clone sequential="false">
<property name="RESPONSE" value="true" />
<header name="To" action="remove" />
<target>
<endpoint>
<address
uri="jms:/step.IF04Output?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616&transport.jms.DestinationType=queue" />
</endpoint>
</target>
Since your requirement is get response form one of the DS service and send that to queue..I think it fails because you are removing "To" header..Use callout mediator inside clone mediator's one of the "Target" configuration after sending to JMS queue drop the message there..In the other target, define your rest of the logic..

Related

change original payload with wso2 esb

I saved the following structure on a property du wso2:
<ELEMENT>
<ELEMENT_2>
<ELEMENT_3>
<ID> 173993 </ID>
</ELEMENT_3>
</ELEMENT_2>
</ELEMENT>
I want to bring TEMP only to children:
<TEMP>
<NAME>GEORGE</NAME>
<COGNOME>MENDEZ</COGNOME>
<BUSINESSNAME/>
<CHANNEL>X091</CHANNEL>
</TEMP>
I want to add them right after the <ELEMENT_2>
FINAL RESULTS:
<ELEMENT>
<ELEMENT_2>
<NAME>GEORGE</NAME>
<COGNOME>MENDEZ</COGNOME>
<BUSINESSNAME/>
<CHANNEL>X091</CHANNEL>
<ELEMENT_3>
<ID> 173993 </ID>
</ELEMENT_3>
</ELEMENT_2>
</ELEMENT>
Thanks
Can you check if your requirement is achieved with the following proxy configuration.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="enrichProxy"
startOnLoad="true"
statistics="disable"
trace="disable"
transports="http,https">
<target>
<inSequence>
<property name="initial_payload" scope="default">
<ELEMENT xmlns="">
<ELEMENT_2>
<ELEMENT_3>
<ID>173993</ID>
</ELEMENT_3>
</ELEMENT_2>
</ELEMENT>
</property>
<call>
<endpoint>
<http uri-template="http://run.mocky.io/v3/7c578a1d-5427-4325-9f00-4ad7bb80dd04"/>
</endpoint>
</call>
<log level="custom">
<property expression="$body//TEMP/*" name="******"/>
</log>
<respond/>
</inSequence>
</target>
<description/>
</proxy>
Remove external tag with xpath wso2
update
Here I have enriched the second property (..) back to the body using a enrich mediator.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="enrichProxy"
startOnLoad="true"
statistics="disable"
trace="disable"
transports="http,https">
<target>
<inSequence>
<property name="initial_payload" scope="default">
<ELEMENT xmlns="">
<ELEMENT_2>
<ELEMENT_3>
<ID>173993</ID>
</ELEMENT_3>
</ELEMENT_2>
</ELEMENT>
</property>
<property name="second_payload" scope="default">
<TEMP xmlns="">
<NAME>GEORGE</NAME>
<COGNOME>MENDEZ</COGNOME>
<BUSINESSNAME/>
<CHANNEL>X091</CHANNEL>
</TEMP>
</property>
<enrich>
<source clone="true" property="second_payload" type="property"/>
<target type="body"/>
</enrich>
<enrich>
<source clone="true" xpath="$body//TEMP/*"/>
<target action="child" xpath="$ctx:initial_payload//ELEMENT_2"/>
</enrich>
<log level="custom">
<property expression="$ctx:initial_payload" name="******"/>
</log>
<respond/>
</inSequence>
</target>
<description/>
</proxy>

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

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 break/stop sequence if exception occurs in mediator using WSO2 ESB

i am trying to implement logic that if during execution of sequence any error occurs, like e.g JMS endpoint is invalid, So sequence should drop here and log the message.
The actual mediation is like below:
Validate-->Clone-->Log Clone mediation snapshot attached.
My Service Code is:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="AdapterService"
transports="jms"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<log level="full" separator="..... XML Received..."/>
<validate source="//DOCUMENT03">
<schema key="conf:/DOCUMENT03_CUSTOM.xsd"/>
<on-fail>
<makefault version="pox">
<reason value="Invalid XML"/>
<detail>Error while validating XML at Adapter Service.</detail>
</makefault>
<log level="full" category="ERROR" separator="... XML Error..."/>
<drop/>
</on-fail>
</validate>
<clone>
<target>
<sequence>
<script language="js">mc.getEnvelope().getBody().getFirstElement().getFirstElement().getFirstElement().detach();</script>
<log level="full"/>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<send>
<endpoint>
<address uri=**"jms:/BookingMessage?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://1929.168.1.113:61616&transport.jms.DestinationType=queue"**
format="pox">
<timeout>
<duration>10</duration>
<responseAction>fault</responseAction>
</timeout>
<suspendOnFailure>
<errorCodes>101507,101505,101503</errorCodes>
<progressionFactor>1.0</progressionFactor>
<maximumDuration>10</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<errorCodes>101508,101504</errorCodes>
<retriesBeforeSuspension>5</retriesBeforeSuspension>
<retryDelay>10</retryDelay>
</markForSuspension>
</address>
</endpoint>
</send>
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>$1</soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg xmlns:tns="http://com.sanomalearning/cdm/finance/generalledger/v1"
evaluator="xml"
expression="//DOCUMENT03/CMMHeader"/>
</args>
</payloadFactory>
<log level="full"/>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<send>
<endpoint key="conf:/CMMHeaderQueueUrl"/>
</send>
<log level="full" separator="Message Sent to Queue"/>
</sequence>
</target>
</clone>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<log level="custom" separator=",">
<property name="text" value="***FAult Handler***"/>
</log>
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
<drop/>
<log level="custom">
<property name="text" value="An unexpected error occured"/>
<property name="message" expression="get-property('ERROR_MESSAGE')"/>
<property name="code" expression="get-property('ERROR_CODE')"/>
<property name="detail" expression="get-property('ERROR_DETAIL')"/>
<property name="exception" expression="get-property('ERROR_EXCEPTION')"/>
</log>
<drop/>
</faultSequence>
</target>
<parameter name="transport.jms.ContentType">
<rules>
<jmsProperty>contentType</jmsProperty>
<default>application/xml</default>
</rules>
</parameter>
<parameter name="transport.jms.ConnectionFactory">myQueueConnectionFactory</parameter>
<parameter name="transport.jms.DestinationType">queue</parameter>
<parameter name="transport.jms.Destination">AdapterService.01.Request.Queue</parameter>
<description/>
</proxy>
Now when i execute this service after receiving request from queue, it is not sending message to invalid queue but sending message to second Url. Now i want if message is not sent to invalid endpoint then sequence should dropped. The invalid url is Bold.
AFAIK you can not define two send mediators under the same target in one clone mediator instead you have to define those inside two different targets.
Also would be helpful if you can elaborate your requirement a bit more. For a solution with regard to JMS endpoint is invalid issue what you can do is define a drop mediator inside the fault sequence.

JMS rollback in WsO2 ESB 4.7.0

I have configured Apache ActiveMQ with transaction and CLIENT_ACKNOWLEDGE in WSO2 ESB 4.7.0. The axis2.xml config is :
<parameter name="transport.jms.SessionTransacted">true</parameter>
<parameter name="transport.jms.SessionAcknowledgement" locked="true">CLIENT_ACKNOWLEDGE</parameter>
I have a simple passthrough proxy with jms transport which passes the messages in the JMS queue to a jax-rs service. The proxy code is :
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="MediaMoveQueue"
transports="jms"
startOnLoad="true"
trace="enable">
<description/>
<target>
<inSequence>
<property name="messageType" value="application/json" scope="axis2"/>
<property name="ContentType" value="application/json" scope="axis2"/>
<send receive="JmsRollbackSequence">
<endpoint>
<address uri="http://192.168.1.2:9766/RestMediaMove_1.0.0/services/rest_media_move_i_f/restmediamoveif/hello"/>
</endpoint>
</send>
<log level="custom">
<property name="In MediaMoveQueue JMSERROR"
expression="get-property('JMSERROR')"/>
</log>
<switch source="get-property('JMSERROR')">
<case regex="true">
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
<log level="custom">
<property name="In MediaMoveQueue Transaction Action"
value="Rollbacked"/>
</log>
</case>
<case regex="false">
<log level="custom">
<property name="In MediaMoveQueue Transaction Action"
value="Committed"/>
</log>
</case>
<default>
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
<log level="custom">
<property name="In MediaMoveQueue Transaction Action default"
value="Rollbacked"/>
</log>
</default>
</switch>
</inSequence>
<outSequence>
<log level="full">
<property name="test" value="IN outsequence"/>
</log>
<send/>
</outSequence>
</target>
<parameter name="transport.jms.ContentType">
<rules>
<jmsProperty>contentType</jmsProperty>
<default>application/json</default>
</rules>
</parameter>
</proxy>
The JmsRollbackSequence sequence receives the reply from the jax-rs service and depending on the reply success or failure returned, I would like to rollback the JMS transaction. But if I set the property in the JmsRollbackSequence it has absolutely no effect ( I tried it first before using the sequence shown below). The transaction is never rolled back. The rollback works only if the property is set in the inSequence. Here is the code for the JmsRollbackSequence :
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="JmsRollbackSequence">
<property name="JMSERROR" value="true"/>
<log level="full">
<property name="test" value="IN JmsRollbackSequence"/>
</log>
</sequence>
So I tried to set up a property called JMSERROR in the JmsRollbackSequence and by reading it after the send mediator in the inSequence I thought I can roll back the transaction in the inSequence. But this does not work either. The switch case in inSequence is called before the property is set up in JmsRollbackSequence so when I read it it always returns null.
So my questions are :
1) Can we set
in a sequence? Why does it not work in JmsRollbackSequence?
2) As mediators are supposed to be called sequentially, why does the switch case in inSequence run before the JmsRollbackSequence has a chance to read the reply and set up the JMSERROR property?
"send" mediator is asynchronous : inSequence will continue his job and JMS transaction will be commited before the response arrive in your JmsRoolbackSequence.
use "callout" mediator for synchronous calls and create a faultSequence in your proxy to deal with errors and rollback your transaction :
<faultSequence>
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
</faultSequence>

Resources