How to use the Fault Mediator to Respond with a Fault - rest

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

Related

REST WSO2 Kafka

I've installed WSO2 Integration Studio version 6.5.0 in my Windows workstation and created a project using the Kafka Consumer and Producer built-in template.
api.xml:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/publishweatherdata" name="WeatherDataPublishAPI" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<kafkaTransport.init>
<bootstrapServers>localhost:9092</bootstrapServers>
<keySerializerClass>org.apache.kafka.common.serialization.StringSerializer</keySerializerClass>
<valueSerializerClass>org.apache.kafka.common.serialization.StringSerializer</valueSerializerClass>
<acks>all</acks>
<requestTimeout>10000</requestTimeout>
<timeout>8000</timeout>
<metadataFetchTimeout>5000</metadataFetchTimeout>
<maxPoolSize>50</maxPoolSize>
</kafkaTransport.init>
<kafkaTransport.publishMessages>
<topic>weatherdatatopic</topic>
</kafkaTransport.publishMessages>
<payloadFactory media-type="json">
<format>
{"topic":"$1", "partition":"$2", "offset":"$3"}
</format>
<args>
<arg evaluator="xml" expression="$ctx:topic"/>
<arg evaluator="xml" expression="$ctx:partition"/>
<arg evaluator="xml" expression="$ctx:offset"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
weatherdatatransmitinboundEP.xml:
<?xml version="1.0" encoding="UTF-8"?>
<inboundEndpoint class="org.wso2.carbon.inbound.kafka.KafkaMessageConsumer" name="WeatherDataTransmitInboundEP" onError="WeatherDataErrorSeq" sequence="WeatherDataProcessSeq" suspend="false" xmlns="http://ws.apache.org/ns/synapse">
<parameters>
<parameter name="sequential">true</parameter>
<parameter name="interval">10</parameter>
<parameter name="coordination">true</parameter>
<parameter name="inbound.behavior">polling</parameter>
<parameter name="value.deserializer">org.apache.kafka.common.serialization.StringDeserializer</parameter>
<parameter name="topic.name">weatherdatatopic</parameter>
<parameter name="poll.timeout">100</parameter>
<parameter name="bootstrap.servers">localhost:9092</parameter>
<parameter name="group.id">hello</parameter>
<parameter name="contentType">application/json</parameter>
<parameter name="key.deserializer">org.apache.kafka.common.serialization.StringDeserializer</parameter>
<parameter name="class">org.wso2.carbon.inbound.kafka.KafkaMessageConsumer</parameter>
</parameters>
</inboundEndpoint>
WeatherDataPublishService.xml:
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="WeatherDataPublishService" startOnLoad="true" transports="http https" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<kafkaTransport.init>
<bootstrapServers>localhost:9092</bootstrapServers>
<keySerializerClass>org.apache.kafka.common.serialization.StringSerializer</keySerializerClass>
<valueSerializerClass>org.apache.kafka.common.serialization.StringSerializer</valueSerializerClass>
<acks>all</acks>
<requestTimeout>10000</requestTimeout>
<timeout>8000</timeout>
<metadataFetchTimeout>5000</metadataFetchTimeout>
<maxPoolSize>50</maxPoolSize>
</kafkaTransport.init>
<kafkaTransport.publishMessages>
<topic>weatherdatatopic</topic>
</kafkaTransport.publishMessages>
<payloadFactory media-type="json">
<format>
{"topic":"$1", "partition":"$2", "offset":"$3"}
</format>
<args>
<arg evaluator="xml" expression="$ctx:topic"/>
<arg evaluator="xml" expression="$ctx:partition"/>
<arg evaluator="xml" expression="$ctx:offset"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</target>
</proxy>
now I can send post request to http://localhost:8290/publishweatherdata and get it in the kafka topic. Also I can receive message produced by kafka in wso2. How can I send message to external service from wso2? I think I should to use
<endpoint [name="string"] [key="string"]>
address-endpoint | default-endpoint | wsdl-endpoint | load-balanced-endpoint | fail-over-endpoint
</endpoint>
but I have no idea where it must be added and how configured
You can use a call mediator [1] or a send mediator [2] to achieve your use case. Within the mediator, you can define the desired endpoint you want to invoke. Please refer to the following sample configuration. Here we have used a call mediator to invoke the external endpoint http://run.mocky.io/v3/9cf4b844-57c1-4fa5-a101-881dc36385bd.
<call>
<endpoint>
<address uri="http://run.mocky.io/v3/9cf4b844-57c1-4fa5-a101-881dc36385bd"/>
</endpoint>
</call>
In your use case, if you have finish building the desired payload after the payload factory mediator, you can use the call mediator after the payload factory mediator to invoke the external endpoint. Here the payload build by the payload factory mediator will be used to invoke the external endpoint.
<payloadFactory media-type="json">
<format>
{"topic":"$1", "partition":"$2", "offset":"$3"}
</format>
<args>
<arg evaluator="xml" expression="$ctx:topic"/>
<arg evaluator="xml" expression="$ctx:partition"/>
<arg evaluator="xml" expression="$ctx:offset"/>
</args>
</payloadFactory>
<call>
<endpoint>
<address uri="http://run.mocky.io/v3/9cf4b844-57c1-4fa5-a101-881dc36385bd"/>
</endpoint>
</call>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<respond/>
Further, in the case of WeatherDataTransmitInboundEP(inbound endpoint), it will read the messages published to Kafka, and then the message is sent to the sequence defined in the inbound endpoint. If you want to send the messages consumed by WeatherDataTransmitInboundEP to an external endpoint you have to follow a different approach.
In your case, WeatherDataProcessSeq is invoked after reading messages from Kafka. So if your requirement is to send the messages in Kafka you will need to define the call or the send mediator in the WeatherDataProcessSeq.
If you want further clarification regarding the call/send mediator please refer to the blog post [3].
[1]-https://docs.wso2.com/display/EI6xx/Call+Mediator
[2]-https://docs.wso2.com/display/EI600/Send+Mediator
[3]-https://www.yenlo.com/blog/wso2torial-to-send-or-not-to-send-that-is-your-choice
I just add
<send>
<endpoint>
<http method="post" statistics="enable" trace="enable" uri-template="http://localhost:8081/api">
<property name="name" scope="axis2" value="messageValue"/>
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</send>
to sequence and get what I want

WSO2 ESB with x-www-form-urlencoded messaage type service call

I have used following code for sending x-www-form-urlencoded message to backed server.
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="FormDataReceiver">
<http uri-template="http://www.eaipatterns.com/MessageEndpoint.html" method="post">
<suspendOnFailure>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
<retryDelay>0</retryDelay>
</markForSuspension>
</http>
</endpoint>
Also used following API code.
<api xmlns="http://ws.apache.org/ns/synapse" name="FORM" context="/Service">
<resource methods="POST">
<inSequence>
<log level="full"></log>
<property name="name" value="Mark" scope="default" type="STRING"></property>
<property name="company" value="wso2" scope="default" type="STRING"></property>
<property name="country" value="US" scope="default" type="STRING"></property>
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<root xmlns="">
<name>$1</name>
<company>$2</company>
<country>$3</country>
</root>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg evaluator="xml" expression="$ctx:name"></arg>
<arg evaluator="xml" expression="$ctx:company"></arg>
<arg evaluator="xml" expression="$ctx:country"></arg>
</args>
</payloadFactory>
<log level="full"></log>
<property name="messageType" value="application/x-www-form-urlencoded" scope="axis2" type="STRING"></property>
<property name="DISABLE_CHUNKING" value="true" scope="axis2" type="STRING"></property>
<call>
<endpoint key="FormDataReceiver"></endpoint>
</call>
<respond></respond>
</inSequence>
</resource>
</api>
But still that message send as rest call manner.
I want something like following message body into backed server. This example message should send through the message body. In here I have used WSO2 Given Example. I have added same wso2esb link for your further reference. wso2. Actually I need to send message XML={{my_xml_message_here}}. Please help me to continue this. Thanks lot.
name=Mark&company=wso2
There is missing Content-Type in header for this type of request. Need to add:
<header name="Content-Type" scope="transport" value="application/x-www-form-urlencoded"/>

How to implement a dummy REST API in WSO2 ESB

I have been trying to implement a simple heart beat REST API in WSO2 ESB and am not able to get a response back. Below is the API
<api xmlns="http://ws.apache.org/ns/synapse" name="HealthCheckAPI" context="/HealthCheck">
<resource methods="GET" url-mapping="/status" faultSequence="fault">
<inSequence>
<payloadFactory media-type="json">
<format>{"Status":"OK"}</format>
<args></args>
</payloadFactory>
<log>
<property name="JSON-Payload" expression="json-eval($.)"></property>
</log>
<property name="messageType" value="application/json" scope="axis2" type="STRING"></property>
<respond></respond>
</inSequence>
</resource>
</api>
When I curl the API, the response is zero length. What could be wrong?
curl -v http://localhost:8280/HealthCheck/status
You need to set following property .
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"></property>
Please find the working example
<api xmlns="http://ws.apache.org/ns/synapse" name="HealthCheckAPI" context="/HealthCheck">
<resource methods="GET" url-mapping="/status" faultSequence="fault">
<inSequence>
<payloadFactory media-type="json">
<format>{"Status":"OK"}</format>
<args></args>
</payloadFactory>
<log>
<property name="JSON-Payload" expression="json-eval($.)"></property>
</log>
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"></property>
<property name="messageType" value="application/json" scope="axis2" type="STRING"></property>
<respond></respond>
</inSequence>
</resource>
</api>
Shibu,
Use following expression in your property mediator.
json-eval($.Status)

How do I define a sequence to do a form post in WSO2 ESB?

I'm trying to define a sequence to do a HTTP post. I can't get my post variables to be sent in the request. I have
<sequence xmlns="http://ws.apache.org/ns/synapse" name="CDN" trace="enable">
<property name="messageType" value="application/x-www-form-urlencoded" scope="axis2" type="STRING"/>
<property name="HTTP_METHOD" value="POST" scope="axis2" type="STRING"/>
<send>
<endpoint>
<address uri="http://posttestserver.com/post.php"/>
<property name="foo" value="bar" scope="axis2"/>
</endpoint>
</send>
</sequence>
You can use payload factory to set the post body. Use some thing like following according to your need
<payloadFactory>
<format>
<m0:getQuote xmlns:m0="http://services.samples">
<m0:request>
<m0:symbol>$1</m0:symbol>
</m0:request>
</m0:getQuote>
</format>
<args>
<arg expression="get-property('uri.var.symbol')"/>
</args>
</payloadFactory>
You have to change the following lines as you need
<arg expression="get-property('uri.var.symbol')"/>
Please look http://docs.wso2.org/display/ESB470/PayloadFactory+Mediator

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"/>