Distinguish operation in wso2 - soap

I came from OpenESB (Glassfish) and I'm new with wso2. I have to mediate a service that it has two operations, 'Block' and 'Consult'.
The only way to distinguish the operations is to evaluate the first node from the soap:body, throught a switch mediator, but always go by default, it doesn't work the case.
(I can't make the distinguish throught get-property('Action') because it doesn't come as http header).
My code to analize the soap-message is the above:
`<log level="custom">
<property xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
name="OP"
expression="$body/*[1]"/>
</log>
<switch xmlns:soap="http://www.w3.org/2003/05/soap-envelope" source="$body/*[1]">
<case regex=".*ConsultRequest.*">
<log level="custom">
<property name="OPERATION" value="CONSULT"/>
</log>
</case>
<case regex=".*BlockRequest.*">
<log level="custom">
<property name="OPERATION" value="BLOCK"/>
</log>
</case>
<default>
<log level="custom">
<property name="OPERATION" value="DEFAULT"/>
</log>
</default>
</switch>`
and the result in the server console is next:
[2015-04-15 11:15:04,611] INFO - LogMediator OP = <cli:BlockRequest xmlns:cli="http://www.eroski.es/pspr/schema/ClientesMDM"><Id_Cliente_Hub>25</Id_Cliente_Hub></cli:BlockRequest>
[2015-04-15 11:15:04,611] INFO - LogMediator OPERATION = DEFAULT
¿Is there anyway to know what operation is invoked by some property?
Can anybody help me :(

$body/*[1] is not the node name, but it's content (value or child xml tree). If you want to get it's name without namespace information, you can use a xpath function called local-name :
local-name($body/*[1])

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

WSO2 EI Dataservice as Rest API with sequence calls

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

Get read time out when Call restful API in the sequence with Iterate mediator in wso2 ESB

I'm new in the WSO2 ESB. I need your help. I get data from database by DSS and send them into a rest web service with call (in block mode) or send mediator. I split my records to individual messages in ESB by Iterate mediator and set iterate mediator properties to ture and then send date as parameters to my API. I can see in the log iterate mediator splits records to individual messages and put them in my html endpoint correctly.
But I get a "read time out response" in ESB after calling my end point. If i don't use iterate mediator and I put parameters directly in the properties as test and send them to my rest API, It works fine. But when I use Iterate mediator to get parameters from DSS and send them to API, it faces with time out error.
I checked log mediator to see what happened, the error is unable to send via post to my endpoint and read time out. I copied the URL for my endpoint from ESB log and tried to invoke it by SoapUI, It works fine without any time out issue.
My api is civicrm api: my Api parametrs are defined :
contact_type={uri.var.contact_type}
first_name={uri.var.first_name}
last_name={uri.var.last_name}
I used Call mediator for call api by blocking mode true.
I sent first_name, last_name, contact_type from DSS:
<Submissions>
<Submission>
<contact_type>Individual</contact_type>
<first_name>Testname</first_name>
<last_name>TestFamily</last_name>
</Submission>
</Submissions>
After iterate mediator I put log mediator and can see the above value.
After calling endpoint, I received this error:
http://localhost/CIVICRM/sites/all/modules/civicrm/extern/rest.php?entity=Contact&action=create&key=1111&user=test&pass=passsss&api_key=1111111111&version=3&contact_type=Individual&first_name=Testname&last_name=TestFamily, MessageID: urn:uuid:daa47ef5-1f7a-4f2c-9372-ba17f0e282ee, Direction: response, MESSAGE = Executing default 'fault' sequence, ERROR_CODE = 401000, ERROR_MESSAGE = Read timed out
When I put this endpoint in SoapUI, It works.
When I don't use DSS and iterate mediator and Put parametrs directly in sequence, it works.
I appreciate your help. Thanks
This can hapen when a response is not sent from your backend. So you can set the following property before the send mediator to get rid of this.
<property name="OUT_ONLY" value="true"/>
Yes, Thanks for your consideration. The sequence that works fine is:
<sequence xmlns="http://ws.apache.org/ns/synapse"
name="importCiviCRM"
trace="disable">
<property name="uri.var.type"
value="Individual"
scope="default"
type="STRING"/>
<property name="uri.var.first"
value="aaaaaa"
scope="default"
type="STRING"/>
<property name="uri.var.last"
value="bbbbbbb"
scope="default"
type="STRING"/>
<property name="FORCE_HTTP_CONTENT_LENGTH"
value="true"
scope="axis2"
type="STRING"/>
<property name="COPY_CONTENT_LENGTH_FROM_INCOMING"
value="true"
scope="axis2"
type="STRING"/>
<property name="HTTP_METHOD" value="POST" scope="axis2" type="STRING"/>
<property name="messageType"
value="application/xml"
scope="axis2"
type="STRING"/>
<header name="To" scope="default" action="remove"/>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
<send buildmessage="true">
<endpoint key="CiviImport"/>
</send>
</sequence>
I tried my above sequence with property Response=True instead of OUT_ONLY and it works fine as well.
my endpoint is:
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="CiviImport">
<http uri-template="http://localhost/CIVICRM%20WAREHOUSE/sites/all/modules/civicrm/extern/rest.php?entity=Contact&action=create&key=111111&user=Testuser&pass=Testpass&api_key=111111111&version=3&contact_type={uri.var.type}&first_name={uri.var.first}&last_name={uri.var.last}"/>
</endpoint>
But when I try to get first_name, last_name and contact_type from DSS and use Iterate mediator for splitting message into separate messages, I face with problem . This is my sequence:
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="CiviCrmAPI">
<iterate xmlns:dss="http://ws.wso2.org/dataservice"
xmlns:ns="http://org.apache.synapse/xsd"
continueParent="true"
id="IterateRequestSink"
expression="//dss:Submission"
sequential="true">
<target>
<sequence>
<property name="uri.var.type"
expression="//dss:contact_type/text()"
scope="default"
type="STRING"/>
<property name="uri.var.first"
expression="//dss:first_name/text()"
scope="default"
type="STRING"/>
<property name="uri.var.last"
expression="//dss:last_name/text()"
scope="default"
type="STRING"/>
<log>
<property name="uri.var.type" expression="get-property('uri.var.type')"/>
<property name="uri.var.first" expression="get-property('uri.var.first')"/>
<property name="uri.var.last" expression="get-property('uri.var.last')"/>
</log>
<property name="FORCE_HTTP_CONTENT_LENGTH"
value="true"
scope="axis2"
type="STRING"/>
<property name="COPY_CONTENT_LENGTH_FROM_INCOMING"
value="true"
scope="axis2"
type="STRING"/>
<property name="HTTP_METHOD" value="POST" scope="axis2" type="STRING"/>
<property name="messageType"
value="application/xml"
scope="axis2"
type="STRING"/>
<header name="To" scope="default" action="remove"/>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
<send buildmessage="true">
<endpoint key="CiviImport"/>
</send>
</sequence>
</target>
</iterate>
</sequence>
I've added Disable-chunking property set value to true before Send mediator.
<property name="DISABLE_CHUNKING" value="true" scope="axis2"/>
The problem was solved.

WSO2 REST to SOAP passing operation parameters

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 .

Wso2 ESB GET PROXY NAME

I would like to know how can I get the name of the proxy in use in a sequence:
<proxy xmlns="http://ws.apache.org/ns/synapse" name="PROXYNAME" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<property> *GET-NAME OF THIS PROXY...* </property>
</inSequence>
</target>
<publishWSDL uri="http://localhost/Test2/Service.asmx?wsdl" />
</proxy>
EDIT
In order to get the Name of the proxy (which should be contained in the header 'To' I am trying this as inSequence of a proxy:
<sequence xmlns="http://ws.apache.org/ns/synapse" name="testsequence">
<property xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="p1" expression="$header/wsa:To" scope="default" />
<log level="custom">
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="***output" expression="get-property('p1')" />
</log>
</sequence>
does not work, any suggestion please?
This will return proxy name.
<log level="custom"> <property name="ProxyName" expression="$ctx:proxy.name"/></log>
Solved with a very simple: get-property('To')
Nuvio,
I'm just wondering what's the real requirement in doing this as the name of a particular proxy service remains static while a particular is completely served by the service. However, if you really want to do this, an easier way would be to have a static property (using property mediator) at the beginning of the sequence and have the proxy name assigned to it. Or you can probably extract the value of the "To" header by using the expression "$header/wsa:To" in which "wsa" corresponds to the relevant addressing namespace, and then write a regular expression to extract the service name.
Cheers,
Prabath