I have defined a "Validate" Mediator fault sequence. I want that if my validation is failed. Message should be sent back to the client as well as to a queue based on JMS.
Problem:
Clone mediator is not working. I am using clone mediator to send message to the queue and then "Respond" mediator to send message back to the client.
Note:
If I remove the clone mediator, the message is perfectly send back to the client. But with clone mediator it is not working.
Validate Mediator Code:
<validate>
<schema xmlns:ns2="http://org.apache.synapse/xsd" xmlns:ns="http://org.apache.synapse/xsd" key="gov:/xsd/testschema.xsd"></schema>
<on-fail>
<makefault version="soap11">
<detail xmlns:ns2="http://org.apache.synapse/xsd" xmlns:ns="http://org.apache.synapse/xsd" expression="get-property('ERROR_DETAIL')"></detail>
</makefault>
<payloadFactory media-type="xml">
<format>
<ErrorMessage xmlns="">
<ErrorCode>007</ErrorCode>
<ErrorMessage>Not Correct Request</ErrorMessage>
</ErrorMessage>
</format>
</payloadFactory>
<clone continueParent="true" sequential="false">
<target>
<endpoint>
<address uri="jms:/ErrorQueue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616&transport.jms.DestinationType=queue"></address>
</endpoint>
</target>
</clone>
<respond></respond>
</on-fail>
</validate>
Exception:
Uncaught exception {org.apache.axis2.transport.base.threads.NativeWorkerPool}
java.lang.ClassCastException: org.apache.axiom.om.impl.llom.OMElementImpl cannot be cast to org.apache.axiom.soap.SOAPFault
at org.apache.axiom.soap.impl.llom.SOAPBodyImpl.getFault(SOAPBodyImpl.java:120)
at org.apache.synapse.util.MessageHelper.cloneSOAPEnvelope(MessageHelper.java:383)
at org.apache.synapse.util.MessageHelper.cloneAxis2MessageContext(MessageHelper.java:233)
at org.apache.synapse.util.MessageHelper.cloneMessageContext(MessageHelper.java:86)
at org.apache.synapse.mediators.eip.splitter.CloneMediator.getClonedMessageContext(CloneMediator.java:159)
at org.apache.synapse.mediators.eip.splitter.CloneMediator.mediate(CloneMediator.java:99)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:77)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47)
at org.apache.synapse.mediators.builtin.ValidateMediator.mediate(ValidateMediator.java:212)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:77)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47)
at org.apache.synapse.mediators.template.TemplateMediator.mediate(TemplateMediator.java:77)
at org.apache.synapse.mediators.template.InvokeMediator.mediate(InvokeMediator.java:129)
at org.apache.synapse.mediators.template.InvokeMediator.mediate(InvokeMediator.java:78)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:77)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:131)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:196)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:77)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:131)
at org.apache.synapse.core.axis2.ProxyServiceMessageReceiver.receive(ProxyServiceMessageReceiver.java:166)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:411)
at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:183)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
Note:
I also didn't define anything in "SOAP Action" field in "Clone" mediator.
It is a bug in ESB 4.8.1. Please check this [1]
1.https://wso2.org/jira/browse/ESBJAVA-3087
Try this with call mediator and enrich mediator. I have not tested this.
<validate>
<schema xmlns:ns2="http://org.apache.synapse/xsd" xmlns:ns="http://org.apache.synapse/xsd" key="gov:/xsd/testschema.xsd"></schema>
<on-fail>
<makefault version="soap11">
<detail xmlns:ns2="http://org.apache.synapse/xsd" xmlns:ns="http://org.apache.synapse/xsd" expression="get-property('ERROR_DETAIL')"></detail>
</makefault>
<payloadFactory media-type="xml">
<format>
<ErrorMessage xmlns="">
<ErrorCode>007</ErrorCode>
<ErrorMessage>Not Correct Request</ErrorMessage>
</ErrorMessage>
</format>
</payloadFactory>
**<property name="BODY_ELEMENTS" expression="$body">**
**<call>**
<endpoint>
<address uri="jms:/ErrorQueue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616&transport.jms.DestinationType=queue"></address>
</endpoint>
**</call>**
**<enrich>
<source xpath="$ctx:BODY_ELEMENTS/>
<target type="body"/>
</enrich>**
<respond></respond>
</on-fail>
</validate>
Related
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
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"/>
I'm new to wso2 and currently I'm trying to expose a mongodb data service as REST API. I followed this tutorial and exposed my data service as Rest resource like this:
<data>
<config>...</config>
<query id="count" useConfig="MongoDB">
<expression>myCollection.count()</expression>
<result outputType="json">{
"Documents": {
"Document": [
{
"Data": "$document"
}
]
}
}</result>
</query>
<operation name="count_op">
<call-query href="count"/>
</operation>
<resource method="GET" path="users/count">
<call-query href="count"/>
</resource>
</data>
Works fine, however when I tried to access the resource from my angular2 project, I stumbled upon the CORS problem. I read up some posts about that and figured I need to modify my Rest API with something like this:
<resource methods="OPTIONS" url-mapping="/*">
<inSequence>
<property action="set" name="HTTP_SC" scope="axis2"
type="STRING" value="200"/>
<property action="set" name="messageType" scope="axis2"
type="STRING" value="application/json"/>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</faultSequence>
</resource>
I tried to integrate this code with my data service definition (the one above) but I can't get it working and it makes me wonder if data service exposed as REST resource are the same thing as Rest APIs? It seems I cannot invoke any elements or other mediators in the data service definition. Do I need to create an actual Rest API for this? If so, how can I use my mongo dataservice as a resource for my Rest API?
EDIT: The CORS error I'm getting from my angular2 project when trying to access the service is "No 'Access-Control-Allow-Origin' header is present on the requested resource." which is another topic. But it led me to edit my data service so I edited my data service resource element and added a new one:
<resource method="GET" path="users/count">
<inSequence>
<property action="set" name="HTTP_SC" scope="axis2" type="STRING" value="200"/>
<property action="set" name="messageType" scope="axis2" type="STRING" value="application/json"/>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</faultSequence>
<call-query href="count"/>
</resource>
<resource method="OPTIONS" path="users/count">
<inSequence>
<property action="set" name="HTTP_SC" scope="axis2"
type="STRING" value="200"/>
<property action="set" name="messageType" scope="axis2"
type="STRING" value="application/json"/>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</faultSequence>
</resource>
rest_add_access_control_headers sequence looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="rest_add_access_control_headers" xmlns="http://ws.apache.org/ns/synapse">
<property name="Access-Control-Allow-Origin" scope="transport"
type="STRING" value="*"/>
<property name="Access-Control-Allow-Methods" scope="transport"
type="STRING" value="GET,POST,PUT,DELETE,OPTIONS"/>
<property name="Access-Control-Allow-Headers" scope="transport"
type="STRING" value="origin, content-type, accept, Authorization"/>
</sequence>
The first seems to be fine but the second one makes my dataservice faulty, giving this error in managemenet console:
DS Code: UNKNOWN_ERROR Source Data Service:- Name: mongodb_dataservice Location: \MongoDB.dbs Description: N/A Default Namespace: http://ws.wso2.org/dataservice Nested Exception:- java.lang.NullPointerException at org.wso2.carbon.dataservices.core.DataServiceFactory.createDataService(DataServiceFactory.java:207) at org.wso2.carbon.dataservices.core.DBDeployer.createDBService(DBDeployer.java:797) at org.wso2.carbon.dataservices.core.DBDeployer.processService(DBDeployer.java:1152) at org.wso2.carbon.dataservices.core.DBDeployer.deploy(DBDeployer.java:201) at org.apache.axis2.deployment.repository.util.DeploymentFileData.deploy(DeploymentFileData.java:136) at org.apache.axis2.deployment.DeploymentEngine.doDeploy(DeploymentEngine.java:807) at org.apache.axis2.deployment.repository.util.WSInfoList.update(WSInfoList.java:144) at org.apache.axis2.deployment.RepositoryListener.update(RepositoryListener.java:377) at org.apache.axis2.deployment.RepositoryListener.checkServices(RepositoryListener.java:254) at org.apache.axis2.deployment.RepositoryListener.startListener(RepositoryListener.java:371) at org.apache.axis2.deployment.scheduler.SchedulerTask.checkRepository(SchedulerTask.java:59) at org.apache.axis2.deployment.scheduler.SchedulerTask.run(SchedulerTask.java:67) at org.wso2.carbon.core.deployment.CarbonDeploymentSchedulerTask.runAxisDeployment(CarbonDeploymentSchedulerTask.java:93) at org.wso2.carbon.core.deployment.CarbonDeploymentSchedulerTask.run(CarbonDeploymentSchedulerTask.java:138) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NullPointerException at org.wso2.carbon.dataservices.core.engine.DataService.init(DataService.java:352) at org.wso2.carbon.dataservices.core.DataServiceFactory.createDataService(DataServiceFactory.java:190) ... 20 more
Again, I'm not sure if I'm even supposed to put such code in data service definition since the code was meant to be for Rest API definition, the one where you use sequences, mediators etc...
How can I consume my dataservice with an ESB API? Would you please provide an example on how to do that ? I did some research but couldn't find anything.
May I know why you are unable to invoke the data service? Are you getting any error while invocation? if you could provide the logs it will be helpful.
Moreover DSS is used to fetch data from DB ,The best practice is to provide an ESB API which will consume this service rather than exposing DSS service to outside world directly
I send Mail with WSO2 ESB 5.0.0
1. I have uncommented the following line in Axis2.xml file
<transportSender name="mailto" class="org.apache.axis2.transport.mail.MailTransportSender">
<parameter name="mail.smtp.host">smtp.gmail.com</parameter>
<parameter name="mail.smtp.port">587</parameter>
<parameter name="mail.smtp.starttls.enable">true</parameter>
<parameter name="mail.smtp.auth">true</parameter>
<parameter name="mail.smtp.user">lmphuong</parameter>
<parameter name="mail.smtp.password">password</parameter>
<parameter name="mail.smtp.from">lmphuong#gmail.com</parameter>
</transportSender>
<transportReceiver name="mailto" class="org.apache.axis2.transport.mail.MailTransportListener">
<!-- configure any optional POP3/IMAP properties
check com.sun.mail.pop3 and com.sun.mail.imap package documentation for more details-->
</transportReceiver>
2. Add content at messageFormatters in axis2.xml
<messageFormatter contentType="text/html" class="org.apache.axis2.transport.http.ApplicationXMLFormatter"/>
3. I have create Proxy Service in WSO2 ESB
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="EmailSender"
transports="http https"
startOnLoad="true">
<description/>
<target>
<inSequence>
<log/>
<property name="messageType"
value="text/html"
scope="axis2"
type="STRING"/>
<property name="ContentType" value="text/html" scope="axis2"/>
<property name="Subject" value="Testing ESB" scope="transport"/>
<property name="OUT_ONLY" value="true"/>
<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
<payloadFactory media-type="xml">
<format>
<ns:text xmlns:ns="http://ws.apache.org/commons/ns/payload">$1</ns:text>
</format>
<args>
<arg value="Hello WSO2 ESB.....!"/>
</args>
</payloadFactory>
<log level="full"/>
<send>
<endpoint>
<address uri="mailto:ledung123#gmail.com"/>
</endpoint>
</send>
</inSequence>
<outSequence/>
</target>
</proxy>
4. I recieved error
ERROR - MailTransportSender Error creating mail message or sending it to the configured server
javax.mail.AuthenticationFailedException
at javax.mail.Service.connect(Service.java:306)
...
[2017-09-15 08:04:05,945] ERROR - MailTransportSender Error generating mail message
...
Please help me out how to soved this error
Looks like there´s something wrong with your credentials (AuthenticationFailedException). Do you have any special chracters in your credentials? Or is there are proxy server between esb and gmail?
What you could do is start esb in debug/enable wire log to see the complete traffic. More info can be found here.
https://docs.wso2.com/display/ESB500/Debugging+Mediation#DebuggingMediation-Viewingwirelogs
Another option might be to use the GMail connector which can be found here.
https://docs.wso2.com/display/ESBCONNECTORS/Gmail+Connector
https://store.wso2.com/store/pages/top-assets?q=%22_default%22%3A%22gmail%22
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 .