Accumulating SOAP responses together with SOAP requests through wso2esb mediation - soap

I have a SOAP web service which can be accessed like:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:sys="system">
<soap:Body>
<sys:getAccountInfo>
<account id="132456"/>
</sys:getAccountInfo>
</soap:Body>
</soap:Envelope>
This web service would provide the following response:
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Body>
<ns1:getAccountInfoResponse xmlns:ns1="system">
<balance value="555">
</ns1:getAccountInfoResponse>
</S:Body>
</S:Envelope>
My challenge is to provide a proxyfying service which can accept multiple accounts as an input and respond with balance for each one like the following:
Request into proxy:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:sys="systemProxy" xmlns:inner="innerProxyNamespace">
<soap:Body>
<sys:getAccountInfo>
<inner:account id="123456"/>
<inner:account id="123457"/>
<inner:account id="123458"/>
</sys:getAccountInfo>
</soap:Body>
</soap:Envelope>
Proxy response:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:sys="systemProxy" xmlns:inner="innerProxyNamespace">
<soap:Body>
<sys:getAccountInfoResponse>
<inner:account id="123456">
<inner:balance value="555"/>
</inner:account>
<inner:account id="123457">
<inner:balance value="666"/>
</inner:account>
<inner:account id="123458">
<inner:balance value="777"/>
</inner:account>
</sys:getAccountInfoResponse>
</soap:Body>
<soap:Envelope>
I am using Iterate and Aggregate mediator for splitting incoming request into multiple requests to backend and accumulating responses from backend into single message. The problem is I can not find the right way to include account id into proxy response even with Enrich mediator.
I do iteration sequence like this:
<!-- it is correct proxy incoming message format -->
<iterate attachPath="soap:Body/sys:getAccountInfo"
expression="$body/sys:getAccountInfo/account"
preservePayload="true"
xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:sys="systemProxy">
<target>
<sequence>
<payloadFactory>
<!-- payloadFactory configuration skipped -->
</payloadFactory>
<enrich>
<source clone="true" type="body"/>
<target property="originalRequest" type="property"/>
</enrich>
<send>
<endpoint key="BackendEndpoint"/>
</send>
</sequence>
</target>
</iterate>
So the question is - what is the right way to aggregate all response messages from backend into one preserving data from the original request?

I used Propetry and PayloadFactory mediators before the Aggregate mediator. It let me include request into response before aggregation. Then I aggregated them all together.

Related

how to update soap response namespace value with wso2 ei

I have a proxy service to expose a soap api on wso2 ei, and i need to update the namespace value of the soap response with my proxy service and return another namespace value.
I have tried with the enrich mediator as follows inside the outsequence.
<property name="namespace"
scope="default"
type="STRING"
value="http://tempuri-updated.org/"/>
<enrich>
<source clone="false" property="namespace" type="property"/>
<target xmlns:ser="http://services.samples"
xmlns:ns="http://org.apache.synapse/xsd"
xpath="namespace-uri($body/*)/text()"/>
</enrich>
I get this error.
ERROR - EnrichMediator Invalid Target object to be enrich.
my actual soap response is as follows
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<AddResponse xmlns="http://tempuri.org/">
<AddResult>12</AddResult>
</AddResponse>
</soap:Body>
</soap:Envelope>
my expected output as follows
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<AddResponse xmlns="http://tempuri-updated.org/">
<AddResult>12</AddResult>
</AddResponse>
</soap:Body>
</soap:Envelope>
All your feedbacks are welcome
This cannot be done with the enrich mediator. Because in the code related to enrich mediator target handling [1], the parsed result of an xpath expression should be one of SOAPHeaderImpl, OMElement, OMText or OMAttribute. Since namespace-uri() is just returning a string value, the target to be enriched is becoming invalid. As an alternative to this use case, we can do an XSLT transformation using the XSLT mediator. Following is a sample XSL style sheet I tried.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#* | comment() | processing-instruction()">
<xsl:copy/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}"
namespace="http://tempuri-updated.org/">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
We can refer this style sheet in the XSLT mediator before sending the response out from the EI. The new namespace will be added to the body.
Try this.
http://codertechblog.com/wso2-change-payload-soap-envelope-namespace/
<sequence name="seTestChangeNamespace" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
(...)
<enrich>
<source type="body"/>
<target type="property" property="INPUT_MESSAGE"/>
</enrich>
<enrich>
<source type="inline">
<myns:Envelope xmlns:myns="http://schemas.xmlsoap.org/soap/envelope/">
<myns:Body/>
</myns:Envelope>
</source>
<target type="envelope"/>
</enrich>
<enrich>
<source type="property" property="INPUT_MESSAGE"/>
<target type="body"/>
</enrich>
(...)
</sequence>

icCube XMLA request documentation

Is there any documentation on how to formulate a request to the XMLA?
The icCube XMLA endpoint for me is: http://localhost:8282/icCube/xmla
I want to make a demo call to the endpoint using postman or something similar, but I am not sure which parameters to pass in the SOAP request.
I have tried:
<x:Envelope xmlns:x="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:schemas-microsoft-com:xml-analysis">
<x:Header>
<urn:Session SessionId="?" mustUnderstand="?"/>
<urn:BeginSession mustUnderstand="?"/>
<urn:EndSession SessionId="?" mustUnderstand="?"/>
</x:Header>
<x:Body>
<urn:Execute>
<Command>
<Statement>
SELECT
{[Customers].[Geography].[All Regions].[North America].[Canada].[Ottawa]} on COLUMNS,
{[Measures].[Count]} on ROWS
FROM [Sales]
</Statement>
</Command>
<Properties/>
</urn:Execute>
</x:Body>
</x:Envelope>
And I get an empty response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<Session SessionId="1hb96vaa7acol14bj97tyokd4f" xmlns="urn:schemas-microsoft-com:xml-analysis"/>
</soap:Header>
<soap:Body>
<ExecuteResponse xmlns="urn:schemas-microsoft-com:xml-analysis">
<return>
<root xmlns="urn:schemas-microsoft-com:xml-analysis:empty"/>
</return>
</ExecuteResponse>
</soap:Body>
</soap:Envelope>
Does anyone know where I can find some more information on how to make this request? The icCube documentation at http://www.iccube.com/support/documentation/user_guide/running_iccube/xmla.php is basically non-existent.
Thank you in advance for any help.
I had to add the correct properties information to the soap call:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<Execute xmlns="urn:schemas-microsoft-com:xml-analysis" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<Command>
<Statement>
SELECT
{[Customers].[Geography].[All Regions].[North America].[Canada].[Ottawa]} on COLUMNS,
{[Measures].[Count]} on ROWS
FROM [Sales]
</Statement>
</Command>
<Properties>
<PropertyList>
<Catalog>Sales</Catalog>
</PropertyList>
</Properties>
</Execute>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The best documentation I have been able to find for the XMLA is the XML for Analysis Specification.

Access a web-service with session-key/token from WSO2 ESB

I'm starting to evaluate WSO2 ESB and try to implement some simple but real life scenarios.
What I'm trying to do, in this specific case is connect to a web-service that uses a session-key in the payload to do the authentication. So there is one web-service call with user and password to get the key and then I need to put this into the payload of the second web-service call to actually retrieve data from a service.
I don't want to log in with every service call, for performance reasons, but log in once, store the key for some time and do a couple of requests.
The service I want to call is a SugarCRM web-service.
The login message would be something like this:
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sug="http://www.sugarcrm.com/sugarcrm" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<soapenv:Header/>
<soapenv:Body>
<sug:login soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<user_auth xsi:type="sug:user_auth">
<user_name xsi:type="xsd:string">interface</user_name>
<password xsi:type="xsd:string">MD5HASHOFPASSWORD</password>
</user_auth>
<application_name xsd:string">dummy</application_name>
<name_value_list xsi:type="sug:name_value_list" soapenc:arrayType="sug:name_value[]"/>
</sug:login>
</soapenv:Body>
Which returns something like this:
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://www.sugarcrm.com/sugarcrm">
<SOAP-ENV:Body>
<ns1:loginResponse xmlns:ns1="http://www.sugarcrm.com/sugarcrm">
<return xsi:type="tns:entry_value">
<id xsi:type="xsd:string">loggfi0i3j6eeugs7l0a0m2587</id>
</return>
</ns1:loginResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Then I need to use the "id" field as the token for a new request.
Example, to request all the Leads (the "id" is put into the "session" field):
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sug="http://www.sugarcrm.com/sugarcrm" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<soapenv:Header/>
<soapenv:Body>
<sug:get_entry_list soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<session xsi:type="xsd:string">loggfi0i3j6eeugs7l0a0m2587</session>
<module_name xsi:type="xsd:string">Leads</module_name>
</sug:get_entry_list>
</soapenv:Body>
</soapenv:Envelope>
This request then returns all the Leads in the database.
Equally this is needed for accessing web-services that use OAuth2, for example the REST-API of MS Dynamics CRM, only then I need to put the token/bearer in the header.
How would I go about realizing the above scenario in WSO2 ESB? I'm sure this is pretty common, but I have not found documentation or examples for it.
Here is the sequence to get the session-id from the CRM:
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="sugar_login" trace="enable" xmlns="http://ws.apache.org/ns/synapse">
<payloadFactory media-type="xml">
<format>
<sug:login xmlns:sug="http://www.sugarcrm.com/sugarcrm">
<sug:user_auth>
<user_name>interface</user_name>
<password>MD5HASHOFPASSWORD</password>
<version>1</version>
</sug:user_auth>
<application_name>dummy</application_name>
</sug:login>
</format>
</payloadFactory>
<header name="To" value="http://my.sugarcrm.com:9090/service/v4_1/soap.php"/>
<call>
<endpoint name="templEPTimeout" template="org.wso2.carbon.connector.sugarcrm.timeout">
<axis2ns653:parameter name="timoutDuration" value="6000" xmlns:axis2ns653="http://ws.apache.org/ns/synapse"/>
<axis2ns654:parameter name="maximumDuration" value="3000" xmlns:axis2ns654="http://ws.apache.org/ns/synapse"/>
<axis2ns655:parameter name="progressAFactor" value="2.0" xmlns:axis2ns655="http://ws.apache.org/ns/synapse"/>
<axis2ns656:parameter name="initialDuration" value="2000" xmlns:axis2ns656="http://ws.apache.org/ns/synapse"/>
</endpoint>
</call>
<!-- Remove response custom header information -->
<header action="remove" name="X-SOAP-Server" scope="transport"/>
<header action="remove" name="Cache-control" scope="transport"/>
<header action="remove" name="Vary" scope="transport"/>
<header action="remove" name="Expires" scope="transport"/>
<header action="remove" name="Set-Cookie" scope="transport"/>
<header action="remove" name="path" scope="transport"/>
<property expression="//ns1:loginResponse/return/id"
name="sugarsessionid" scope="default" type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
</sequence>
You can use the sugarcrm connector to connect with SugarCRM API. You can find the sugarcrm connector at WSO2 Store. Find more details in the documentation.

How to retrieve SOAP response header in a SOAPFaultException in Apache CXF

I have a trouble in Apache CXF where some code throws SOAPFaultException.
My original SOAP response is as following :
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope ...>
<soap:Header>
<awsse:Session TransactionStatusCode="InSeries">
<awsse:SessionId>012GBF5W3H</awsse:SessionId>
<awsse:SequenceNumber>1</awsse:SequenceNumber>
<awsse:SecurityToken>3CGFFDO499VDB7WTRT37R6HPV</awsse:SecurityToken>
</awsse:Session>
</soap:Header>
<soap:Body>
<soap:Fault xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<faultcode>soap:Client</faultcode>
<faultstring>SOME_FAULT_STRING</faultstring>
<faultactor>SOME_FAULT_FACTOR</faultactor>
</soap:Fault>
</soap:Body>
</soap:Envelope>
I receive later a SOAPFaultException with information contains only soap:Body/soap:Fault. However, I need information from soap:Header section for further processing.
How can I pass these Header information to SOAPFaultException?

coldfusion publish webservice using SOAP

I am trying to create a web service that can be consumed with SOAP. I were exercising with normal webservices that returns any values, but know i want to check which elements in the SOAP:BODY are needed and return them with a response. I found the methods
GetSoapRequest()
and
AddSoapResponse()
in the livedoc from adobe, but don't understand how to use them.
I saw the explenation of a request and response on w3school.com
i tried to solve the Problem with the tags "cfsavecontent"
<cffunction
name="soap"
access="remote"
returntype="any"
output="false">
<cfsavecontent variable="soapMessage">
<?xml version="1.0">
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
</soap:Header>
<soap:Body>
<m:GetPriveResponse xmlns:m="namespace">
<m:Price>1.90</m:Price>
</m:GetPriceResponse>
</soap:Body>
</soap:Envelope>
</cfsavecontent>
but it only works, if the cffunction has returntype="any". The type "xml" occurs an error.
thx for helf
The easiest way to create a web service in CF, see
Creating components for web services http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec13a13-7fe2.html
Publishing web services
http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec22c24-78b7.html
I just installed the soapUI eclipse addon and called the WSDL that includes an argument of a complexe type. After testing the methods of my web service with the addon, I got the SOAP-Message I was searching all the time. Maybe it will help anybody, i just where searching long time for this solution.
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:com="http://components.conner.somebody">
<soapenv:Header/>
<soapenv:Body>
<com:echoAddress soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<input xsi:type="com:Address">
<City xsi:type="xsd:string">?</City>
<Country xsi:type="xsd:string">?</Country>
<State xsi:type="xsd:string">?</State>
<Street xsi:type="xsd:string">?</Street>
</input>
</com:echoAddress>
</soapenv:Body>
</soapenv:Envelope>
Here is the method of the coldfusion component that will be called
<cffunction
name="echoAddress"
returnType="address"
output="false"
access="remote">
<cfargument
name="input"
type="address">
<cfreturn #arguments.input#>
</cffunction>