how to update soap response namespace value with wso2 ei - soap

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>

Related

Accumulating SOAP responses together with SOAP requests through wso2esb mediation

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.

WSO2 ESB - soap envelope that is automatically added is causing issues

I'm exploring WSO2 ESB and have hit an issue. I am using a simple pass through proxy to post XML data from SAP (or Postman, to test) which then gets forwarded to a REST API - should be easy!
When I POST direct to the REST API (not through ESB), it works fine.(200, OK)
But WSO2 ESB is adding a SOAP Envelope automatically, which the REST API will not accept. I've tried various approaches to remove the automatically added SOAP envelope, with no success. Tried XSLT transform, POX format, Enrich mediator etc., every suggestion I could find.
(I can remove envelope element using XSLT if it is sent as part of the body, but not the one WSO2 adds in)
I can access the body, without SOAP envelope, using :
<property name="body" expression="$body/*[1]" type="OM"/>
but am not sure how to forward this to the API.
Any ideas how to stop this envelope being added in the first place in WSO2 ESB, or on how to remove it?
I used the xslt code from this answer, which works fine when I include the SOAP tags in the body, but has no effect on the SOAP envelope that seems to get automatically added in WSO2 (except to give the error, below).
I tried different variations of the line:
<xsl:apply-templates select="soap:Envelope/soap:Body/*"/>
such as
<xsl:apply-templates select="soap:Envelope/*"/>
<xsl:apply-templates select="/*"/>
this is an error I see in the ESB log:
Unable to perform XSLT transformation using : Value {name ='null', keyValue ='discountPayment'} against source XPath : s11:Body/child::[position()=1] | s12:Body/child::[position()=1] reason : Unable to create an OMElement using XSLT result
I am pretty new to WSO2 ESB, and have not used XSLT before, so may be some very basic mistake in my approach....
here is my proxy xml, and the XSLT "removeSOAP":
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="APIServer" startOnLoad="true" trace="disable"
transports="https http" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<log level="full">
<property name="FirstLog" value="APITest LOG...."/>
<property name="payload" expression="$body/*[1]" type="OM"/>
</log>
<xslt key="removeSOAP"/>
<log level="full">
<property name="SecondLog" value="after xslt...."/>
</log>
<property name="messageType" scope="axis2" type="STRING" value="application/xml"/>
<send>
<endpoint name="endpoint_urn_uuid_xxxxxx">
<address trace="disable" uri="http://myAPIendpoint " />
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full"/>
<send/>
</outSequence>
<faultSequence/>
</target>
</proxy>
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="removeSOAP" xmlns="http://ws.apache.org/ns/synapse">
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:m="http://www.example.org/stock">
<xsl:template match="/">
<xsl:apply-templates select="soap:Envelope/soap:Body/*"/>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
</localEntry>
A colleague figured this out today, I post the answer here incase it helps someone in the future:
in the proxy service, before send, add the line
<property name="DISABLE_CHUNKING" value="true" scope="axis2"/>
then it works.
No need for the XSLT transform that is shown above, just this line fixes it.
if your backend it´s an API better you can use the http endpoint https://docs.wso2.com/display/ESB500/HTTP+Endpoint:
<send>
<endpoint>
<http method="POST"
uri-template="http://your.backend.endpoint.org/"/>
</endpoint>
</send>

wso2 esb change soap namespace prefix

I have a proxy service on my wso2esb and a response like this:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
..........
</soap:Body>
</soap:Envelope>
Does wso2esb have any configurable place where I can change the soap prefix? I need a result like this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
..........
</soapenv:Body>
</soapenv:Envelope>
You should'nt care about the name of the namespace, but if you really need that, you can for exemple use enrich mediator to : Save the body, change soap envelope, restore the body
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="TestSOF"
transports="http"
startOnLoad="true"
trace="disable">
<description/>
<target endpoint="ProductEngineServiceMock1">
<outSequence>
<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>
<send/>
</outSequence>
</target>
</proxy>

WSO2 ESB 4.8.0 Proxy service transcoding iso to utf-8

Context:
I use wso2esb 4.8.0.
I have proxy service:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="eProxy"
transports="https"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
</inSequence>
<outSequence>
<send/>
</outSequence>
<endpoint>
<address uri="http://10.24.74.53:8088/xxxService?WSDL"/>
</endpoint>
</target>
<publishWSDL uri="file://wso2esb-4.8.0/repository/mcc/resources/xxx.wsdl"/>
<description/>
</proxy>
Problem:
xxxService response is encoding in iso-8859 and I want to transform this response to utf-8
My first approch:
I use xslt mediator :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" />
<xsl:template match="/">
<result>
<xsl:value-of select="." />
</result>
</xsl:template>
</xsl:stylesheet>
but I have error
ERROR NativeWorkerPool uncaught exception java.lang.stackoverflowerror com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.scanName(XMLEntityScanner.java:726)
My second approch:
I set property in out Sequence:
<property name='CHARACTER_SET_ENCODING' scope='Axis2' value='UTF-8'/>
but I have error
ERROR NativeWorkerPool uncaught exception java.lang.stackoverflowerror com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.scanName(XMLEntityScanner.java:726)
My last approch:
I write custom mediator but I dont know how chang SoapEnvelope or SoapBody encoding
thinks for your Help.
To change encoding and content type, look at ContentType and messageType properties : http://docs.wso2.org/display/ESB480/Generic+Properties
Sample value : text/xml; charset=ISO-8859-1

WSO2 ESB adding prefix to header

I try to use the WSO2 ESB with the SAP Solution Manager Webservice as an endpoint.
For sending a message to the Webservice I need to modify the SOAP Header.
While searching with google I found out that I could use the Enrich Mediator for this. But I couldn't find an example how to add the prefix to the header.
What I have is this:
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<urn:ReadCompleteIncident>
<IncidentGuid>xxxxx</IncidentGuid>
<SystemGuid>xxx</SystemGuid>
</urn:ReadCompleteIncident>
</soapenv:Body>
</soapenv:Envelope>
But I get an error because the ESB doesn't know the prefix "urn:". So I have to add "xmlns:urn="urn:sap-com:document:sap:soap:functions:mc-style"" to the Header for getting this:
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:urn="urn:sap-com:document:sap:soap:functions:mc-style">
<soapenv:Body>
<urn:ReadCompleteIncident>
<IncidentGuid>xxxxx</IncidentGuid>
<SystemGuid>xxx</SystemGuid>
</urn:ReadCompleteIncident>
</soapenv:Body>
</soapenv:Envelope>
How can I do this with the Enrich Mediator? Or is there another solution?
Thank you :)
You can use the Header mediator of WSO2 ESB to achieve your requirement.
<header name="Action" value="urn:ReadCompleteIncident"/>
You can refer this link to find more information.
http://docs.wso2.org/wiki/display/ESB460/Header+Mediator
I solved this problem with Enrich Mediator. For example, here is my proxy.
Input message to ESB:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header/>
<soap:Body>
<content>Message content</content>
</soap:Body>
</soap:Envelope>
Required Input message to SAP PI:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:xxxx">
<soapenv:Header/>
<soapenv:Body>
<urn:xxxx>
<content>Message content</content>
</urn:xxxx>
</soapenv:Body>
</soapenv:Envelope>
Solution:
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="WSO2toSAP"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<property name="FORCE_SC_ACCEPTED"
value="true"
scope="axis2"
type="STRING"/>
<log level="full"/>
<enrich>
<source type="body" clone="true"/>
<target type="property" property="INPUT_MESSAGE"/>
</enrich>
<enrich>
<source type="inline" clone="true">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body/>
</soapenv:Envelope>
</source>
<target type="envelope"/>
</enrich>
<enrich>
<source type="inline" clone="true">
<urn:xxxx xmlns:urn="urn:xxxx"/>
</source>
<target type="body"/>
</enrich>
<enrich>
<source type="property" clone="true" property="INPUT_MESSAGE"/>
<target type="body" action="child"/>
</enrich>
<log level="full"/>
<send>
<endpoint key="WSO2toSAP_endpoint"/>
</send>
</inSequence>
</target>
<description/>
</proxy>
I hope, that I help you :)
I think there are multiple ways you can solve this problem -
payloadFactory mediator to manipulate the request or response.
using script mediator - check this page http://abeykoon.blogspot.com/2013/03/encoding-and-decoding-xml-using-wso2-esb.html#comment-form for more details on how to use the script. As you can see, the blogger is generating the request using payloadFactory and then manipulate it using the scripts to get the desired effect.
If I find time, I will try to build a quick solution for you using the scripts.
All the best..