How exactly works this payloadFactory chained with an header mediator in a WSO2 ESB project? - soap

I am absolutly new in WSO2 and I am working on a WSO2 Enterprise Integrator project containing this ESB project section (I think that my question is only related to ESB).
So my doubt is: I have an XML file defining an API. The flow starts with a payloadFactory mediator, something like this:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/xxxTest2" name="xxxTest2" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET">
<inSequence>
<!-- Create empty message to get all samples from DSS -->
<!-- Get Sample ID -->
<payloadFactory media-type="xml">
<format>
<body/>
</format>
<args>
<arg evaluator="xml" expression="get-property('uri.var.int_val')" xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd"/>
</args>
</payloadFactory>
<!--
Adding an header that defines the actionr related to the "FindNotProcessed" DSS service
used to retrieve all the unprocessed resource on the DB
-->
<header name="Action" scope="default" value="urn:FindNotProcessed"/>
<!-- Log the request generated by the previous payloadFactory mediator: -->
<log level="full"/>
...............................................................
...............................................................
...............................................................
</api>
My doubt is: this payloadFactory mediator generate and empty message because its content is:
<format>
<body/>
</format>
The next element in the chain is the header mediator:
<header name="Action" scope="default" value="urn:FindNotProcessed"/>
used to set a new header having name="Action" that specify (as value) the name of a DSS service to obtain some data from the DB.
Finnally the next element in the chain is a log mediator. It seems to me that is is used to log the message generated by the concatenation of the previous payloadFactory mediator chianed with the following header mediator.
This log mediator generate this log:
TID: [-1234] [] [2017-03-28 10:05:30,943] INFO {org.apache.synapse.mediators.builtin.LogMediator} -
To: /glisTest2, WSAction: urn:FindNotProcessed, SOAPAction: urn:FindNotProcessed, MessageID: urn:uuid:95913219-2ad1-4488-a260-78693f3bbde2, Direction: request,
Envelope:
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<body xmlns="http://ws.apache.org/ns/synapse"/>
</soapenv:Body>
</soapenv:Envelope> {org.apache.synapse.mediators.builtin.LogMediator}
My doubts are:
1) Why is it generating an XML message that embedd a soapenv structure?
2) It depends by the fact that the header meadiator defines scope="default" that should coincide to Synapse. Because reading the official documentation:
https://docs.wso2.com/display/ESB481/Header+Mediator
it says:
Scope: Select Synapse if you want to manipulate SOAP headers. Select
Transport if you want to manipulate HTTP headers.
so I think that settings in this way is generating a SOAP message and so is the reason because my message is into the soapenv structure.
Is it or am I missing something?

By default, all the messages in the WSO2 EI/ESB will be treated as SOAP messages, that's why your payload is enclosed in the soap envelope.
Headers actually work when you send the message to an endpoint, so if you have an endpoint http://hostname:port/abc/xyz , the Action (Soap Action) of the message will be set as urn:FindNotProcessed. It means that the message will go to the urn:FindNotProcessed operation of the endpoint, provided the endpoint is a soap endpoint.
Thanks

Related

How to create a Rest API from SOAP Backend with WSO2 API Manager

I am new working with wso2 api manager, and I need to pause a SOAP service and take it to a REST API, I have seen all the documentation, but none responds to my problem, I already created an input sequence
getProdRequestInSequence.xml
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="getProdRequestInSequence" ><!-- This is the SOAP action which the backend SOAP operation expects, we set it in a header mediator --><header description="SOAPAction" name="SOAPAction" scope="transport" value="http://localhost:81/soap/products.php/query/getProd"/><!-- We are storing the input values which the end users input for these values into these two properties --><property name="uri.var.categoria" expression="$url:categoria"/>
<!-- Since we do not want the URL pattern we mentioned to be sent to the backend we need to add the below property to remove it --><property name="REST_URL_POSTFIX" scope="axis2" action="remove"/><!-- Now we need to create the actual payload which the backend requires. For that we use the payload factory mediator --><payloadFactory description="transform" media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:quer="http://localhost:81/soap/products.php/query/">
<soapenv:Header/>
<soapenv:Body>
<quer:getProd>
<quer:categoria>$1</quer:categoria>
</quer:getProd></soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg expression="get-property(‘uri.var.categoria’)"/>
</args>
</payloadFactory><!-- Here we are setting the content type which the web service expects --><property description="messageProperty" name="messageType" scope="axis2" type="STRING" value="application/soap+xml"/>
</sequence>
xml_to_json_out_message.xml
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="xml_to_json_out_message" >
<!-- Transforms the response to a JSON -->
<property description="message" name="messageType" scope="axis2" type="STRING" value="application/json"/>
</sequence>
Now, according to the documentation, these files once created, I charge in the Message Mediation Policies, and should work perfectly
but it gives me this error
Gateway Failures
Failed to Publish Environments
Production and Sandbox
Error in deploying the sequence to gateway###
Thanks in advance for the help
getProdRequestInSequence.xml
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="getProdRequestInSequence" ><!-- This is the SOAP action which the backend SOAP operation expects, we set it in a header mediator --><header description="SOAPAction" name="SOAPAction" scope="transport" value="http://localhost:81/soap/products.php/query/getProd"/><!-- We are storing the input values which the end users input for these values into these two properties --><property name="uri.var.categoria" expression="$url:categoria"/>
<!-- Since we do not want the URL pattern we mentioned to be sent to the backend we need to add the below property to remove it --><property name="REST_URL_POSTFIX" scope="axis2" action="remove"/><!-- Now we need to create the actual payload which the backend requires. For that we use the payload factory mediator --><payloadFactory description="transform" media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:quer="http://localhost:81/soap/products.php/query/">
<soapenv:Header/>
<soapenv:Body>
<quer:getProd>
<quer:categoria>$1</quer:categoria>
</quer:getProd></soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg expression="get-property(‘uri.var.categoria’)"/>
</args>
</payloadFactory><!-- Here we are setting the content type which the web service expects --><property description="messageProperty" name="messageType" scope="axis2" type="STRING" value="application/soap+xml"/>
</sequence>
and the output sequence
xml_to_json_out_message.xml
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="xml_to_json_out_message" >
<!-- Transforms the response to a JSON -->
<property description="message" name="messageType" scope="axis2" type="STRING" value="application/json"/>
</sequence>
Now, according to the documentation, these files once created, I charge in the Message Mediation Policies, and should work perfectly
but it gives me this error
Gateway Failures
Failed to Publish Environments
Production and Sandbox
Error in deploying the sequence to gateway
Thanks in advance for the help
There is a syntax mismatch in the provided getProdRequestInSequence.xml synapse configuration file.
The uri.var.categoria has been enclosed with a special character (‘) inside the get-property() method and which is not a single-quote symbol ('). Please find the updated synapse configuration file below
getProdRequestInSequence.xml
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="getProdRequestInSequence" >
<!-- This is the SOAP action which the backend SOAP operation expects, we set it in a header mediator -->
<header description="SOAPAction" name="SOAPAction" scope="transport" value="http://localhost:81/soap/products.php/query/getProd"/>
<!-- We are storing the input values which the end users input for these values into these two properties -->
<property name="uri.var.categoria" expression="$url:categoria"/>
<!-- Since we do not want the URL pattern we mentioned to be sent to the backend we need to add the below property to remove it -->
<property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>
<!-- Now we need to create the actual payload which the backend requires. For that we use the payload factory mediator -->
<payloadFactory description="transform" media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:quer="http://localhost:81/soap/products.php/query/">
<soapenv:Header/>
<soapenv:Body>
<quer:getProd>
<quer:categoria>$1</quer:categoria>
</quer:getProd>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg expression="get-property('uri.var.categoria')"/>
</args>
</payloadFactory>
<!-- Here we are setting the content type which the web service expects -->
<property description="messageProperty" name="messageType" scope="axis2" type="STRING" value="application/soap+xml"/>
</sequence>
Resolution for the above-mentioned issue:
At the moment Your approach has a special character "‘" which is
common if you use a mac book for the developments. Replacing the
single quotes with the correct character will resolve your current
issues.
Recommended Approach with WSo2 API Manager :
WSO2 API Manager has the capability of exposing a SOAP Service/API as a REST API Out of the box without any sequences or synapse level configurations.
To get the REST service exposed with WSO2 API Manager you just have to provide the backend URL and the WDSL file with this feature.
Please refer to the Documentation here.

different Content-Types in the end point response

I have a rest API with the Content-Type = application/json, provided by a tomcat server.
This means that all the responses are supposed to be in the json format.
The rest API is called by the WSO2 ESB to pass some data.
in case that the application providing the rest API is down (but the tomcat server is still up), the tomcat server replays with the http code=404 with the Content-Type=text/html (sending the HTML page "The requested resource is not available.") what results into the ESB error "Error while building message" exception and ESB crashes and losses the message.
Can you please suggest how to handle such a scenario? I'd need to receive the msg and react on this event. Is there perhaps a way how to dynamically switch content-types?
Can you try this with your own modification:
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="fault_filter_based_http_status_code" trace="disable">
<filter regex="401" source="get-property('axis2', 'HTTP_SC')">
<then>
<makefault version="soap11">
<code xmlns:soap11Env="http://schemas.xmlsoap.org/soap/envelope/" value="soap11Env:Server"/>
<reason value="Unauthorized to access the resource"/>
<role/>
</makefault>
<send/>
</then>
<else/>
</filter>
<filter regex="500" source="get-property('axis2', 'HTTP_SC')">
<then>
<makefault version="soap11">
<code xmlns:soap11Env="http://schemas.xmlsoap.org/soap/envelope/" value="soap11Env:Server"/>
<reason value="Internal Server Error Occurred"/>
<role/>
</makefault>
<send/>
</then>
<else/>
</filter>
</sequence>
Take a look: http://harshcreationz.blogspot.com/2016/02/common-and-error-handling-sequences.html

Rest Service on WSO2 ESB API with a Mal Formed XML request

I have created an api proxy to call my rest service, but when I send in a Mal formed XML request, I only receive an HTTP status code 202.
I have coded my service to handle this mal formed xml, and I just want the ESB to pass through the request.
Here is the code to my ESB API:
<?xml version="1.0" encoding="UTF-8"?>
<api xmlns="http://ws.apache.org/ns/synapse" name="myApi" context="/restService">
<resource methods="POST">
<inSequence>
<send>
<endpoint>
<address uri="http://myserver/MyRestService"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence/>
</resource>
</api>
Thanks
In this case, ESB should be able to successfully send the message to the backend. By enabling wire logs you can make sure message sending correctly to the backend.
If you are not expecting any response from your backend, Please set out_only property in your inseqeunce

WSO2 HTTP Response

I am using WSO2 to send rest request, which I am able to do. But I would like to have some logic before I send the response to the client.
The Backend Rest service returns "Successful" as a response string. I have a Java code which used to do this, and I would like to use the same logic in WSO2. The logic is simple
1. If
the HTTP Status is greater than eq to 200 and less than 300 and resonseStr.equalsIgnoreCase("Successful") THEN
return "RetCode=C;Message=Success"
ELSE
return "RetCode=F;Message=Failed because Itegration Exception";
responseStr is the response from the Backend Rest Service.
My API looks like this:
<api xmlns="http://ws.apache.org/ns/synapse" name="TririgaApi" context="/tririga">
<resource methods="GET" url-mapping="/employee">
<inSequence>
<sequence key="conf:/tririgaConf"/>
<property name="POST_TO_URI" value="true" scope="axis2"/>
<send>
<endpoint>
<http trace="enable" method="GET" uri-template="http://{uri.var.service.host}:{uri.var.service.port}/html/en/default/rest/Integration?USERNAME={uri.var.service.user}&PASSWORD={uri.var.service.pass}&ioName={uri.var.wfname}"/>
</endpoint>
</send>
</inSequence>
</resource>
</api>
Thanks
Add an outSequence to your api and implement your mediation inside it
You can access to http status code with $axis2:HTTP_SC
You can test it's value with filter mediator
You can create a message with payloadFactory mediator

Proxy a RESTful service using SOAP with WSO2 ESB

We want to proxy a RESTful web service with SOAP.
The REST service uses the GET method and accepts inputs via query parameters. It produces a resource of type application/csv.
Does WSO2 ESB/Synapse support such a scenario, and is there an example available?
Example Request
SOAP Proxy Request:
<request>
<fromDate>2012-01-01</fromDate>
<toDate>2012-12-31</toDate>
</request>
REST Endpoint Request:
http://localhost/person?fromDate=2012-01-01&toDate=2012-12-31
Example Response
REST Endpoint Response
"Name","Age","Sex"
"Geoff","22","Male"
SOAP Proxy Response
<person>
<name>Geoff</name>
<age>22</age>
<sex>Male</sex>
<person>
Many thanks.
If I understand you correctly, you want to expose a REST service as a SOAP service, so that SOAP clients can access your REST service through the ESB?
If that is the case, it is possible :) You should check out sample 152 from these: http://docs.wso2.org/wiki/display/ESB451/Proxy+Service+Samples
It'll explain how you take a SOAP request and pass it to a REST backend and then transform the REST response into a SOAP response.
EDIT: Here's a sample configuration on how to do what you asked in the comments, hopefully it will get you started :)
<proxy xmlns="http://ws.apache.org/ns/synapse" name="RESTProxy" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<!-- We set the HTTP Method we want to use to make the REST request here -->
<property name="HTTP_METHOD" value="GET" scope="axis2"/>
<!-- This is where the magic happens, for what you want i.e. mapping SOAP "params" to REST query param's -->
<property name="messageType" value="application/x-www-form-urlencoded" scope="axis2"/>
<send>
<endpoint>
<!-- This is the RESTful URL we are going to query, like the one in the ESB example 152 -->
<address uri="http://localhost/person" />
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full"/>
<property name="messageType" value="text/xml" scope="axis2"/>
<send/>
</outSequence>
</target>
<description></description>
</proxy>
Then the SOAP request you make to the ESB should be something like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<person>
<fromDate>2012-01-01</fromDate>
<toDate>2012-12-31</toDate>
</person>
</soapenv:Body>
</soapenv:Envelope>
Hope that helps :)
Hope This will be very helpful you to understand of SOAP Client and REST Service communication
http://docs.wso2.org/display/ESB460/Using+REST+with+a+Proxy+Service#UsingRESTwithaProxyService-SOAPClientandRESTService
You can use class mediator to extract the SOAP parameters using XPATH. Than build the REST URL and send it back to IN sequence flow.
1. you need to get the value from SOAP PROXY
2. you need to store it in a local variable
3. you need to pass the value to the REST SERVICE using Query Parameters
4. you need to format the response from REST Service to an SOAP Format
The SOAP Request will be,
<request>
<fromDate>2012-01-01</fromDate>
<toDate>2012-12-31</toDate>
</request>
You can store the value from SOAP PROXY Request as,
<proxy xmlns="http://ws.apache.org/ns/synapse" name="RESTProxy" transports="https,http" statistics="disable" trace="disable" startOnLoad="true><target>
<inSequence>
<property name="fromDate" expression="//fromDate" scope="default" type="STRING"/>
<property name="toDate" expression="//toDate" scope="default" type="STRING"/>
Then you can pass the values to the REST Service by,
<send>
<endpoint>
<http method="GET" uri-template="http://localhost/person?fromDate=={get-property('fromDate')}&toDate={get-property('toDate')}"/>
</endpoint>
</send>
</inSequence>
Then You can Format the Response using PayloadFactory mediator,
<outSequence>
<payloadFactory media-type="xml">
<format>
<person>
<Name>$1</Name>
<Age>$2</Age>
<Sex>$3</Sex>
</person>
</format>
<args>
<arg evaluator="json" expression="$.Name"/>
<arg evaluator="json" expression="$.Age"/>
<arg evaluator="json" expression="$.Sex"/>
</args>
</payloadFactory>
<send/>
</outSequence>
</target>
<description/>
</proxy>
So the Response of Proxy will be,
<person>
<name>Geoff</name>
<age>22</age>
<sex>Male</sex>
<person>