WSO2 EI | SOAP Envelope Exception - soap

I am using WSO2 EI interacting with a SOAP Service. I have a weird case when SOAP Service returns HTTP 500, WSO2 returns the following exception. Can someone help me understand why this is happening?
http://www.w3.org/2005/08/addressing/anonymous, WSAction: , SOAPAction: , MessageID: urn:uuid:d176d8c6-57ff-4ee3-b5ca-e043602d6fec, Direction: response, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><soapenv:Envelope><soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing"><wsa:To>http://www.w3.org/2005/08/addressing/anonymous</wsa:To><wsa:ReplyTo><wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address></wsa:ReplyTo><wsa:MessageID>urn:uuid:992bea3f-16f0-49d3-91a2-1e03375bac9c</wsa:MessageID><wsa:Action>http://www.w3.org/2005/08/addressing/soap/fault</wsa:Action></soapenv:Header><soapenv:Body><soapenv:Fault><faultcode>soapenv:</faultcode><faultstring>First Element must contain the local name, Envelope , but found PhoneNumber</faultstring><detail><Exception>org.apache.axis2.AxisFault: Exception during creation of SOAP envelope structure
at com.ibm.broker.axis2.Axis2Invoker.processInboundRequest(Axis2Invoker.java:3527)
at com.ibm.broker.axis2.Axis2Invoker.invokeAxis2(Axis2Invoker.java:3101)
at com.ibm.broker.axis2.TomcatNodeRegistrationUtil.invokeAxis2(TomcatNodeRegistrationUtil.java:669)
at com.ibm.broker.axis2.TomcatNodeRegistrationUtil.invokeAxis2(TomcatNodeRegistrationUtil.java:615)
Caused by: org.apache.axiom.soap.SOAPProcessingException: First Element must contain the local name, Envelope , but found PhoneNumber
at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.constructNode(StAXSOAPModelBuilder.java:305)
at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.createOMElement(StAXSOAPModelBuilder.java:252)
at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.createNextOMElement(StAXSOAPModelBuilder.java:234)
at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:249)
at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.getSOAPEnvelope(StAXSOAPModelBuilder.java:204)
at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.<init>(StAXSOAPModelBuilder.java:154)
at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.<init>(StAXSOAPModelBuilder.java:140)
at com.ibm.broker.axis2.SoapUtilities.createSOAPMessage(SoapUtilities.java:2224)
at com.ibm.broker.axis2.SoapUtilities.createSOAPMessage(SoapUtilities.java:1924)
at com.ibm.broker.axis2.Axis2Invoker.processInboundRequest(Axis2Invoker.java:3521)
... 3 more

Problem solved after adding "soap11" to indicate that this request is a SOAP request.

Related

Problem with validation of SOAP request with Zeep (python)

I have problems to get SOAP request through Zeep, I get a (client) validation error... I have also tested with SoapUI and that does NOT give me the same validation error...
The specification below is from the server... Based on that specification, the OrderStatus and SynchStatus are needed to perform the request.
<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/ xmlns:web="WebServiceProvider">
<soapenv:Header/>
<soapenv:Body>
<web:Order_Get>
<!--Optional:-->
<web:orderOptions>
<web:FromDate>?</web:FromDate>
<web:ToDate>?</web:ToDate>
<web:OrderStatus>?</web:OrderStatus>
<web:SynchStatus>?</web:SynchStatus>
<!--Optional:-->
<web:OrderNumber>?</web:OrderNumber>
<web:FromOrderNumberToLastRecieved>?</web:FromOrderNumberToLastRecieved>
<web:PaymentStatus>?</web:PaymentStatus>
</web:orderOptions>
</web:Order_Get>
</soapenv:Body>
</soapenv:Envelope>
However, executing this from the SoapUI without OrderStatus and SynchStatus will give me a list of all the orders for the specified dates:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="WebServiceProvider">
<soapenv:Header/>
<soapenv:Body>
<web:Order_Get>
<web:orderOptions>
<web:FromDate>2021-03-30</web:FromDate>
<web:ToDate>2021-03-31</web:ToDate>
</web:orderOptions>
</web:Order_Get>
</soapenv:Body>
</soapenv:Envelope>
I want to do the same with Zeep (https://github.com/mvantellingen/python-zeep) but the client validation fails...
I initiate the request with the following code:
api_url = 'https://abc.se/Webservice20/v3.0/webservice.asmx?WSDL'
session.auth = HTTPDigestAuth(username, password)
api = Client(api_url, transport=Transport(session=session))
And then I try to execute the following request:
order_options = {
'FromDate': '2021-03-30',
'ToDate': '2021-03-31',
}
orders = api.service.Order_Get(orderOptions=order_options)
This will result in the following error:
zeep.exceptions.ValidationError: Missing element OrderStatus (Order_Get.orderOptions.OrderStatus)
If I add OrderStatus to the request, I will get a validation error saying that SynchStatus is missing. When that has been added as well, the request is sent to the server.
I.e. it seems like the zeep client is more strict with regards to validating the data in the request than what the server is... Is there a way to force the client to skip this validation?
Many thanks in advance!
Searched a bit more and found a workaround in this post: Getting zeep.exceptions.ValidationError: Missing element for method that worked with suds
So the solution in my case looks like this:
from zeep import xsd
...
order_options = {
'FromDate': '2021-03-30',
'ToDate': '2021-03-31',
'OrderStatus': xsd.SkipValue,
'SynchStatus': xsd.SkipValue,
}
response = api.service.Order_Get(orderOptions=order_options)
This will block zeep from doing client side validation of the parameters OrderStatus and SynchStatus.
it seems like the zeep client is more strict with regards to validating the data in the request than what the server is...
Looks like it.
Looking at the request SoapUI generates based on the WSDL, the two fields you mention are mandatory:
<web:orderOptions>
<web:FromDate>?</web:FromDate>
<web:ToDate>?</web:ToDate>
<web:OrderStatus>?</web:OrderStatus>
<web:SynchStatus>?</web:SynchStatus>
<!--Optional:-->
<web:OrderNumber>?</web:OrderNumber>
<web:FromOrderNumberToLastRecieved>?</web:FromOrderNumberToLastRecieved>
<web:PaymentStatus>?</web:PaymentStatus>
</web:orderOptions>
So the error that the zeep client displays is correct. Zeep inspects the WSDL and generates the corresponding code to use the types in the contract. Your WSDL contract says that OrderStatus and SynchStatus are mandatory. The fact that the server doesn't validate them shows a problem: the web service isn't respecting it's own documented contract
The WSDL and the behavior of the web service should be the same. I suggest you contact the web service owners and ask about this behavior. It might be a validation missing on the server and what you get is just some side effect of that, or the behavior is intentional but someone forgot to update the WSDL to say that you can also make the call without those parameters.
Meanwhile, the workaround is very simple. Download the WSDL, change it to make the two fields optional, then feed this changed WSDL to zeep for it to generate the code, instead of using the original WSDL. You should however clarify this with the web service provider. If it's indeed a neglect of someone, this might be spotted at some point and fixed, making your workaround call fail a server validation because of the missing fields.

SOAP Fault response from Wiremock not detected as SOAPFault by API-Connect 2018

When I call the actual SOAP service (using Postman and SoapUI) with an invalid parameter value, it causes a SOAP-Fault response, with HTTP 200 .
I copied the body of the response into a Wiremock response file, whose corresponding mapping file returns HTTP 200.
When I use Postman to invoke the SOAP service and the mocked one, the 'Body' of the responses are identical (apart from headers, as the mocked response doesn't explicitly set any).
When my API invokes the actual SOAP service, the SOAPError is caught, the processing stops and the API is processed as defined in the 'catch' section.
However, when the API invokes the mocked SOAP service, the SOAPError is not detected after 'invoke', processing continues and produces an incorrect response.
This suggests that there is something 'extra' returned in a fault from a real SOAP service, that APIC uses to detect a SOAPError. What is it?
I would add it to the mocked response, if only I knew what it should be.
BTW: The response headers are the same for both valid parameters and the SOAP Fault for an invalid one.
[edit]
Thanks #Jan Papenbrock. Adding "Content-Type = text/xml" sorted it out.
I don't know why I thought I was receiving the same headers from real and mocked responses - total rubbish!
John
[/edit]
Had the same error with WireMock and fixed it with the help of answers to this question. In my case, the Content-Type header was missing.
I suggest you try the following:
Send Content-Type: text/xml as response header (or try application/soap+xml)
Return HTTP status code 500 for the SOAP fault response, according to the specification (note: status 400 did not work for me).
My stub generation looks like this:
static ResponseDefinitionBuilder errorInvalidStopResponse() {
responseWithBodyFile('response-error-invalid-stop.xml')
.withStatus(500)
}
static ResponseDefinitionBuilder responseWithBodyFile(String responseBodyFileName) {
aResponse()
.withStatus(200)
.withHeader("Content-Type", "text/xml")
.withBodyFile(responseBodyFileName)
}

WSO2 API Manager - Publishing API with non-XML response

I am trying to proxy the following call through WSO2 API Manager
http://api.qrserver.com/v1/create-qr-code/?data=HelloWorld&size=100x100
which returns a QR code image. I published the API using http://api.qrserver.com/v1/ as endpoint, no problem there. But when I perform the call through the API Manager, I get the following error:
curl -H 'Authorization:Bearer 7q6W4LteX9idveFWbSa_oaGPhVsa' 'http://ec2-xx-xx-xx-xx.eu-west-1.compute.amazonaws.com:8280/qrcode/1.0.0/create-qr-code/?data=HelloWorld&size=100x100'
<Exception>Unexpected response received. HTTP response code : 200 HTTP status : OK exception : com.ctc.wstx.exc.WstxIOException: Invalid UTF-8 start byte 0x89 (at char #1, byte #-1)</Exception>
when performing the call directly the response header seems good to me (the mime type image/png is correctly set), but the WSO2 API proxy refuses the response... what I am doing wrong? Setting a wadl file with response mediaType="image/png" does not seem to help either.
Thanks in advance
I have a similar problem in wso2 esb. Seems that the response works with short xml files but not with a big one.
This problem is due to not having match message builders and formatters by default in API manager's axis2.xml. Please add following parameters to axis2.xml.
<messageBuilder contentType=".*" class="org.wso2.carbon.relay.BinaryRelayBuilder"/>
<messageFormatter contentType=".*" class="org.wso2.carbon.relay.ExpandingMessageFormatter"/>
Thanks.
Sanjeewa.

How to deserialize soap response with multiref in .net?

I am making a .net wcf client for java ws. But when I make a request, and response contains fault, it also contains multiRef section. So I get this exception:
Server returned an invalid SOAP Fault.
End element 'Body' from namespace 'http://schemas.xmlsoap.org/soap/envelope expected. Found element 'multiRef' from namespace ''
This is how response from server looks like (taken directly from network):
<soapenv:Envelope>
<soapenv:Header/>
<soapenv:Body>
<soapenv:Fault>...</soapenv:Fault>
<multiRef>...</multiRef>
</soapenv:Body>
</soapenv:Envelope>
Is there any way to configure my wcf client to deserialize that message right ? Or a possibility to get a raw response xml?

SOAP Action WSDL

I'm trying to implement a client for National Rail Enquiries' SOAP Service (http://www.livedepartureboards.co.uk/ldbws/).
I stick the WSDL (http://realtime.nationalrail.co.uk/ldbws/wsdl.aspx) into http://soapclient.com/soaptest.html, but I get back the error message "Unable to handle request without a valid action parameter. Please supply a valid soap action."; what on earth should the action be?
Thanks,
Stewart
edit:
I just used soapclient.com as a quick example. In my software, I send the following XML; I still get that I'm missing an action.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://thalesgroup.com/RTTI/2008-02-20/ldb/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:ldbt2="http://thalesgroup.com/RTTI/2008-02-20/ldb/types" xmlns:ldbt="http://thalesgroup.com/RTTI/2007-10-10/ldb/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ct="http://thalesgroup.com/RTTI/2007-10-10/ldb/commontypes" >
<SOAP-ENV:Body>
<ldbt2:GetDepartureBoardRequest xmlns:ldbt2="http://thalesgroup.com/RTTI/2008-02-20/ldb/" >
<ldbt2:numRows>5</ldbt2:numRows>
<ldbt2:crs>WAT</ldbt2:crs>
<ldbt2:filterCrs>GLD</ldbt2:filterCrs>
<ldbt2:filterType>to</ldbt2:filterType>
<ldbt2:timeOffset>0</ldbt2:timeOffset>
</ldbt2:GetDepartureBoardRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
If its a SOAP 1.1 service then you will also need to include a SOAPAction HTTP header field:
http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528
I have come across exactly the same problem when trying to write a client for the National Rail SOAP service with Perl.
The problem was caused because the Perl module that I'm using 'SOAP::Lite' inserts a '#' in the SOAPAction header ...
SOAPAction: "http://thalesgroup.com/RTTI/2008-02-20/ldb/#GetDepartureBoard"
This is not interpreted correctly by .NET servers. I found this out from Example 3-19 in O'Reilly's Programming Web Services with SOAP . The solution was given below in section 3-20, namely you need to explicitly specify the format of the header with the 'on_action' method.
print SOAP::Lite
-> uri('urn:Example1')
-> on_action(sub{sprintf '%s/%s', #_ })
-> proxy('http://localhost:8080/helloworld/example1.asmx')
-> sayHello($name)
-> result . "\n\n";
My guess is that soapclient.com is using SOAP::Lite behind the scenes and so are hitting the same problem when talking to National Rail.
The solution is to write your own client so that you have control over the format of the SOAPAction header ... but you've probably done that already.
SOAPAction is required in SOAP 1.1 but can be empty ("").
See https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528
"The header field value of empty string ("") means that the intent of the SOAP message is provided by the HTTP Request-URI."
Try setting SOAPAction=""
When soapAction is missing in the SOAP 1.2 request (and many clients do not set it, even when it is specified in WSDL), some app servers (eg. jboss) infer the "actual" soapAction from {xsd:import namespace}+{wsdl:operation name}.
So, to make the inferred "actual" soapAction match the expected soapAction, you can set the expected soapAction to {xsd:import namespace}+{wsdl:operation name} in your WS definition (#WebMethod(action=...) for Java EE)
Eg. for a typical Java EE case, this helps (not the Stewart's case, National Rail WS has 'soapAction' set):
#WebMethod(action = "http://packagename.of.your.webservice.class.com/methodName")
If you cannot change the server, you will have to force client to fill soapAction.
I've just spent a while trying to get this to work an have a written a Ruby gem that accesses the API. You can read more on it's project page.
This is working code in Ruby:
require 'savon'
client = Savon::Client.new do
wsdl.document = "http://realtime.nationalrail.co.uk/LDBWS/wsdl.aspx"
end
response = client.request 'http://thalesgroup.com/RTTI/2012-01-13/ldb/GetDepartureBoard' do
namespaces = {
"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.xml do |xml|
xml.soap(:Envelope, namespaces) do |xml|
xml.soap(:Header) do |xml|
xml.AccessToken do |xml|
xml.TokenValue('ENTER YOUR TOKEN HERE')
end
end
xml.soap(:Body) do |xml|
xml.GetDepartureBoardRequest(xmlns: "http://thalesgroup.com/RTTI/2012-01-13/ldb/types") do |xml|
xml.numRows(10)
xml.crs("BHM")
xml.filterCrs("BHM")
xml.filterType("to")
end
end
end
end
end
p response.body
Hope that's helpful for someone!
We put together Web Services on Windows Server and were trying to connect with PHP on Apache. We got the same error. The issue ended up being different versions of the Soap client on the different servers. Matching the SOAP versions in the options on both servers solved the issue in our case.
the service have 4 operations:
1. GetServiceDetails
2. GetArrivalBoard
3. GetDepartureBoard
4. GetArrivalDepartureBoard
I have solved this problem, in Java Code, adding:
MimeHeaders headers = message.getMimeHeaders();
headers.addHeader("SOAPAction", endpointURL);