I'm trying to add a SOAP API to APIM 1.10.0.
First, I'll try to test the SOAP service itself, using the following CURL. The service should return weather conditions of a given city/country:
curl -X POST -T soap.xml -H "Content-Type: text/xml" \
"http://www.webservicex.net/globalweather.asmx"
Providing the following soap.xml:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetWeather xmlns="http://www.webserviceX.NET">
<CityName>Eilat</CityName>
<CountryName>Israel</CountryName>
</GetWeather>
</soap:Body>
</soap:Envelope>
I receive a sensible response!
Now I introduce this service to APIM, as follows:
- Add new API
- I have a SOAP endpoint
- WSDL URL: http://www.webservicex.net/globalweather.asmx?wsdl
- Start Creating
- Name: eilat
- Context: /eilat
- Version: 1.0.0
- WSDL: http://www.webservicex.net/globalweather.asmx?wsdl [tested ok]
- Production Endpoint: http://www.webservicex.net/globalweather.asmx [valid]
- Tier Availability: Unlimited
I subscribe to this API, and try the following CURL
curl -H "Authorization: Bearer <my-key>" -X POST -T soap.xml \
-H "Content-Type: text/xml" http://localhost:8280/eilat/1.0.0
I get the following reply:
<faultstring>unknown</faultstring>
Trying the same in SOAP UI, I get:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server</faultcode>
<faultstring>unknown</faultstring>
<detail/>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
With #status#: HTTP 1.1/500 Internal Server Error
Looking at the logs:
1) http_access_2016-01-17.log
127.0.0.1 - - [17/Jan/2016:16:53:34 +0200]
"POST /eilat/1.0.0 HTTP/1.1" - 482 "-"
"curl/7.19.7 (x86_64-redhat-linux-gnu)
libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
2) wso2-apigw-errors.log
2016-01-17 16:53:34,364 [-] [PassThroughMessageProcessor-374]
ERROR ServerWorker Error processing
POST reguest for :
/eilat/1.0.0. Error detail: null. java.lang.NullPointerException
3) wso2carbon.log
INFO {org.apache.synapse.rest.API} -
Initializing API: admin--eilat:v1.0.0 {org.apache.synapse.rest.API}
INFO {org.wso2.carbon.core.services.util.CarbonAuthenticationUtil} -
'admin#carbon.super [-1234]' logged in at [2016-01-17 16:52:51,282+0200]
{org.wso2.carbon.core.services.util.CarbonAuthenticationUtil}
ERROR {org.apache.synapse.transport.passthru.ServerWorker} -
Error processing POST reguest for : /eilat/1.0.0.
Error detail: null.
{org.apache.synapse.transport.passthru.ServerWorker}
java.lang.NullPointerException
Looking at the API again, I see that WSDL URL is changed from the URL I provided, to the following:
/registry/resource/_system/governance/apimgt/applicationdata/wsdls/admin--eilat1.0.0.wsdl
I guess this is normal behavior.
Question is - why the Null Pointer Exception?
Error was caused due to a custom authentication plugin handler.
Removing this handler from the chain of handlers solved the problem.
Related
First off, let me apologize, because I don't know much about SOAP and most of what I'm saying is probably nonsense.
I upgraded some client-side code that was generated using gSoap 2.8.4 to gSoap 2.8.93
As far as I can tell, the program only sends one request to the server. Previously this request was wrapped in
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="bmf.gv.at:pkt/PKTSoap" xmlns:ns1="bmf.gv.at:pkt" xmlns:ns3="bmf.gv.at:pkt/PKTSoap12">
<SOAP-ENV:Body>
...
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
However with the code generated by the new version this envelope is missing. I understand that this is because the request is generated as a REST request instead of a SOAP one. I've found threads that talk about the //gsoap directive for the service setting the method-protocol to SOAP instead of POST, but I can only find these directives for requests to the sub-services /PKTSoap and /PKTSoap12, not to the root service bmf.gv.at:pkt, to which the request is sent. In fact that is not even called a service in the code, it's called a schema. And the requests to it are called top-level root elements of the schema. They are all automatically generated as REST requests.
My question is how can I instruct gSoap to generate all requests as SOAP1.1 requests? Any help whatsoever is greatly appreciated.
WSDL: https://pastebin.com/bmC8Hx6M
typemap.dat is the default one with the following appended:
ns1 = "bmf.gv.at:pkt"
ns2 = "bmf.gv.at:pkt/PKTSoap"
ns3 = "bmf.gv.at:pkt/PKTSoap12"
And I use the following commands to generate:
wsdl2h.exe -c -g -N ns %1.wsdl
soapcpp2.exe -c -C -I./import -1 %1.h
It is not clear from your question which request messages do not include the envelope.
Here is a quick way to test the generated source code, to verify that the SOAP1.1 envelope and body are included (I've used C++ here):
wsdl2h -L -g -N ns service.wsdl
soapcpp2 -1 -C -I import service.h
A small demo client, to test the request message:
#include "soapH.h"
#include "PKTSoap.nsmap"
int main()
{
struct soap *soap = soap_new1(SOAP_XML_INDENT);
_ns1__DatenpoolkontoErzeugen req;
_ns1__Verarbeitung res;
req.soap_default(soap);
soap_call___ns2__PKTDatenpoolkontoErzeugen(soap, "http://", NULL, &req, res);
}
Compiled with:
c++ -o service service.cpp soapC.cpp soapClient.cpp stdsoap2.cpp
Then run:
$ ./service
POST / HTTP/1.1
Host:
User-Agent: gSOAP/2.8
Content-Type: text/xml; charset=utf-8
Content-Length: 526
Connection: close
SOAPAction: "bmf.gv.at:pkt/PKTDatenpoolkontoErzeugen"
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="bmf.gv.at:pkt/PKTSoap" xmlns:ns1="bmf.gv.at:pkt" xmlns:ns3="bmf.gv.at:pkt/PKTSoap12">
<SOAP-ENV:Body>
<ns1:DatenpoolkontoErzeugen>
<ns1:Absender xsi:nil="true"/>
</ns1:DatenpoolkontoErzeugen>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This shows that bmf.gv.at:pkt requests are sent exactly as specified in the WSDL.
I have a X509 certificate (e.g. C:\Cert\BBcert.pl2) and a password (e.g. "XYZ") with which I should use to authenticate and the DLWS here https://service.bloomberg.com/assets/dl/dlws.wsdl
I can use a SOAP GUI client to connect and do some queries but how do I go about using the certificate, password and link above in powershell so I can send some queries?
If anyone has used the Bloomberg Data License Web Services and can provide a complete example how to fetch some pricing data?
Start with:
curl --cert .\BloombergDLWS.p12:MyP#$$w0rd -H "Content-Type: text/xml;charset=utf-8" -H 'SOAPAction: \"submitGetDataRequest\"' -d "#submitGetDataRequest.xml" --request-target 'https://dlws.bloomberg.com/dlps' --url 'https://dlws.bloomberg.com/dlps'
Three notes about the CURL command:
The request-target flag is necessary. Otherwise it sends POST /dlps HTTP/1.1 instead of POST /dlps HTTP/1.1 and results in a 502 BAD GATEWAY error.
Escape the SOAPAction quotes, otherwise you get Failed to convert request to BAS: Failed to find action index for SOAP action 'submitGetDataRequest' when converting SOAP request for service ID 125322
Read the SOAP envelope XML from a file. Inline XML, besides vastly inflating the command length, generated a ParseError even though I had copied it in carefully as one line.
Where submitGetDataRequest.xml contains
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://services.bloomberg.com/datalicense/dlws/ps/20071001">
<soapenv:Header/>
<soapenv:Body>
<ns:submitGetDataRequest>
<ns:headers>
<ns:secmaster>true</ns:secmaster>
</ns:headers>
<ns:fields>
<ns:field>NAME</ns:field>
<ns:field>TICKER</ns:field>
<ns:field>CPN</ns:field>
<ns:field>MATURITY</ns:field>
<ns:field>ID_BB_GLOBAL</ns:field>
</ns:fields>
<ns:instruments>
<ns:instrument>
<ns:id>912810CY2</ns:id>
<ns:type>CUSIP</ns:type>
</ns:instrument>
</ns:instruments>
</ns:submitGetDataRequest>
</soapenv:Body>
</soapenv:Envelope>
This returns a response that doesn't contain the data you want, but it does include a responseId code to use in a second request.
<?xml version="1.0" encoding="UTF-8" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<dlws:submitGetDataResponse xmlns='http://services.bloomberg.com/datalicense/dlws/ps/20071001'
xmlns:dlws="http://services.bloomberg.com/datalicense/dlws/ps/20071001"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<dlws:statusCode>
<dlws:code>0</dlws:code>
<dlws:description>Success</dlws:description>
</dlws:statusCode>
<dlws:requestId>01234567-89AB-CDEF-0123-456789ABCDEF</dlws:requestId>
<dlws:responseId>ABCDEF0123-4567890AB</dlws:responseId>
</dlws:submitGetDataResponse>
</soap:Body>
</soap:Envelope>
You must insert the responseId code into another request like so (saved as retrieveGetDataResponse.xml):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://services.bloomberg.com/datalicense/dlws/ps/20071001">
<soapenv:Header/>
<soapenv:Body>
<ns:retrieveGetDataRequest>
<ns:responseId>ABCDEF0123-4567890AB</ns:responseId>
</ns:retrieveGetDataRequest>
</soapenv:Body>
</soapenv:Envelope>
Wait a few minutes, then submit the final request, saving your data as DataResponse.xml:
curl --cert .\BloombergDLWS.p12:MyP#$$w0rd -H "Content-Type: text/xml;charset=utf-8" -H 'SOAPAction: \"retrieveGetDataResponse\"' -d "#retrieveGetDataResponse.xml" --request-target 'https://dlws.bloomberg.com/dlps' --url 'https://dlws.bloomberg.com/dlps' -o DataResponse.xml
Submitting this request too soon will return a result that basically says it's not ready, try again later.
I have used IBM MobileFirst Studio V7.1 - Service Discovery wizard option and created a SOAP adapter from a application WSDL file. The Service Discovery procedure correctly creates the MobileFirst adapter in the MFP Studio.
The sample message payload is as follows.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:fet="http://siebel.com/asi/Fetch Account Info">
<soapenv:Body>
<fet:ExecuteFetchAccountInfo_Input>
<fet:Object_spcId>1-6U8KAR</fet:Object_spcId>
</fet:ExecuteFetchAccountInfo_Input>
</soapenv:Body>
</soapenv:Envelope>
Now, using the adapter testing option in the MobileFirst Studio, the following JSON payload are being passed in the dialog window
params:
{"ExecuteFetchAccountInfo_Input":{"Object_spcId":"1-6U8KAR"}}
But I get the following error when I call the adapter
{
"errors": [
"Runtime: Failed to read the HTTP response to: \/eai_enu\/start.swe?SWEExtSource=WebService&SWEExtCmd=Execute \njava.io.EOFException: Unexpected end of ZLIB input stream"
],
"info": [
],
"isSuccessful": false,
"warnings": [
]
}
Also when I tried to check the log files. I was able to capture the request and response.
Request:
[2/16/16 11:27:10:997 IST] 000001ce com.worklight.integration.model.ProcedureInvoker I FWLSE0318I: request:
/eai_enu/start.swe?SWEExtSource=WebService&SWEExtCmd=Execute
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<tns:ExecuteFetchAccountInfo_Input xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://siebel.com/asi/Fetch Account Info" xmlns:xsdLocal1="http://www.siebel.com/xml/Account%20IO" >
<tns:Object_spcId>1-6U8KAR</tns:Object_spcId>
</tns:ExecuteFetchAccountInfo_Input>
</soap:Body>
</soap:Envelope>
Response:
response:
OK
Date=Tue, 16 Feb 2016 05:34:35 GMT
Server=Microsoft-IIS/6.0
X-Powered-By=ASP.NET
_charset=UTF-8
cache-control=no-cache, must-revalidate, max-age=0
pragma=no-cache
transfer-encoding=Chunked
content-type=text/xml;charset=UTF-8
[project IBMBankProject]
[2/16/16 11:27:11:000 IST] 000001ce om.worklight.integration.services.impl.DataAccessServiceImpl E FWLSE0099E: An error occurred while invoking procedure [project IBMBankProject]SoapAdapter1/HttpRequestFWLSE0100E: parameters: [project IBMBankProject]
Failed to read the HTTP response to: /eai_enu/start.swe?SWEExtSource=WebService&SWEExtCmd=Execute
java.io.EOFException: Unexpected end of ZLIB input stream
FWLSE0101E: Caused by: [project IBMBankProject]java.lang.RuntimeException: java.io.EOFException: Unexpected end of ZLIB input streamjava.lang.RuntimeException: Failed to read the HTTP response to: /eai_enu/start.swe?SWEExtSource=WebService&SWEExtCmd=Execute
java.io.EOFException: Unexpected end of ZLIB input stream
By looking at the response it says the response if Ok but it is unable to read it. Please help if I need to set-up something extra to read the response.
It turns out that there was a defect here that needed to be fixed. The APAR number is PI67417 and it can be downloaded from Fix Central.
Once you've applied the iFix, you'll also need to add "Accept-Encoding: identity" to your adapter call. That should resolve your issue. If it doesn't please let me know.
Since this is working in SOAP UI but fails in the adapter, it may indicate a product defect. Please open an IBM PMR and provide your files for reproduction by the development team.
I want to make a soap request with SoapClient in groovy.
My Code:
SoapClient client = SoapClient.builder()
.endpointUri("http://www.webservicex.com/globalweather.asmx")
.build();
String output = client.post(requestxml)
Request XML:
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<web:GetWeather xmlns:web="http://www.webserviceX.NET">
<web:CityName>Berlin</web:CityName>
<web:CountryName>Germany</web:CountryName>
</web:GetWeather>
</soapenv:Body>
</soapenv:Envelope>
I always get an exception:
ERROR errors.GrailsExceptionResolver - TransmissionException occurred when processing request:
HTTP response=[Internal Server Error] code=[500]. Stacktrace follows:
Message: HTTP response=[Internal Server Error] code=[500]
Line | Method
->> 171 | executePost in org.reficio.ws.client.core.SoapClient
What am I doing wrong?
Consider using WSLite: http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22groovy-wslite%22 This is almost standard SOAP client for Groovy, IMHO.
I followed the Create your first webservice tutorial. When I go to the Hello Service Soap11 metadata page, I see the following:
POST /xml/reply/Hello HTTP/1.1
Host: localhost
Content-Type: application/xml
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ...
</soap:Envelope>
The line POST /xml/reply/Hello HTTP/1.1 seems incorrect. When I use the Postman Rest Client and post to /xml/reply/hello to test the SOAP endpoint. It doesn't work. The response is a 400 Bad Request with a message "Could not deserialize 'application/xml' request..."
Then I change the URL to make the request post to /soap11 instead, it works with status code 200 OK.
This problem happens for the Soap12 metadata page too.
Seems like something is not right with the metadata page generation?
By looking at the code, this does look like a bug.
I have fixed the problem and submitted a pull request to ServiceStack, pending for acceptance.
Pull request: https://github.com/ServiceStack/ServiceStack/pull/389
Update: Pull request has been merged into ServiceStack master branch. Problem solved!