WSO2 REST to SOAP passing operation parameters - rest

Using WSO2 ESB 4.8.1, I have configured a WSDL proxy that I want to access over REST. the proxy points to the SOAP WSDL URI and has publish WSDL turned on. This seem to work fine and I can see the service and its various operations in the WSO2 admin UI. Likewise if I go to localhost:8280/services/
The questions is how do I pass operation specific parameters when accessing over HTTP REST?
Let's say my FooService OperationX expects a "p1" parameter, can I pass this directly when accessing localhost:8280/services/FooService/OperationX in a browser?
I tried for example localhost:8280/services/FooService/SomeOperation?p1=somevalue, but always get a validation error that the required parameter is missing:
cvc-complex-type.2.4.b: The content of element 'axis2ns15:OperationXRequest' is not complete. One of '{"somenamespace":p1}' is expected.
Can this be supported by a basic WSDL proxy? Or do I need to use the API?

I think the better option for your scenario is to use api to access over REST. Here I have created an api (I used http://jsonplaceholder.typicode.com/comments as my REST back end) which gets the query parameter(postId) which was sent in REST request (http://172.22.99.96:8290/test/comments?postId=1) and assign that value to a property called mypostId inside the api.
Then I am modifying the payload by adding the mypostId property using payload factory mediator which will match to the echo service request(I have used echo service as the SOAP backend).
Then I use enrich mediator to change my soap envelope to match the echo service request soap envelope by adding "xmlns:echo="http://echo.services.core.carbon.wso2.org"" name space. Finally I am sending my created request to echo service proxy.
<api xmlns="http://ws.apache.org/ns/synapse" name="test" context="/test">
<resource methods="GET" uri-template="/comments?postId={postId}">
<inSequence>
<log level="custom">
<property name="Message Flow" value="--- Order GET ---"></property>
</log>
<log level="custom">
<property name="postId" expression="$url:postId"></property>
</log>
<property name="mypostId" expression="$url:postId"></property>
<call>
<endpoint>
<http method="GET" uri-template="http://jsonplaceholder.typicode.com/comments?postId={uri.var.postId}"></http>
</endpoint>
</call>
<payloadFactory media-type="xml">
<format>
<echo:echoInt xmlns:echo="http://echo.services.core.carbon.wso2.org">
<in>$1</in>
</echo:echoInt>
</format>
<args>
<arg evaluator="xml" expression="get-property('mypostId')"></arg>
</args>
</payloadFactory>
<log level="full"></log>
<log level="custom">
<property name="Message Flow" value="--- After Palyload factory---"></property>
</log>
<property name="extarctedBody" expression="$body"></property>
<log level="custom">
<property name="MyextarctedBody" expression="get-property('extarctedBody')"></property>
</log>
<log level="full"></log>
<enrich>
<source type="inline" clone="true">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:echo="http://echo.services.core.carbon.wso2.org"></soapenv:Envelope>
</source>
<target type="envelope"></target>
</enrich>
<log level="custom">
<property name="Message Flow" value="--- Order GET2 ---"></property>
</log>
<log level="full"></log>
<enrich>
<source type="property" clone="true" property="extarctedBody"></source>
<target xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:echo="http://echo.services.core.carbon.wso2.org" action="child" xpath="//soapenv:Envelope"></target>
</enrich>
<log level="full"></log>
<send>
<endpoint>
<address uri="http://localhost:8290/services/echo"></address>
</endpoint>
</send>
</inSequence>
<outSequence>
<send></send>
</outSequence>
</resource>
</api>
Hope this may help you .

Related

How to use the Fault Mediator to Respond with a Fault

I am trying to use the WSO2 EI Fault mediator but the Fault Response always gives me a void response message. The point here is to try to build custom Fault messages. My Sample API code:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/test" name="TestFaultAPI" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET" uri-template="/{teste}">
<inSequence>
<log description="" level="full" separator=";">
<property expression="get-property('uri.var.teste')" name="Path"/>
<property expression="get-property('transport','Content-Type')" name="ContentType"/>
</log>
<filter xpath="get-property('uri.var.teste') != '1234'">
<then>
<log description="" level="full">
<property name="Entrada" value=""Fault Way""/>
</log>
<makefault description="" version="soap11">
<code value="soap11Env:Client" xmlns:soap11Env="http://schemas.xmlsoap.org/soap/envelope/"/>
<reason value="Recruso incorreto"/>
<detail>incorrect Resource</detail>
</makefault>
<respond/>
</then>
<else>
<log level="full">
<property name="Caminho" value=""Corret Way""/>
</log>
<payloadFactory media-type="json">
<format>{
"Status":"Correct Resource"
}</format>
<args/>
</payloadFactory>
<respond/>
</else>
</filter>
</inSequence>
<outSequence/>
<faultSequence>
<log level="full" separator=";">
<property name="Caminho" value=""Entrou Fault Sequence""/>
</log>
<property description="" name="HTTP_SC" scope="axis2" type="INTEGER" value="400"/>
<payloadFactory media-type="json">
<format>{
"codigoErro":$1,
"detalhe":$2
}</format>
<args>
<arg evaluator="xml" expression="get-property('HTTP_SC','axis2')"/>
<arg evaluator="xml" expression="get-property('ERROR_DETAIL')"/>
</args>
</payloadFactory>
<respond/>
</faultSequence>
</resource>
</api>
So I have two questions:
1 - How can I make the custom fault messages response?
2 - Is it possible to use the fault mediator to change the sequence to the 'Fault Sequence' ?
I will put the answers here. Those are results of my study and experiences:
1 - How can I make the custom fault messages response?
The way to do it is use filter mediator for test a rule and build the messages to respond your request.
2 - Is it possible to use the fault mediator to change the sequence to the 'Fault Sequence'?
No. The fault sequence only start to be executed if a fault occurs. You can´t change the execution path by yourself using a mediator.
So It´s possible that other people with more experience then I answer different informations.
[],s
Marcello

How to convert text/xml response into application/json wso2 EI

I have a soap service and I need to expose this service as a rest api in Wso2 EI, content type is text/xml, I tried with
<property name="messageType" value="application/json"
scope="axis2"/>
in the outsequence, but it doesnt convert my response into a json. Can you please assist me on how to do it.
I tried this,
<resource methods="POST">
<inSequence>
<send>
<endpoint>
<address uri="http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<property name="messageType" value="application/json" scope="axis2"/>
<send/>
</outSequence>
</resource>
Reason for this is that WSO2 EI or ESB is developed in a manner where it responds to a SOAP request with a SOAP response by default. When you invoke the PROXY or API with SOAPAction and Content-Type: text/xml, EI understands this as a SOAP request and it'll respond with a SOAP response.
So if the client request is in SOAP-1.1 EI responds with a SOAP-1.1 response or if the client request is in SOAP-1.2 EI responds with a SOAP-1.2.
To bypass this behaviour they have provided an additional property as below.
<property name="IsClientDoingREST" scope="default" type="BOOLEAN" value="true"/>
So, before responding the client, properties should be set as below to get the expected behaviour of responding with a JSON.
<property name="IsClientDoingREST" scope="default" type="BOOLEAN" value="true"/>
<property name="messageType" scope="axis2" value="application/json"/>
This approach will help you to get the JSON response out of a SOAP request.
It should work perfectly. A sample REST API configuration given below.
<api xmlns="http://ws.apache.org/ns/synapse" name="CheckREST" context="/samplerest">
<resource methods="GET">
<inSequence>
<send>
<endpoint>
<http uri-template="http://localhost:8280/services/sampleSOAPproxy"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<property name="messageType" value="application/json" scope="axis2" type="STRING"/>
<send/>
</outSequence>
</resource>
</api>
If not working, please mention the EI version you are using.

Malformed Response - Invoking one ESB REST service from another

I am relatively new to WSO2 ESB,
Trying to invoke a REST Web service with GET parameter which is hosted on WSO2 ESB through another REST API.
This is a simple Web service(SampleREST) which replies with welcome messsage in XML format,
When i am invoking this service directly; i can see the correct response on browser, shown below
<Message xmlns="http://ws.apache.org/ns/synapse">WelcomeRanjan</Message>
Now i created another REST web service(InvokeSampleRest) which in turn invokes SampleREST web service with the parametrized GET,
the Invoke WebService Client returns me the XML response wrapped inside the mediator xml tag and other malformed tags, shown below
<mediate><<Message xmlns>"http://ws.apache.org/ns/synapse">WelcomeRanjan</Message></<Message xmlns></mediate>
Here is my Code for the SampleREST API
<?xml version="1.0" encoding="UTF-8"?>
<api xmlns="http://ws.apache.org/ns/synapse" name="SampleREST" context="/SampleRest" hostname="10.203.245.47">
<resource methods="GET" uri-template="/{str1}">
<inSequence>
<header name="To" action="remove"/>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
<payloadFactory>
<format>
<Message>$1</Message>
</format>
<args>
<arg expression="get-property('uri.var.str1')"/>
</args>
</payloadFactory>
<log level="full" separator=",">
<property name="sequence" value="*** Got Request ***"/>
</log>
<send/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
The code for the InvokeSampleREST code is as shown below( i am calling SampleREST service from here )
<?xml version="1.0" encoding="UTF-8"?>
<api xmlns="http://ws.apache.org/ns/synapse" name="InvokeSampleREST" context="/InvokeSampleREST" hostname="10.203.245.47">
<resource methods="GET" uri-template="/{str1}">
<inSequence>
<log level="full" separator=","/>
<property name="REST_URL_POSTFIX" expression="fn:concat('/Welcome',get-property('uri.var.str1'))" scope="axis2" type="STRING"/>
<log level="full">
<property name="sequence" value="****Message Sent *** "/>
</log>
<send>
<endpoint>
<address uri="http://10.203.245.47:8280/SampleRest/"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full" separator=",">
<property name="out" value="** Ouput of Rest call ***"/>
</log>
<property name="ContentType" value="application/xml" scope="axis2" type="STRING"/>
<send/>
</outSequence>
<faultSequence/>
</resource>
</api>
Appreciate any help.
Thanks,
Ranjan
Why are you using two APIs? You can design your flow, in a single API. I mean you can merge them together.
BTW, you need to set the contentType property in your backend API(ie:At SampleREST API)
Because, when you send back the response to "InvokeSampleREST" API, System doesnt know the content-type of the incoming response and try to handle it as text message.
Eg:
<api name="SampleREST" context="/SampleRest" hostname="localhost">
<resource methods="GET" uri-template="/{str1}">
<inSequence>
<header name="To" action="remove"/>
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<payloadFactory>
<format>
<Message>$1</Message>
</format>
<args>
<arg expression="get-property('uri.var.str1')"/>
</args>
</payloadFactory>
<log level="full" separator=",">
<property name="sequence" value="*** Got Request ***"/>
</log>
<property name="Content-Type"
value="application/xml"
scope="transport"
type="STRING"/>
<send/>
</inSequence>
<faultSequence/>
</resource>
Try doing the following change at the InvokeSampleREST API.
At the outSequence, set the messageType as follows before the <send> mediator.
<property name="messageType" value="application/xml" scope="axis2"/>

WSO2 esb: how to proxy REST service with numeric operation name

We are trying to implement basic SOAP-to-REST proxy service on WSO2 ESB. Our 3rd-party REST service accepts the requests in the following format:
http://<MYURL>/simpleQuery/16783484?oslc.select=value1
The problem is that operation name has numeric only format - "16783484" in our case. payloadFactory mediator does not allow having <16783484> as XML element, since XML spec restricts numeric-only element names.
<proxy xmlns="http://ws.apache.org/ns/synapse" name="CQProxy" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<payloadFactory>
<format>
<16783484>
<oslc.select>$1</oslc.select>
</16783484>
</format>
<args>
<arg value="myvalue1"/>
</args>
</payloadFactory>
<send>
<endpoint>
<address uri="http://<MYURL>/simpleQuery" format="get"/>
</endpoint>
</send>
<drop/>
</inSequence>
<outSequence>
<log level="full"/>
<send/>
</outSequence>
</target>
</proxy>
How can this be overcome?
Appreciate your help!
WSO2 support team suggested the following solution. Thank you Sandapa!
In that case, you have to set endpoint format as 'rest'. And if it's a GET request you have to set 'HTTP_METHOD' as as GET. Please refer the example given below.
Example:
<proxy xmlns="http://ws.apache.org/ns/synapse" name="CQProxy" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<property name="REST_URL_POSTFIX" value="/getSimpleQuote?symbol=IBM" scope="axis2" type="STRING"/>
<property name="HTTP_METHOD" value="GET" scope="axis2" type="STRING"/>
<send>
<endpoint>
<address uri="http://localhost:9000/services/SimpleStockQuoteService/" format="rest"/>
</endpoint>
</send>
<drop/>
</inSequence>
<outSequence>
<log level="full"/>
<send/>
</outSequence>
</target>
<description></description>
</proxy>
Although this comment is not going to suggest you a solution, I can say that this is a bad idea :-) You can try using XSLT instead of PayloadFactory to transform, but again that might choke up the XML parser. Problem is a lot of open source projects/libs that WSO2 products use and you might bump into elsewhere will honour the spec. In the long run, complying to the spec will give you less headaches when you integrate with other external tools/systems. Is it possible to change your rest service so that the service name at least have an underscore in front?

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>