wso2 / product-apim

Welcome to the WSO2 API Manager source code! For info on working with the WSO2 API Manager repository and contributing code, click the link below.
http://wso2.github.io/
Apache License 2.0
851 stars 787 forks source link

How to capture response from wso2 Rest API that has successfully passed/received on request/response to Backend Soap API #5580

Closed prats2017 closed 1 week ago

prats2017 commented 5 years ago

Newbie with wso2. I am doing a POC to write Wso2 API for SOAP service and generating Rest endpoints. Wso2 Swagger API is working fine and getting response from backend API. Then, I downloaded Java SDK to write client. When I run my client I see that my request has reached Backend server and response has been generated. I also see response in my wso2 logs in Json format.

My problem is, I am not sure how to capture response in client I wrote because wso2 generated API is returning ApiResponse. I have gone through pizza-shack example at and that doesn't seem to be very helpful. Is there any example that I can follow on learn. Or should i be changing code generated by wso2?

Wso2Client I wrote --

public void callWso2API() throws ApiException{ AllCountryApi allCountryApi = new AllCountryApi(); String accessToken = "6f529fca-b574-32c2-8833-a7dbcffcaa1d"; ApiClient apiClient = allCountryApi.getApiClient(); apiClient.addDefaultHeader("Accept", "application/json"); apiClient.addDefaultHeader("Authorization", "Bearer " + accessToken); apiClient.setLenientOnJson(true); apiClient.setBasePath("http://XXX.1:8280/countries1/v1.0.0"); allCountryApi.allCountryGet(); System.out.println("End"); } API Class WSo2 generated --

public class AllCountryApi { public void allCountryGet() throws ApiException { allCountryGetWithHttpInfo(); }
public ApiResponse allCountryGetWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = allCountryGetValidateBeforeCall(null, null); return apiClient.execute(call); }
}

WSo2 Logs have response from backend API. Not sure where i am loosing it-- DEBUG - wire HTTP-Sender I/O dispatcher-1 << "<?xml version='1.0' encoding='UTF-8'?></soapenv:Body></soapenv:Envelope>[\r][\n]" DEBUG - wire HTTP-Sender I/O dispatcher-1 << "0[\r][\n]" wire HTTP-Sender I/O dispatcher-1 << "[\r][\n]" wire HTTP-Sender I/O dispatcher-1 >> "HTTP/1.1 200 [\r][\n]" wire HTTP-Sender I/O dispatcher-1 >> "Accept: application/soap+xml, text/html, image/gif, image/jpeg, ; q=.2, /; q=.2[\r][\n]" wire HTTP-Sender I/O dispatcher-1 >> "Content-Type: application/soap+xml;charset=utf-8[\r][\n]" wire HTTP-Sender I/O dispatcher-1 >> "Content-Length: 744[\r][\n]" wire HTTP-Sender I/O dispatcher-1 >> "Date: Fri, 13 Sep 2019 18:13:49 GMT[\r][\n]" wire HTTP-Sender I/O dispatcher-1 >> "[\r][\n]" wire HTTP-Sender I/O dispatcher-1 >> "Poland</ns2:name>38186860</ns2:population>Warsaw</ns2:capital>PLN</ns2:currency></ns2:countryDetails>United Kingdom</ns2:name>63705000</ns2:population>London</ns2:capital>GBP</ns2:currency></ns2:countryDetails>India</ns2:name>46704314</ns2:population>Delhi</ns2:capital>INR</ns2:currency></ns2:countryDetails></ns2:getAllCountryResponse></env:Body></env:Envelope>" wire HTTP-Listener I/O dispatcher-1 << "HTTP/1.1 200 [\r][\n]" wire HTTP-Listener I/O dispatcher-1 << "Accept: application/soap+xml, text/html, image/gif, image/jpeg, ; q=.2, /; q=.2[\r][\n]" wire HTTP-Listener I/O dispatcher-1 << "Access-Control-Allow-Origin: *[\r][\n]" wire HTTP-Listener I/O dispatcher-1 << "Access-Control-Allow-Methods: GET[\r][\n]" wire HTTP-Listener I/O dispatcher-1 << "Access-Control-Allow-Headers: authorization,Access-Control-Allow-Origin,Content-Type,SOAPAction[\r][\n]" wire HTTP-Listener I/O dispatcher-1 << "Content-Type: application/json; charset=utf-8[\r][\n]" wire HTTP-Listener I/O dispatcher-1 << "Date: Fri, 13 Sep 2019 18:13:49 GMT[\r][\n]" wire HTTP-Listener I/O dispatcher-1 << "Transfer-Encoding: chunked[\r][\n]" DEBUG - wire HTTP-Listener I/O dispatcher-1 << "Connection: Keep-Alive[\r][\n]" DEBUG - wire HTTP-Listener I/O dispatcher-1 << "[\r][\n]" DEBUG - wire HTTP-Listener I/O dispatcher-1 << "118[\r][\n]" DEBUG - wire HTTP-Listener I/O dispatcher-1 << "{"getAllCountryResponse":{"countryDetails":[{"name":"Poland","population":38186860,"capital":"Warsaw","currency":"PLN"},{"name":"United Kingdom","population":63705000,"capital":"London","currency":"GBP"},{"name":"India","population":46704314,"capital":"Delhi","currency":"INR"}]}}[\r][\n]"**** wso2

praminda commented 5 years ago

I tried a sample SOAP to REST API for calculator endpoint. Generated Code gave me a Client similar to this.

public class DefaultApi {
    private ApiClient apiClient;

    public DefaultApi() {
        this(Configuration.getDefaultApiClient());
    }

    public DefaultApi(ApiClient apiClient) {
        this.apiClient = apiClient;
    }

    public AddOutput add(AddInput payload) throws ApiException {
        ApiResponse<AddOutput> resp = addWithHttpInfo(payload);
        return resp.getData();
    }

    public ApiResponse<AddOutput> addWithHttpInfo(AddInput payload) throws ApiException {
        com.squareup.okhttp.Call call = addValidateBeforeCall(payload, null, null);
        Type localVarReturnType = new TypeToken<AddOutput>(){}.getType();
        return apiClient.execute(call, localVarReturnType);
    }
}

With this I can call add operation as below and get the response.

public static void main(String[] args) {
    DefaultApi api = new DefaultApi();
    Add addData = new Add().intA(1).intB(1);
    AddInput addInput = new AddInput();
    addInput.add(addData);

    try {
        AddOutput resp = api.add(addInput);
        int result = resp.getAddResponse().getAddResult();
        System.out.println("Result is: " + result);
    } catch (ApiException e) {
        e.printStackTrace();
    }
}

Looks like generated code you have is bit different from what I got. Can you let us know the APIM version you are using? Also only if possible attach the generated SDK?

prats2017 commented 5 years ago

Thanks for your response. I am using APIM 2.6.0. Attached is the SDK zip.

countries_v1.0.0_java.zip

praminda commented 5 years ago

hmm. Can't see any data models generated in this client. Can you attach the wsdl you are using?

chamilaadhi commented 5 years ago

Hi, I assume you are using the fresh APIM 2.6.0 pack. I tried the Rest API generation using a WSDL endpoint and generated a SDK and try to get the payload and couldn't get it. (Same issue you are facing).

Seems like the swagger file generated for this API is not properly constructed (missing definition for response objects for each apis, etc).

We have done some improvements for this feature. Is there any possibility to take a wum update for APIM 2.6.0 and try this out please? All the fixes and improvements are sent as updates. You could refer https://docs.wso2.com/display/updates/Using+WSO2+Update+Manager on how to do this

You could try the same scenario on this pack and let us know the results. I was able to get the payload from my soap service when I used the latest wum update AM 2.6.0

When the sdk is generated correctly, You would be able to use DefaultApi api = new DefaultApi(); and using the api object access the rest api resources

Regards Chamila.

prats2017 commented 5 years ago

uploading corresponding wsdl file. Please have a look @praminda

countriesWSDL.txt

prats2017 commented 5 years ago

wso2 countries-wsdl.txt @chamilaadhi I downloaded latest WUM update as u mentioned and see some strange stuff happening. Not sure if I am making some mistakes. My backend soap service supports soap1.2. I setup my APIM API to support 1.2 by selecting format in "Advanced Endpoint Configuration". I however still see my "Conversion Policies :" setting message property as text/xml

when I still go ahead to run my API in store, I am getting this in my backend soap log Unable to create envelope from given source

This was working fine in last APIM version I was using


Servlet.service() for servlet [messageDispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.ws.soap.SoapMessageCreationException: Could not create message from InputStream: Unable to create envelope from given source: ; nested exception is com.sun.xml.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source: ] with root cause

com.sun.xml.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source because the root element is not named "Envelope" at com.sun.xml.messaging.saaj.soap.SOAPPartImpl.lookForEnvelope(SOAPPartImpl.java:199) ~[saaj-impl-1.5.0.jar:na] at com.sun.xml.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:165) ~[saaj-impl-1.5.0.jar:na] at com.sun.xml.messaging.saaj.soap.EnvelopeFactory.parseEnvelopeSax(EnvelopeFactory.java:205) ~[saaj-impl-1.5.0.jar:na] at com.sun.xml.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:122) ~[saaj-impl-1.5.0.jar:na]

chamilaadhi commented 5 years ago

@prats2017 can you enable the wirelogs again and do the request, please? please attach the wso2carbon.log file (would be much easier to analyze the error log this way) . This way we could get some idea on where the issue is.

chamilaadhi commented 5 years ago

Hi @prats2017 While going through the wsdl file you provided, I notice that soapAction is not defined.

<wsdl:operation name="getAllCountry">
    <soap:operation soapAction=""/>
    <wsdl:input name="getAllCountryRequest">
    <soap:body use="literal"/>
</wsdl:input>

When you generate the mapping using the wsdl file, this empty action is mapped as "" and it will be sent to the backend. (If you enable the wirelogs you should see empty SOAPAction header going back to the backend. Since you mentioned your backend only supports soap 1.2, this might be the reason for the failure.

You could try following

Go to the Implement page in the publisher and select the relevent resource and select the In Flow

there remove the following and save and publish the api again (need republishing to affect the changes to the gateway)

Now try to invoke the api again

chamilaadhi commented 5 years ago

adding more to the previous comment. if the payload is not constructed correctly (by looking at the In Flow and Out Flow in the above image), you could modify it as well (if you have the correct payload to invoke the backend soap service)

prats2017 commented 5 years ago

thanks for responding. I wasn't sure I was making any mistakes. So, I picked up an example project from web to make sure i have not made any mistake and run that but I am getting same error you can take project from https://spring.io/guides/gs/producing-web-service/ .
its giving me com.sun.xml.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source because the root element is not named "Envelope".

chamilaadhi commented 5 years ago

Will check this service. Btw, if you need a sample SOAP service, you could use http://localhost:8280/services/Version?wsdl (a simple soap service which returns the APIM version) or add this SimpleStockQuote .aar file in https://drive.google.com/open?id=1xGxGrJRuGsdjZM95WRe_JxkUrPBjWCWx to /wso2am-2.6.0/repository/deployment/server/axis2services folder and access the service using http://localhost:8280/services/SimpleStockQuoteService?wsdl

prats2017 commented 5 years ago

@chamilaadhi Thanks so much, please take a look. I have tried hard to find my mistake and am very curious to know what am I doing wrong.

chamilaadhi commented 5 years ago

Hi

Found the issue here. The web service you use only support SOAP 1.1 and we have a limitation when generating the SOAP to REST Mapping section for this older version. APIM supports SOAP 1.2 services for this feature and has some limitations when it comes to SOAP 1.1. Most of the SOAP web services support both SOAP 1.1 and 1.2 and in APIM, SOAP to REST Mapping generated to call a SOAP 1.2 request in APIM. Sorry you had to find this information in the hard way.

But for the POC, I hope you could use a SOAP 1.2 supported service. If you intend to still use this service, you may have to manually create the SOAP to REST Mapping section in the Implementation section in the publisher

Chamila.

prats2017 commented 5 years ago

Hi, thanks so much for responding. My Soap sesrvice is/was actually soap12 to start with but I was getting following error in my backend API - com.sun.xml.messaging.saaj.soap.SOAPVersionMismatchException: Cannot create message: incorrect content-type for SOAP version. Got: text/xml Expected: application/soap+xml

So I went and checked payload in wso2-> publisher-> conversion Policies and got this

so, I went to and changed Implement->Endpoint->Advanced options -> Message content AND changed Format from SOAP1.1 to SOAP1.2

My Payload was still showing (Not sure if I should do something for value to change to soap12 compliant)

anyhow, I still went ahead and ran my API but got 400 in APIM and below in backend servive ERROR: 'Content is not allowed in prolog.' 2019-09-19 08:14:37.705 ERROR 29840 --- [io-9090-exec-10] com.sun.xml.messaging.saaj.soap : SAAJ0511: Unable to create envelope from given source 2019-09-19 08:14:37.706 DEBUG 29840 --- [io-9090-exec-10] o.s.w.t.http.MessageDispatcherServlet : Completed 400 BAD_REQUEST

and I keep seeing below error in APIM log every now and then. Don't think it is the cause here javax.net.ssl.SSLException: Received fatal alert: certificate_unknown

I can upload my Spring boot code if that will help u to see what I am talking about.

chamilaadhi commented 5 years ago

I suspect the wsdl does not have SOAP1.2 related bindings because APIM set the content type to text/xml if it only has SOAP1.1 bindings. Can you doublecheck the original WSDL for this SOAP 1.2 service, please? (the attached countriesWSDL.txt has <wsdl:binding name="CountriesPortSoap11 sections which shows it supports SOAP1.1 stuff).

I can upload my Spring boot code if that will help u to see what I am talking about.

Yes please. We could set up the service on our side as well and check this.