WSO2 EI: Can I use mediator to request another API and pass its response to the body request? - dynamic

In my case, I want to add a dynamic value ("Bearer" + {access-token}) to the header mediator .
So before the header mediator, I want to invoke a get-token API and extract {access-token} element from its response. How can I get that ? Thank you so much.

You can achieve such requirements with mediation sequences. You can refer to this blog for more detailed instructions on how to develop a sequence for your requirement. The blog is written for the API Manager product, but nevertheless, you can follow the same to get it done in the EI.
A sample mediation sequence will be as following
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="oauth2-sequence" xmlns="http://ws.apache.org/ns/synapse">
<!-- token generation to the oauth server's token endpoint -->
<!-- add the base64 encoded credentials -->
<property name="client-authorization-header" scope="default" type="STRING" value="MDZsZ3BTMnh0enRhOXBsaXZGUzliMnk4aEZFYTpmdE4yWTdLcnE2SWRsenBmZ1RuTVU1bkxjUFFh" />
<property name="request-body" expression="json-eval($)" scope="default" type="STRING" />
<property name="resource" expression="get-property('axis2', 'REST_URL_POSTFIX')" scope="default" type="STRING" />
<!-- creating a request payload for client_credentials -->
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<root xmlns="">
<grant_type>client_credentials</grant_type>
</root>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args></args>
</payloadFactory>
<!-- set related headers to call the token endpoint -->
<header name="Authorization" expression="fn:concat('Basic ', get-property('client-authorization-header'))" scope="transport" />
<header name="Content-Type" value="application/x-www-form-urlencoded" scope="transport" />
<property name="messageType" value="application/x-www-form-urlencoded" scope="axis2" type="STRING" />
<property name="REST_URL_POSTFIX" value="" scope="axis2" type="STRING" />
<!-- change the token endpoint -->
<call blocking="true">
<endpoint>
<http method="POST" uri-template="https://localhost:9443/oauth2/token" />
</endpoint>
</call>
<!-- append the acquired access token and make the call to the backend service -->
<property name="bearer-token" expression="json-eval($.access_token)" scope="default" type="STRING" />
<property name="REST_URL_POSTFIX" expression="get-property('resource')" scope="axis2" type="STRING" />
<header name="Authorization" expression="fn:concat('Bearer ', get-property('bearer-token'))" scope="transport" />
<payloadFactory media-type="json">
<format>$1</format>
<args>
<arg evaluator="xml" expression="get-property('request-body')" />
</args>
</payloadFactory>
<!-- perform a send or call to complete the execution of the backend service call in EI -->
</sequence>
Hope this helps you to start with implementation.

Related

Unexpected error during sending message out - ERROR {org.apache.synapse.core.axis2.Axis2Sender}

When i try to call a remote web-service using a dynamic uri-template in send mediator, i receive this error.
The url of the resource to call is : https://ec.europa.eu/esco/api/resource/skill?uri=http://data.europa.eu/esco/skill/a59708e3-e654-4e37-8b8a-741c3b756eee&language=it
For this purpose i use below in-sequence and out-sequence:
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="EscoInSequence" xmlns="http://ws.apache.org/ns/synapse">
<property expression="$url:resource" name="resource" scope="default"
type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="$url:uri" name="uri"
scope="default" type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<property expression="$url:language" name="language" scope="default"
type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<property
expression="concat('https://ec.europa.eu/esco/api/resource/',$ctx:resource,'?uri=',$ctx:uri,'&language=',$ctx:language)"
name="UrlToEsco" scope="default" type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<payloadFactory media-type="text">
<format>$1</format>
<args>
<arg evaluator="xml" expression="$ctx:UrlToEsco"
literal="false" xmlns:ns="http://org.apache.synapse/xsd"/>
</args>
</payloadFactory>
<send>
<endpoint>
<http method="GET" uri-template="{UrlToEsco}"/>
</endpoint>
</send>
<enrich>
<source clone="true" type="body"/>
<target action="child" property="rispostaEsco" type="property"/>
</enrich>
<loopback/>
</sequence>
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="EscoOutSequence" xmlns="http://ws.apache.org/ns/synapse">
<send/>
</sequence>
When i try to call my api using a static uri ( https://ec.europa.eu/esco/api/resource/skill?uri=http://data.europa.eu/esco/skill/a59708e3-e654-4e37-8b8a-741c3b756eee&language=it ) i haven't problem, but when i use UrlToEsco property i obtain this error :
TID[-1234] [EI] [2019-09-03 12:31:53,029] ERROR
{org.apache.synapse.core.axis2.Axis2Sender} - Unexpected error during
sending message out
org.apache.axis2.description.ClientUtils.inferOutTransport(ClientUtils.java:86)
org.apache.synapse.core.axis2.DynamicAxisOperation$DynamicOperationClient.executeImpl(DynamicAxisOperation.java:116)
org.apache.axis2.client.OperationClient.execute(OperationClient.java:149)
org.apache.synapse.core.axis2.Axis2FlexibleMEPClient.send(Axis2FlexibleMEPClient.java:603)
org.apache.synapse.core.axis2.Axis2Sender.sendOn(Axis2Sender.java:85)
org.apache.synapse.core.axis2.Axis2SynapseEnvironment.send(Axis2SynapseEnvironment.java:547)
org.apache.synapse.endpoints.AbstractEndpoint.send(AbstractEndpoint.java:384)
org.apache.synapse.endpoints.HTTPEndpoint.send(HTTPEndpoint.java:85)
org.apache.synapse.mediators.builtin.SendMediator.mediate(SendMediator.java:123)
org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:108)
org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:70)
org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:158)
org.apache.synapse.rest.Resource.process(Resource.java:364)
org.apache.synapse.rest.API.process(API.java:399)
org.apache.synapse.rest.RESTRequestHandler.apiProcess(RESTRequestHandler.java:123)
org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:101)
org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:69)
org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:303)
org.apache.synapse.core.axis2.SynapseMessageReceiver.receive(SynapseMessageReceiver.java:92)
org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
org.apache.synapse.transport.passthru.ServerWorker.processNonEntityEnclosingRESTHandler(ServerWorker.java:337)
org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:158)
org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
Uri templates variables should be named as follows uri.var.[parameterName] so for example uri.var.UrlToEsco.
Try renameing your property
<property expression="concat('https://ec.europa.eu/esco/api/resource/',$ctx:resource,'?
uri=',$ctx:uri,'&language=',$ctx:language)"
name="uri.var.UrlToEsco" scope="default" type="STRING"
xmlns:ns="http://org.apache.synapse/xsd"/>
And using it like so:
<send>
<endpoint>
<http method="GET" uri-template="{uri.var.UrlToEsco}"/>
</endpoint>
</send>

How to map field values while converting message JSON<->SOAP

I need to map values of several fields while message is sending from one system to another. For example receive SOAP message with status "START" and produce JSON message with status "BEGIN".
Is it possible to do this with WSO2 ESB (or with some help from other WSO2 products)?
You can use the PayloadFactory and Switch mediator.
A simple example:
<switch source="//status">
<case regex="START">
<property name="status" scope="default" type="STRING" value="BEGIN"/>
</case>
<default>
<property expression="//status" name="status" scope="default" type="STRING"/>
</default>
</switch>
<payloadFactory media-type="json">
<format>
{"status": $1}
</format>
<args>
<arg expression="get-property('status')"/>
</args>
</payloadFactory>
I hope this helps.

WSO2 ESB: Display dataService response

How do you display the response returned by calling a webservice endpoint on a sequence?
Below is the sequence that I use. I would like to display the return value from the dataservice called "CDServiceEndpoint" on the wso2carbon.log. Is that possible? If not, how can I get the data displayed.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="ConcurGetADPExtractFlow" onError="GeneralErrorHandler">
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="current-context-details" expression="concat(get-property('current-context-details'), ', ConcurGetADPExtractFlow')" />
<property name="scenario" value="ConcurGetADPExtractFlow" />
<log level="custom">
<property name="DEBUGGING" value="ConcurGetADPExtractFlow" />
<property name="start-date" value="2015-02-23" />
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="End Date" expression="get-property('current-date')" />
</log>
<xslt key="Concur_Get_ADP_Extract_Transformation">
<property name="start-date" value="2015-03-02" />
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="end-date" expression="get-property('current-date')" />
</xslt>
<property name="post-data-service-sequence" value="ConcurTransformADPExtractFlow" />
<property name="OUT_ONLY" value="false" />
<send receive="DataServiceInvocationErrorFlow">
<endpoint key="ConcurDataServiceEndpoint" />
</send>
<description>Sends a request to the data service for the ADP extract data.</description>
</sequence>
Below is how my DataServiceInvocationErrorFlow looks like.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="DataServiceInvocationErrorFlow">
<filter xmlns:ns="http://org.apache.synapse/xsd" xmlns:m="http://ws.wso2.org/dataservice" xmlns:ns3="http://org.apache.synapse/xsd" xpath="//m:DataServiceFault">
<then>
<log level="custom">
<property name="status" value="data-service-fault" />
</log>
<property name="error_message" expression="//m:DataServiceFault" />
<sequence key="GeneralErrorHandler" />
<drop />
</then>
<else>
<filter source="string-length(get-property('ERROR_MESSAGE'))" regex="0.0">
<then>
<filter xpath="//soapenv:Fault">
<then>
<log level="custom">
<property name="status" value="ERROR" />
</log>
<property name="error_message" expression="//soapenv:Fault" />
<sequence key="GeneralErrorHandler" />
<drop />
</then>
<else>
<log level="custom">
<property name="status" value="success response from DSS" />
</log>
<filter source="string-length(normalize-space(get-property('post-data-service-sequence')))" regex="0.0">
<then />
<else>
<property name="temp-post-data-service-sequence" expression="get-property('post-data-service-sequence')" />
<property name="post-data-service-sequence" value="" />
<sequence key="{get-property('temp-post-data-service-sequence')}" />
</else>
</filter>
</else>
</filter>
</then>
<else>
<property name="error_message" expression="get-property('ERROR_MESSAGE')" />
<sequence key="GeneralErrorHandler" />
<drop />
</else>
</filter>
</else>
</filter>
</sequence>
If by CDServiceEndpoint you meant ConcurDataServiceEndpoint, then you are already handling the response from that endpoint in your DataServiceInvocationErrorFlow sequence that you defined on the Send mediator, which by the way is confusingly named, since your receive sequence will run no matter if you get an error response or a good one. All you need to do is log it inside DataServiceInvocationErrorFlow using Log mediator.
Had you not defined a receive sequence on your Send mediator, the response would have gotten to your outSequence, where you can log it with Log mediator too.

In WSO2 ESB, how to store cookies and use them later for authentication?

I have a service that I am calling, which is returning back cookies with authentication info. How do I store the cookies, and use them later?
This is not working for me. I see the cookies being returned back, but I don't see it getting set.
<!-- LOGON CALL -->
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="setCookieHeader" expression="$trp:cookie"></property>
<payloadFactory media-type="xml">
<format><somexml></somexml></format>
</payloadFactory>
<call>
<endpoint>
<address uri="http://serviceurl.domain.com" format="pox"></address>
</endpoint>
</call>
<log>
<property name="cookie" expression="get-property('setCookieHeader')"></property>
</log>
<!-- The Above Log statement prints correctly -->
<!-- Second Service CALL -->
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="setCookieHeader" expression="$trp:cookie"></property>
<payloadFactory media-type="xml">
<format><somexml></somexml></format>
</payloadFactory>
<call>
<endpoint>
<address uri="http://serviceurl.domain.com" format="pox"></address>
</endpoint>
</call>
To get cookies from the response :
<property name="setCookieHeader" expression="$trp:Set-Cookie" scope="default" type="STRING"/>
To set cookies for the next request :
<property name="Cookie" expression="$ctx:setCookieHeader" scope="transport"/> <!-- if setCookieHeader has been initialized before -->
Or
<property name="Cookie" expression="$trp:Set-Cookie" scope="transport"/>

Issue in getting response back while connecting to Oracle DB in WSO2 esb

I am working on sample application in WSO2 esb
which connects to Oracle Database and return the response of a query. Below mentioned is my service. Issue I am facing is I am not getting the response back after execution of service.However I am able to see the value returned as a query response, but not able to render it in response document.
Can anybody suggest, what I am missing?
DB credentials fields have been hashed.
Proxy :
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="getEmployeeDetails"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<property name="OUT_ONLY" value="true" scope="default" type="BOOLEAN"/>
<log level="full" category="DEBUG"/>
<dblookup>
<connection>
<pool>
<password>****</password>
<user>****</user>
<url>****</url>
<driver>oracle.jdbc.xa.client.OracleXADataSource</driver>
</pool>
</connection>
<statement>
<sql>select firstname from employee where lastname = 'pawar'</sql>
<result name="firstname" column="firstname"/>
</statement>
</dblookup>
<log level="custom">
<property name="firstname" expression="get-property('firstname')"/>
</log>
<payloadFactory media-type="xml">
<format>
<GetEmployeeDetailsResponse xmlns="">
<out>$1</out>
</GetEmployeeDetailsResponse>
</format>
<args>
<arg evaluator="xml" expression="get-property('firstname')"/>
</args>
</payloadFactory>
</inSequence>
<outSequence>
<log level="full" category="DEBUG"/>
</outSequence>
</target>
<publishWSDL uri="file:/development/data/wso2/wsdl/Employee.wsdl"/>
<description/>
</proxy>
You have to send back the message generated by your payloadFactory in your inSequence :
<header name="To" action="remove"/>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
<send/>
Your mediation is "OUT_ONLY", so, your outSequence will never been executed