We have a use case, where we have to iterate through array of json-object and call an external endpoint based on certain key value. So we have used a iterator mediator, switch mediator(to match condition) and an aggregate mediator.
<?xml version="1.0" encoding="UTF-8"?>
<api context="/propertycheck" name="propertyCheck" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<iterate attachPath="json-eval($)" expression="json-eval($.main)" id="testingid" preservePayload="true" sequential="true">
<target>
<sequence>
<switch source="json-eval($.sub1)">
<case regex="a">
<log level="full" separator=","/>
<call>
<endpoint>
<http method="post" uri-template="http://localhost:3000/test">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
</case>
<case regex="b">
<log level="full" separator=","/>
<call>
<endpoint>
<http method="post" uri-template="http://localhost:3000/test">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
</case>
<case regex="c">
<log level="full" separator=","/>
<call>
<endpoint>
<http method="post" uri-template="http://localhost:3000/test">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
</case>
<default>
<log>
<property name="default" value="defaultCase"/>
</log>
<payloadFactory media-type="json">
<format>{
"sub1":"My own Response"
}</format>
<args/>
</payloadFactory>
</default>
</switch>
</sequence>
</target>
</iterate>
<log/>
<aggregate id="testingid">
<correlateOn expression="json-eval($)"/>
<completeCondition>
<messageCount max="-1" min="-1"/>
</completeCondition>
<onComplete aggregateElementType="root" expression="json-eval($)">
<log>
<property expression="json-eval($)" name="outout"/>
</log>
</onComplete>
</aggregate>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
The Above use case works fine, when an external endpoint is called and response is returned to the aggregate mediator, but we have to build the response in the default case with out calling an endpoint, How can be this achieved? As the aggregate mediator will be triggered only after it receives response from a back end service.
We have also followed the answer that was provided in the post : WSO2 ESB, Using Aggregate mediator without send/call in iterate mediator
This also does not seems to work, below is the implementation as per the post answer
<?xml version="1.0" encoding="UTF-8"?>
<api context="/propertycheck" name="propertyCheck" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<iterate attachPath="json-eval($)" expression="json-eval($.main)" id="testingid" preservePayload="true" sequential="true">
<target>
<sequence>
<switch source="json-eval($.sub1)">
<case regex="a">
<log level="full" separator=","/>
<call>
<endpoint>
<http method="post" uri-template="http://localhost:3000/test">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
</case>
<case regex="b">
<log level="full" separator=","/>
<call>
<endpoint>
<http method="post" uri-template="http://localhost:3000/test">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
</case>
<case regex="c">
<log level="full" separator=","/>
<call>
<endpoint>
<http method="post" uri-template="http://localhost:3000/test">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
</case>
<default>
<log>
<property name="default" value="defaultCase"/>
</log>
<payloadFactory media-type="json">
<format>{
"sub1":"My own Response"
}</format>
<args/>
</payloadFactory>
<property name="RESPONSE" scope="default" type="STRING" value="true"/>
<sequence key="AggregateSequence"/>
</default>
</switch>
</sequence>
</target>
</iterate>
<log/>
<aggregate id="testingid">
<correlateOn expression="json-eval($)"/>
<completeCondition>
<messageCount max="-1" min="-1"/>
</completeCondition>
<onComplete aggregateElementType="root" expression="json-eval($)">
<log>
<property expression="json-eval($)" name="outout"/>
</log>
</onComplete>
</aggregate>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
AggregateSequence
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="AggregateSequence" statistics="enable" trace="enable" xmlns="http://ws.apache.org/ns/synapse">
<log>
<property expression="json-eval($)" name="request to mediator"/>
</log>
<aggregate id="testingid">
<correlateOn expression="json-eval($)"/>
<completeCondition>
<messageCount max="-1" min="-1"/>
</completeCondition>
<onComplete aggregateElementType="root" expression="json-eval($)">
<log>
<property expression="json-eval($)" name="inside Aggregator"/>
</log>
</onComplete>
</aggregate>
</sequence>
Request
{
"main":[
{
"sub1":"a"
},
{
"sub1":"b"
},
{
"sub1":"c"
},
{
"sub1":"d"
}
]
}
Any help is appreciated. Thanks
Think I had exactly the same problem, when no backend is called. Not sure anymore if it was stated in the documentation, anyhow I solved it calling the local "echo" EI/ESB service" when no backend call should be done.
Here's a snippet of how I solved it.
<iterate xmlns:m0="http://ws.wso2.org/dataservice" expression="$body//m0:Entry" id="iteratorID" sequential="true">
<target>
<sequence>
<filter xpath="contains(get-property('schedulerHour'), get-property('currentHour')) and (contains($ctx:schedulerMinutes, $ctx:currentMinute))">
<then>
.... real backend should be called...
<call>
<endpoint>
<http uri-template="https://someURL"/>
</endpoint>
</call>
....
</then>
<else>
.... fake backend call...
<payloadFactory media-type="xml">
<format>
<p:echoInt xmlns:p="http://echo.services.core.carbon.wso2.org">
<in>123</in>
</p:echoInt>
</format>
<args/>
</payloadFactory>
<call>
<endpoint>
<http method="POST" uri-template="http://localhost:8280/services/echo"/>
</endpoint>
</call>
.....
</else>
</filter>
</sequence>
</target>
</iterate>
Related
I have an API that will return XML data, I want to use datamapper to map some data and then return it to the client, but the API after using DataMapper keeps returning null.
see below
<?xml version="1.0" encoding="UTF-8"?>
<api context="/AllAdByCRN" name="AllAdByCRN" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope format="soap11" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header/>
<soapenv:Body>
<GetCustomerWaselNotCancelled xmlns="http://tempuri.org/">
<userName></userName>
<password></password>
<id></id>
<idType></idType>
<sequenceNumber></sequenceNumber>
<laborOffice></laborOffice>
</GetCustomerWaselNotCancelled>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args/>
</payloadFactory>
<header name="Action" scope="default" value=""/>
<call>
<endpoint>
<http format="soap11" method="post" uri-template="">
<timeout>
<duration>17000000</duration>
<responseAction>fault</responseAction>
</timeout>
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<property expression="json-eval($.*)" name="responseData" scope="default" type="STRING"/>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<datamapper config="gov:datamapper/NewConfig.dmc" inputSchema="gov:datamapper/NewConfig_inputSchema.json" inputType="JSON" outputSchema="gov:datamapper/NewConfig_outputSchema.json" outputType="XML" xsltStyleSheet="gov:datamapper/NewConfig_xsltStyleSheet.xml"/>
<log level="custom">
<property expression="json-eval($.*)" name="responseData"/>
</log>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
I want to map data only not converting from XML to JSON.
You have to choose XML as input and output :
<datamapper config="gov:datamapper/NewConfig.dmc" inputSchema="gov:datamapper/NewConfig_inputSchema.json" inputType="XML" outputSchema="gov:datamapper/NewConfig_outputSchema.json" outputType="XML" xsltStyleSheet="gov:datamapper/NewConfig_xsltStyleSheet.xml"/>
I´m noob to that application, but I´ve been trying some tutorials and all of them had no response, nothing happens. I just send a request and nothing. I deployed and all looks as the tutorials explained, but when I try to execute, nothing appears in my browse or curl.
Here is a example:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/healthcare" name="HealthcareAPI" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET" uri-template="/querydoctor/{category}">
<inSequence>
<log description="RequestLog"/>
<send/>
</inSequence>
<outSequence>
<log description="ResponseLog"/>
<send/>
</outSequence>
<faultSequence>
<log description="ErrorLog"/>
</faultSequence>
</resource>
<resource methods="POST" uri-template=" /categories/{category}/reserve">
<inSequence>
<property description="GetHospital" expression="json-eval($.hospital)" name="Hospital" scope="default" type="STRING"/>
<switch source="get-property('Hospital')">
<case regex="grand oak community hospital">
<log description="GrandOakLog" level="custom">
<property expression="fn:concat('Routing to ', get-property('Hospital'))" name="message"/>
</log>
<send/>
</case>
<case regex="clemency medical center">
<log description="ClemencyLog" level="custom">
<property expression="fn:concat('Routing to ', get-property('Hospital'))" name="message"/>
</log>
<send/>
</case>
<case regex="pine valley community hospital">
<log description="PineValleyLog" level="custom">
<property expression="fn:concat('Routing to ', get-property('Hospital'))" name="message"/>
</log>
<send/>
</case>
<default>
<log description="ErrorLog" level="custom">
<property expression="fn:concat('Invalid hospital - ', get-property('Hospital'))" name="message"/>
</log>
<respond description="RespondError"/>
</default>
</switch>
</inSequence>
<outSequence/>
<faultSequence>
<log description="ErrorLog"/>
</faultSequence>
</resource>
</api>
<?xml version="1.0" encoding="UTF-8"?>
<endpoint name="ClemencyEP" xmlns="http://ws.apache.org/ns/synapse">
<http method="post" uri-template="http://wso2training-restsamples.wso2apps.com/clemency/categories/{uri.var.category}/reserve"/>
</endpoint>
<?xml version="1.0" encoding="UTF-8"?>
<endpoint name="GrandOakEP" xmlns="http://ws.apache.org/ns/synapse">
<http method="post" uri-template="http://wso2training-restsamples.wso2apps.com/grandoaks/categories/{uri.var.category}/reserve"/>
</endpoint>
<?xml version="1.0" encoding="UTF-8"?>
<endpoint name="PineValleyEP" xmlns="http://ws.apache.org/ns/synapse">
<http method="post" uri-template="http://wso2training-restsamples.wso2apps.com/pinevalley/categories/{uri.var.category}/reserve"/>
</endpoint>
And here is the request to make that application work:
{
"patient": {
"name": "John Doe",
"dob": "1940-03-19",
"ssn": "234-23-525",
"address": "California",
"phone": "8770586755",
"email": "johndoe#gmail.com"
},
"doctor": "thomas collins",
"hospital": "grand oak community hospital"
}
You should have the endpoint call in the send mediator
<case regex="grand oak community hospital">
<log description="GrandOakLog" level="custom">
<property expression="fn:concat('Routing to ', get-property('Hospital'))" name="message"/>
</log>
<send>
<endpoint name="GrandOakEP" xmlns="http://ws.apache.org/ns/synapse">
<http method="post" uri-template="http://wso2training-restsamples.wso2apps.com/grandoaks/categories/{uri.var.category}/reserve"/>
</endpoint>
</send>
</case>
And also the outSequence should have a <send/> mediator
<?xml version="1.0" encoding="UTF-8"?>
<sequence name=SEQUENCE trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<iterate expression=EXPRESSION sequential="true" xmlns:ns="http://org.apache.synapse/xsd">
<target>
<sequence>
<log level="full">
<property expression="$body/*" name="Test within iterate"/>
</log>
<call>
<endpoint>
<http method="POST" uri-template=URI TEMPLATE
</endpoint>
</call>
<log>
<property name="After CALL" value="response"/>
</log>
</sequence>
</target>
</iterate>
<aggregate>
<completeCondition>
<messageCount max="-1" min="-1"/>
</completeCondition>
<onComplete expression="$body/*" sequence="OutSequenceforData"
xmlns:ns="http://org.apache.synapse/xsd"
xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xmlns:s12="http://www.w3.org/2003/05/soap-envelope"/>
</aggregate>
<send/>
<log level="full">
<property expression="$body/*" name="After Aggregate" xmlns:ns="http://org.apache.synapse/xsd"/>
</log>
</sequence>
I am trying to invoke a web service using call mediator. But I do not see any log about the call in the wso2 logs. The goal is to display the data from a file in the web service.
Yes you can, after the Call mediator put a Log mediator.
<log level="full" xmlns="http://ws.apache.org/ns/synapse"/>
I have custom mediator where we are validating internal authentication system. If authentication fails, mediator return false. Client receiving response as HTTP status code 202. This I want to override with some JSON response like { "authError" : "Authetication failed - TOKEN_INVALID" }. Please let me know how to handle such scenarios.
ESB Version - 4.81.
Here is my proxy configuration -
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="UGCGetJSONFileList"
transports="https,http"
statistics="enable"
trace="disable"
startOnLoad="true">
<target outSequence="WEB_OUT_Sequence">
<inSequence>
<log level="full" separator=","/>
<class name="com.hc.synapse.mediator.HCAuthenticationMediator"/>
<property name="RESPONSE" value="true" scope="axis2"/>
<property name="uri.var.querystrings"
expression="substring-after(get-property('To'), '?')"
scope="axis2"
type="STRING"/>
<log level="full" separator=","/>
<switch source="$axis2:HTTP_METHOD">
<case regex="GET">
<property name="uri.var.querystrings"
expression="substring-after(get-property('To'), '?')"
scope="default"
type="STRING"/>
<log level="full" separator=","/>
<send>
<endpoint>
<http method="get"
uri-template="http://dalx-entsvc-d1:9660/ugc/getJSONFileList?{uri.var.querystrings}"/>
</endpoint>
</send>
</case>
<case regex="POST">
<log level="full" separator=","/>
<send>
<endpoint>
<address uri="http://dalx-entsvc-d1:9660/ugc/getJSONFileList?{uri.var.querystrings};content"
trace="enable"
statistics="enable">
<timeout>
<duration>30000</duration>
<responseAction>discard</responseAction>
</timeout>
<suspendOnFailure>
<initialDuration>0</initialDuration>
<progressionFactor>1.0</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
</address>
</endpoint>
</send>
</case>
<default/>
</switch>
</inSequence>
<faultSequence>
<log level="full" separator=",">
<property name="trace" expression="get-property('ERROR_MESSAGE')"/>
</log>
<payloadFactory media-type="json">
<format>{ "authError" : "Authetication failed - TOKEN_INVALID" }</format>
<args/>
</payloadFactory>
<property name="RESPONSE" value="true"/>
<header name="To" action="remove"/>
<send/>
</faultSequence>
</target>
<description/>
</proxy>
In your class mediator, you can throw a SynapseException
In this case, inSequence mediation stop and faultSequence will be executed
In the faultSequence, your can use mediator payloadFactory with media-type="json" to build your json message and send it to the client with <send/>
I have a problem in deploying this sample: "Complex Event Processing and Business Rule Management With SOA" (Link: http://wso2.org/library/articles/2011/07/complex-event-processing-business-rule-management-soa)
I did all the details, but when I copy "cepSample.xml" file in the location "wso2esb-4.6.0/repository/deployment/server/synapse-configs/default/proxy-services" I get this error in the console and I won't be deployed:
/WSO2/wso2esb-4.6.0/repository/deployment/server/synapse-configs/default/proxy-services/cepSample.xml failed - Continue in fail-safe mode
org.apache.synapse.SynapseException: The 'name' attribute is required for a Proxy service definition
I try to create Proxy Service manually - and get this file (in ESB 4.8.1.)
May be it help you:
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="cepSample"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<log level="full"/>
<property name="txAmount" expression="//reqFinancTx/amount/text()"/>
<property name="financTx" expression="//reqFinancTx/financTx/text()"/>
<dblookup>
<connection>
<pool>
<password>esb</password>
<user>esb</user>
<url>jdbc:mysql://localhost:3306/brms_db</url>
<driver>com.mysql.jdbc.Driver</driver>
</pool>
</connection>
<statement>
<sql>
SELECT * FROM `BRMS_USER_INFO` where `user_id`=? </sql>
<parameter expression="//reqFinancTx/userID" type="VARCHAR"/>
<result name="balance" column="account_balance"/>
<result name="userId" column="user_id"/>
<result name="userName" column="name"/>
<result name="access" column="accessability"/>
</statement>
</dblookup>
<log>
<property name="userId" expression="get-property('userId')"/>
<property name="userName" expression="get-property('userName')"/>
<property name="access" expression="get-property('access')"/>
<property name="balance" expression="get-property('balance')"/>
<property name="txAmount" expression="get-property('txAmount')"/>
<property name="financTx" expression="get-property('financTx')"/>
</log>
<xslt key="sampleXSLT">
<property name="accountBalance" expression="get-property('balance')"/>
</xslt>
<log level="full"/>
<property name="STATE" value="PERSON_INFO_REQUEST"/>
<send>
<endpoint>
<address uri="http://localhost:9764/services/transactionValidatorService"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<log>
<property name="xxxxxx" expression="get-property('STATE')"/>
</log>
<switch source="get-property('STATE')">
<case regex="PERSON_INFO_REQUEST">
<log level="full"/>
<property xmlns:brs="http://brs.carbon.wso2.org"
xmlns:ax26="http://transactionApprovalService.samples/xsd"
name="RESULT"
expression="//brs:processTransactionResponse/brs:TransactionResult/ax26:transactionCanProceed"/>
<log>
<property name="RESULT" expression="get-property('RESULT')"/>
</log>
<switch source="get-property('RESULT')">
<case regex="true">
<clone>
<target>
<sequence>
<xslt key="cepXSLT">
<property name="userId" expression="get-property('userId')"/>
<property name="financTx" expression="get-property('financTx')"/>
</xslt>
<log level="full"/>
<send>
<endpoint>
<address uri="http://localhost:9766/services/localBrokerService/AllTransactions"/>
</endpoint>
</send>
</sequence>
</target>
<target>
<sequence>
<dblookup>
<connection>
<pool>
<password>esb</password>
<user>esb</user>
<url>jdbc:mysql://localhost:3306/brms_db</url>
<driver>com.mysql.jdbc.Driver</driver>
</pool>
</connection>
<statement>
<sql> SELECT * FROM `BRMS_USER_INFO` where `user_id`=? </sql>
<parameter expression="//reqFinancTx/userID" type="VARCHAR"/>
<result name="balance" column="account_balance"/>
<result name="userId" column="user_id"/>
<result name="userName" column="name"/>
<result name="access" column="accessability"/>
</statement>
</dblookup>
<log>
<property name="userId" expression="get-property('userId')"/>
<property name="userName" expression="get-property('userName')"/>
<property name="access" expression="get-property('access')"/>
</log>
<switch source="get-property('access')">
<case regex="false">
<xslt key="accLockedXSLT"/>
<send/>
</case>
<case regex="true">
<xslt key="txProceedXSLT"/>
<send/>
</case>
</switch>
</sequence>
</target>
</clone>
</case>
<case regex="false">
<log level="full">
<property name="sequence"
value="outSequence - STATE 02 - response from CreditService"/>
</log>
<send/>
</case>
</switch>
<send>
<endpoint key="CreditEpr"/>
</send>
</case>
<case regex="CREDIT_REQUEST">
<log level="full">
<property name="sequence"
value="outSequence - STATE 02 - response from CreditService"/>
</log>
<send/>
</case>
</switch>
</outSequence>
</target>
</proxy>