Replace a body parameter based on value that client sent - wso2

I created a API in WSO2 integrator studio contain the below body to receive the application requests.
{"count": "2000",
"Name": "22312312"
},
For responding to above request, I have to send the following JSON body toward the endpoint:
{"count": "2000",
"Name": "BANK"
},
As you can see, the difference between to bodies is about "NAME" value. In this scenario, each client send its own unique number in "Name" parameter, and I have to translate it into a String Name (in WSO2 Enterprise integrator) and send it to the endpoint.
How can I manage this in Integrator studio?

Here is how you can do it. You can have the mappings in a LocalEntry and then use a combination of Property mediators and Enrich mediator to select the Name and replace the Code. Check the following.
Local Entry
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="Mappings" xmlns="http://ws.apache.org/ns/synapse">
<Mappings xmlns="">
<bank>
<code>22312312</code>
<name>bank</name>
</bank>
<bank>
<code>22312313</code>
<name>bank2</name>
</bank>
<bank>
<code>22312314</code>
<name>bank3</name>
</bank>
</Mappings>
</localEntry>
API
<?xml version="1.0" encoding="UTF-8"?>
<api context="/bank" name="BankAPI" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST" url-mapping="/code">
<inSequence>
<property expression="get-property('Mappings')" name="localEntry" scope="default" type="OM"/>
<property expression="json-eval($.Name)" name="BankCode" scope="default"/>
<property expression="$ctx:localEntry//bank[code = $ctx:BankCode]/name/text()" name="BankName"/>
<enrich>
<source type="property" clone="true" property="BankName"/>
<target xpath="json-eval($.Name)"/>
</enrich>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
Request and Response
{
"count": "2000",
"Name": "22312313"
}
{
"count": "2000",
"Name": "bank2"
}
If your mapping is dynamic, for example, if you need to pass the code to another API and get the Name, you can still use the same logic above with the Enrich mediator. Instead of reading from the LocalEntry you can get the data from the API.

Related

Concat operation in property mediator of wso2 is invalid

<property name="Code" expression="json-eval($.Code)" scope="default" type="STRING"/>
<property name="Endpoint" expression="json-eval($.data.InternalConfig.Events.Code.Endpoint)" scope="default"
<property expression="fn:concat(json-eval($.data.InternalConfig.Events'.'get-property('Code')'.'Endpoint)" name="URL" type="STRING" scope="default"/>
one property is fetching from payload and another from respository , i am trying to merge into 1 property
I believe that you are trying to extract the data from the payload using dynamic values during the runtime. If yes, we can make use of Script Mediator in the WSO2 platform to access the JSON payloads.
For example:
Given below is a sample payload, and you are trying to extract the data: 'some value here' from the payload using the code and endpoint values
{
"userId": 10,
"code": 1,
"body": {
"id": 2,
"endpoint": "some-key",
"1": {
"anotherId": 30,
"title": "Lorum ipsum",
"some-key": "some value here"
}
}
}
Given below is a sample mediation sequence with the Script mediator to achieve your requirement
<?xml version="1.0" encoding="UTF-8"?><sequence xmlns="http://ws.apache.org/ns/synapse" name="mediation-sequence">
<script language="js">
<![CDATA[
// read the JSON payload from the message context
var payload = mc.getPayloadJSON();
// read the property values
var code = payload["code"];
var endpoint = payload["body"]["endpoint"];
var extracted_value = payload["body"][code][endpoint];
// set the extracted value as property to message context
mc.setProperty("ExtractedValue", extracted_value);
]]>
</script>
<log level="custom">
<property name="Extracted value" expression="$ctx:ExtractedValue" />
</log>
</sequence>
Hope this helps you to achieve your requirement.

How can i use an JSON or SOAP attribute into a Path URL Param or a Query Param WSO2 Entrerprise Integrator

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

How to remove soap envelope in wso2 esb

I am using wso2esb 4.8.0,I am trying to connect my legacy systems which can accept rest calls with post method.
I am sending the same to them but soap envelope is adding by wso2 .
current message :
<?xml version='1.0' encoding='UTF-8'?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.comapny.org/" xmlns:env="http://com.comany.inn/Envelope"><soap:Header xmlns:p="http://webservices.usedin.com/PService">
</soap:Header><soap:Body>
<requested id="12345">
<authen login="username" password="password">
<parm name="COMPANY" value="myname"/>
</authen>
<actionReq production="doctor" id="1234" type="TINGS">
<parm name="name" value="12345"/>
</actionReq>
</requested>
</soap:Body></soap:Envelope>
Expected one:
<requested id="12345">
<authen login="username" password="password">
<parm name="COMPANY" value="myname"/>
</authen>
<actionReq production="doctor" id="1234" type="TINGS">
<parm name="name" value="12345"/>
</actionReq>
</requested>
Since this rest cal i can't use format also "format=pox" like in soap services.
my code is like this.
</xquery>
<send>
<http uri-template="http://******/webservices/***.php" method="post">
</send>
Do I need to add any property to remove soap envelope for esb out request.
Try to add this property before send mediator :
<property name="messageType" value="application/xml" scope="axis2"/>

Is it possible to extract and/or pass along a query parameter in ESB REST proxy service

I am building a ReST to ReST proxy service. I need to be able to pass along some query parameters to that service that are incoming with the request. E.g.
myhost.zz/proxyService?foo=1&bar=2
When I define such proxy - and later try to extract the value of 'foo' I get null.
So is it possible to achieve?
You shouls define an API (if you really want a proxy service, look at the end of this answer) :
<api xmlns="http://ws.apache.org/ns/synapse" name="proxyService" context="/proxyService">
<resource methods="POST GET OPTIONS DELETE PUT">
<inSequence>
<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2" type="STRING"></property>
<log level="custom">
<property name="foo" expression="get-property('query.param.foo')"></property>
<property name="bar" expression="get-property('query.param.bar')"></property>
</log>
</inSequence>
</resource>
</api>
call it with this url : http://host:port/proxyService?foo=12&bar=14
look at wso2-esb-service.log : INFO __SynapseService foo = 12, bar = 14
in the "resource", you can define a uri-template (URL Style = uri-template) with, for exemple, "/{scope}/*" and then when you call your api with http://host:port/proxyService/toto?foo=12&bar=14, you can access the "scope" with get-property('uri.var.scope')
to send a REST request, use a http endpoint with a uri-template using the same logic : uri-template="http://other_host:port/Service/{uri.var.scope}/truc?abc={query.param.foo}&dfc={query.param.bar}"
-->
If you want to use a proxy service, you can access to query parameters like this :
request : http://esb:8280/services/MonService?param1=val1&param2=val2
<property name="PARAM1"
expression="tokenize(substring-after(syn:get-property('To'),'param1='),'&')"
scope="default"
type="STRING"/>
<property name="PARAM2"
expression="tokenize(substring-after(syn:get-property('To'),'param2='),'&')"
scope="default"
type="STRING"/>
you can use synapse xpath variable $url to read the query parameter values.
check this[1] for example.
Reading Dynamic query parameter in WSO2 APIM

WSO2 ESB - WS Proxy error "EPR for Operation not found" when SOAPAction = ""

We´re getting this error:
The endpoint reference (EPR) for the Operation not found is [OUR ENDPOINT] and the WSA Action = . If this EPR was previously reachable, please contact the server administrator.
Our SOAPActions are declared as "", as allowed by specification.
The following answer explains why it´s happening: https://stackoverflow.com/a/15556669/1553243. However, we can´t afford the suggested workarounds, 1 and 3. We can´t have our vendors declare their SOAPActions, and we can´t have our clients always append the operation name. Workaround 2 doesn´t work when SOAPAction = "", either.
The answer also states they were in a process of fixing this limitation, but I´m using a one year later release and nothing.
Is there any other workaround?
Our proxy is defined like:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="TEST"
transports="https,http"
statistics="enable"
trace="enable"
startOnLoad="true">
<target>
<inSequence>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<log/>
</faultSequence>
<endpoint>
<wsdl service="TESTService"
port="TESTServicePort"
uri="http://localhost:8080/test?wsdl"/>
</endpoint>
</target>
<publishWSDL uri="http://localhost:8080/test?wsdl"/>
<description/>
</proxy>
Since ESB v4.8, using pass-through http transport, you can add this parameter to your proxy def :
<parameter name="disableOperationValidation" locked="false">true</parameter>
In your webservice implementation class add the annotation #WebMethod to define the SOAP Action for individual operations. for example
#WebService
#SOAPBinding(style=Style.RPC)
public class BookingServiceWS {
#WebMethod(action="getBooking",operationName="getBooking")
public BookingServiceResponse getBooking(String pnr){
}
This will generate the WSDL with SOAP Action defined as
<operation name="getBooking">
<soap:operation soapAction="getBooking"/>
<input>...</input>
<output>...</output>
</operation>
This should be able to resolve the issue
Then you have control at ESB level? If so, you define the SOAPAction property at ESB level.
That is, when request hits the sequence, if you are sure where to route the request, at that time set SOAPAction property before the send mediator
<property name="SOAPAction" value="urn:OPERATION NAME"
scope="transport"/>
Workaround 2: You can specify the SOAPAction in the client side code. Specify it in the options as shown below.
options.setAction("urn:SOAPAction");