I am having a problem with call blocking mediator in a WSO2 Esb proxy service.And i'm currently using wso2 4.9.0.
I am going to call multiple WSO2 ESB Sequence mediator using under the call mediator (using filter statement). This will loop by following XML tag format. Based on the results. I need to call out sequence according to this xml tag value.
Here is my In Sequence:
<call blocking="true">
<endpoint key="CommonEPR"/>
</call>
<filter regex="02" source="json-eval($.responsecode) xmlns:ns="http://org.apache.synapse/xsd">
<then>
<log level="full">
<property
name="CALLCommonAPI" value="MESSAGE"/>
</log>
<sequence name="CommonOutSequence">
<log/>
<out>
<sequence key="CommonOutSequence"/>
<send/>
</out>
</sequence>
</then>
</filter>
What i need is send to results to CommonOutSequence, yes i know its not possible in call mediator send to out sequence.can any one tell me possible way to send out Sequence using call mediator.
I'm not really clear about your requirement, but if you want to move to the outflow at some point, you can call the <loopback/> mediator[1].
Updated as per the 1st comment:
Doesn't this work?
<filter regex="02" source="json-eval($.responsecode) xmlns:ns="http://org.apache.synapse/xsd">
<then>
<log level="full">
<property name="CALLCommonAPI" value="MESSAGE"/>
</log>
<sequence key="CommonOutSequence"/>
<respond/>
</then>
</filter>
[1] https://docs.wso2.com/display/ESB490/Loopback+Mediator
Related
I have a REST service that returns a json simple {message: "ok"}. When I use Respond Mediator this stop further processing of a message and send the message back to the client.
I need to send response to client, and then execute task asynchronously, but if I use it ignores the next call to a sequence or an endpoint.
How can you respond synchronously (response to client) and then invoke a service, without response mediator ignore the next mediator?
thanks;
I was able to solve the challenge. effectively Clone mediator not just clone message, it give new separate life to new message.
<api xmlns="http://ws.apache.org/ns/synapse" name="porticApiAsyn" context="/test">
<resource methods="POST" url-mapping="/asyn">
<inSequence>
<log>
<property name="message" value="asyn"/>
</log>
<payloadFactory media-type="json">
<format>{"message":"asyn test"}</format>
<args/>
</payloadFactory>
<clone continueParent="true" sequential="true">
<target sequence="logSequence"/>
</clone>
<respond/>
</inSequence>
In this case, the message is sent to logsequence, then the response mediator is executed. Thanks for your help.
For your case you could even do the following
<api xmlns="http://ws.apache.org/ns/synapse" name="porticApiAsyn" context="/test">
<resource methods="POST" url-mapping="/asyn">
<inSequence>
<log>
<property name="message" value="asyn"/>
</log>
<payloadFactory media-type="json">
<format>{"message":"asyn test"}</format>
<args/>
</payloadFactory>
<clone continueParent="true" sequential="true">
<target sequence="logSequence"/>
<target>
<sequence>
<respond/>
</sequence>
</target>
</clone>
</inSequence>
I guess it should work as well and is maybe more readable
I am very new in WSO2 ESB and I have the following doubt about how to implement an "if(){...} else{...}" like structure in my ESB project.
So in the input flow of the application on which I am working I have this property mediator followed by a log mediator that simply print the value of this property, something like this:
<property expression="count(//ds:Sample)" name="total_samples" scope="default" type="STRING" xmlns:ds="http://ws.wso2.org/dataservice"/>
<log level="custom">
<property expression="$ctx:total_samples" name="total samples: "/>
</log>
This works fine.
This total_samples property contains the number of record obtained from a previous call of a DSS service (I am not putting here in the code).
So the value of this total_samples property could be:
0: if the the query implemented by the DSS service returned 0 records.
A numeric value >0: if this query returned some records.
Now what I need to do at this time is only to chain a n "if(){...} else{...}" structure that print different log message if the total_samples property value is 0 or whatever number >0.
It should be a ver simple task but I have some doubts about how achieve it:
FIRST DOUBT: Looking on the online documentation it seems to me that exists 2 mediator that can be used to perform choice in the WSB flow: the switch mediator and the filter mediator. They seems to me very similar. What are the difference between these mediators? And what is better for my purpose?
SECOND DOUBT: It seems to me that these mediators works only on XPATH expression (something like count(//ds:Sample)), can they work directly on my property (something like "$ctx:total_samples") ?
THIRD DOUBT: At this stage I have implemented something like this in my flow:
<property expression="count(//ds:Sample)" name="total_samples" scope="default" type="STRING" xmlns:ds="http://ws.wso2.org/dataservice"/>
<log level="custom">
<property expression="$ctx:total_samples" name="total samples: "/>
</log>
<filter xpath="EXPRESSION THAT DO SOMETHING LIKE: $ctx:total_samples == 0">
<then>
<log description="No Resource Log">
<property name="message" value=""EMPTY RESULTSET, NO RESOURCES TO PROCESS""/>
</log>
</then>
<else>
<log description="Found Resource Log">
<property name="message" value=""Resources have been found, will be processed""/>
</log>
</else>
</filter>
Ok so my problem is: What have I to use as expression to enter in the case if the $ctx:total_samples value is 0 in the following line?
<filter xpath="EXPRESSION THAT DO SOMETHING LIKE: $ctx:total_samples == 0">
A more generic solution:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="testIfElse"
transports="https http"
startOnLoad="true">
<target>
<inSequence>
<payloadFactory media-type="xml">
<format>
<ds:Sample xmlns:ds="http://ws.wso2.org/dataservice">
<ds:INT_ID>1</ds:INT_ID>
<ds:INT_ID>2</ds:INT_ID>
<ds:INT_ID>3</ds:INT_ID>
</ds:Sample>
</format>
<args>
</args>
</payloadFactory>
<property expression="count(//ds:Sample/ds:INT_ID)" name="total_samples" scope="default" xmlns:ds="http://ws.wso2.org/dataservice" type="DOUBLE"/>
<property value="0" name="initial_value" scope="default" type="DOUBLE"/>
<property expression="fn:number($ctx:total_samples) > fn:number($ctx:initial_value)" name="result" scope="default"/>
<log level="custom">
<property expression="$ctx:initial_value" name="initial value: "/>
<property expression="fn:number($ctx:total_samples)" name="total samples: "/>
<property expression="$ctx:result" name="if total samples greater than initial value: "/>
</log>
<filter xpath="$ctx:result" regex="true">
<then>
<log description="Found Resource Log">
<property name="message" value=""Resources have been found, will be processed""/>
</log>
</then>
<else>
<log description="No Resource Log">
<property name="message" value=""EMPTY RESULTSET, NO RESOURCES TO PROCESS""/>
</log>
</else>
</filter>
</inSequence>
<outSequence>
<log level="full"/>
<drop/>
</outSequence>
<faultSequence/>
</target>
</proxy>
Use this expression
<filter xpath="fn:number(get-property('total_samples')) = fn:number(0)">
you are really asking three questions here so I'll try to answer all of them:
The Switch mediator allows for multiple cases, so for example you could have a case for count = 0, count = 1 and count > 1. The filter mediator on the other hand is like the classic if/else. If this than do x, else do .
The filter mediator can either work comparing some value with a regular expression using the 'source' and 'regex' attributes in which case it checks if they match. Or it uses the xpath attribute in which case it evaluates the result of the xpath expression as a boolean. In the xpath expression as well as the source you can refer directly to your property using $ctx. For example:
What you could do is
<filter xpath="fn:number($ctx:total_samples) = fn:number(0)">
I have a problem with wso2 esb.
I wrote a proxy and in that I call an endpoint to do some changes on original input. but the log before call and after call is the same(it should be different). It seems the call is not working at all.when I send respone to outsequence it is null. Can any one say why this happen? (I have tested my endpoint in soupUI)
this is my proxy:
<inSequence>
<property name="transport.vfs.ReplyFileName" value="GET" scope="transport"/>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<smooks config-key="smooks-csv1">
<input type="text"/>
<output type="xml"/>
</smooks>
<iterate continueParent="true"
preservePayload="true"
attachPath="//csv-set"
expression="//csv-set/search"
sequential="true">
<target>
<sequence>
<xslt key="gov:/first.xsl"/>
<xslt key="gov:/second.xsl"/>
**<log level="full"/>
<call blocking="true">
<endpoint>
<address uri="MyEndPiont"/>
</endpoint>
</call>
<log level="full"/>**
</sequence>
</target>
</iterate>
<respond/>
</inSequence>
<outSequence>
<aggregate>
<completeCondition>
<messageCount min="0" max="100"/>
</completeCondition>
<onComplete expression="//Guest">
</onComplete>
</aggregate>
</outSequence>
Try this. List of changes:
Removed respond mediator.
Replaced call by send.
Added send in out sequence.
<inSequence>
<property name="transport.vfs.ReplyFileName" value="GET" scope="transport"/>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<smooks config-key="smooks-csv1">
<input type="text"/>
<output type="xml"/>
</smooks>
<iterate continueParent="true"
preservePayload="true"
attachPath="//csv-set"
expression="//csv-set/search"
sequential="true">
<target>
<sequence>
<xslt key="gov:/first.xsl"/>
<xslt key="gov:/second.xsl"/>
<log level="full"/>
<send>
<endpoint>
<address uri="MyEndPiont"/>
</endpoint>
</send>
</sequence>
</target>
</iterate>
</inSequence>
<outSequence>
<aggregate>
<completeCondition>
<messageCount min="0" max="100"/>
</completeCondition>
<onComplete expression="//Guest">
</onComplete>
</aggregate>
<send />
</outSequence>
Try blocking="false". Please note that making this change does not make the call mediator is asynchonus. It's synchronous regardless of whether blocking is true or false. Blocking is just an implementation detail.
The Call mediator is used to send messages out of the ESB to an
endpoint. You can invoke services either in blocking or non-blocking
manner.
When you invoke a service in non-blocking mode, the underlying worker
thread returns without waiting for the response. In blocking mode, the
underlying worker thread gets blocked and waits for the response after
sending the request to the endpoint. Call mediator in blocking mode is
very much similar to the Callout mediator.
In both blocking and non-blocking modes, Call mediator behaves in a
synchronous manner. Hence, mediation pauses after the service
invocation and resumes from the next mediator in the sequence when the
response is received. Call mediator allows you to create your
configuration independent from the underlying architecture.
Quoted from https://docs.wso2.com/display/ESB500/Call+Mediator
I have the following problem:
Develop a WSDL Based Proxy that calls several different SOAP Web services in parallel and returns the responses:
<inSequence>
<log level="full"/>
<iterate xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:agg="http://www.test.ro/aggregate"
preservePayload="true"
attachPath="//soapenv:Body"
expression="//agg:AggregateRequest/agg:messageRequest">
<target>
<sequence>
<property name="messageId"
expression="//soapenv:Body/agg:messageRequest/agg:messageId[node()]"/>
<property name="endpoint"
expression="//soapenv:Body/agg:messageRequest/agg:endpoint[node()]"/>
<xslt key="CleanPayload" source="/"/>
<send>
<endpoint key="MirrorEndpoint"/>
</send>
</sequence>
</target>
</iterate>
</inSequence>
<outSequence>
<property name="resp" scope="default">
<agg:AggregateResponse xmlns:agg="http://www.test.ro/aggregate"/>
</property>
<aggregate>
<completeCondition timeout="10">
<messageCount min="-1" max="-1"/>
</completeCondition>
<onComplete xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
expression="$body/*"
enclosingElementProperty="resp">
<log level="full"/>
<send/>
</onComplete>
</aggregate>
</outSequence>
My challenges are:
how do I pass the messageId from inSequence to outSequence so I can match the response to the request (similar to local environment from Message Broker)
how do I set the endpoint key with the text from agg:endpoint
I know this may be a newbie question but I'm having a hard time finding good tutorials on this topic.
Thank you
When you set a property (scope default) inside the In Sequence, you can find back it's value inside the Out Sequence.
Set this property inside your In Sequence :
<property name="IN_MESSAGE_ID" expression="get-property('MessageID')"/>
you can use get-property('IN_MESSAGE_ID') in your Out Sequence
If you want to send a message to a dynamic address, you can set "To" header and use send mediator :
<header name="To" expression="get-property('MY_DESTINATION')"/>
<send/>
Try setting the messageId as a HTTP header property,
<header name="MessageId" value="0001" scope="transport"/>
And retrieve this header in the outSequence
<property name="MessageId" expression="get-property('MessageId')"/>
I havnt tested this out, so give a feedback on whether it works
I want to customize the error messages sent by api manager, for instance when an access token is missing or expired. I've configured _auth_failure_handler_ to return messages in json as described here, and get responses like:
{"fault":{"code":"900902","message":"Missing Credentials","description":"Required OAuth credentials not provided"}}
I would like to modify the message description and remove the "code" altogether. Is there a way to do this? I've tried tweaking the sequence with no luck.
You need to target the error codes from https://docs.wso2.com/display/AM260/Error+Handling and update it to your custom JSON messages. For auth token related errors try modify _auth_failure_handler_ as below:
<sequence name="_auth_failure_handler_" xmlns="http://ws.apache.org/ns/synapse">
<property name="error_message_type" value="application/json"/>
<filter source="get-property('ERROR_CODE')" regex="405">
<then>
<sequence key="converter"/>
<drop/>
</then>
<else>
</else>
</filter>
<filter source="get-property('ERROR_CODE')" regex="900901">
<then>
<sequence key="invalidCredential"/>
<drop/>
</then>
<else>
</else>
</filter>
<filter source="get-property('ERROR_CODE')" regex="900902">
<then>
<sequence key="missingCredential"/>
<drop/>
</then>
<else>
</else>
</filter>
<sequence key="_cors_request_handler_"/>
For your case Missing Credential has a 900902 code , so it will match and need to define missingCredential.xml as below :
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="missingCredential">
<payloadFactory media-type="json">
<format>{ "status": "Error","message": "Missing Credentials" }</format>
<!--Add your custom message and format here. This will be your output-->
</payloadFactory>
<property name="RESPONSE" value="true"/>
<header name="To" action="remove"/>
<property name="HTTP_SC" value="401" scope="axis2"/>
<property name="messageType" value="application/json" scope="axis2"/>
<send/>
</sequence>
It is not wise advice to modify the error code. Nevertheless, yes it is possible to modify the payload. Use the filter mediator and Json path and identify the data and use enrich mediator to modify the payload as you want.