SOAP API calling with retrofit getting null body i

2019-01-27 09:55发布

问题:

I am trying to post an soap xml with Retrofit2 but but getting response 200 ok and body is always null I'm using a Simple XML Framework to model a SOAP request that looks like below code:

API calls

HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();

interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

Strategy strategy = new AnnotationStrategy();

Serializer serializer = new Persister(strategy);

OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(interceptor)
        .connectTimeout(2, TimeUnit.MINUTES)
        .writeTimeout(2, TimeUnit.MINUTES)
        .readTimeout(2, TimeUnit.MINUTES)
        .build();

return new Retrofit.Builder()
        .addConverterFactory(SimpleXmlConverterFactory.create(serializer))

        .baseUrl("http:*********/ ")
        .client(okHttpClient)
        .build();

        "Content-Type: text/xml",
    "Accept-Charset: UTF-8",
    "SOAPAction: http://www.***.**/getDetails ",
    "Host: XXXXXXXXXXX"
})
@POST("/xx/getDetails.svc")
Call<AccountInfoResponseEnvelope> getAccountInfo(@Body AccountInfoRequestEnvelope body);

Response Classes are below

@Root(name = "s:Envelope",  strict = false)
@Namespace( prefix = "s", reference = "http://schemas.xmlsoap.org/soap/envelope/")
public class AccountInfoResponseEnvelope {

    @Element(name = "s:Body", required = false)
    private AccountInfoResponseBody body;

    public AccountInfoResponseBody getBody() {
        return body;
    }

    public void setBody(AccountInfoResponseBody body) {
        this.body = body;
    }

    @Override
    public String toString() {
        return "AccountInfoResponseEnvelope{" +
                "body=" + body +
                '}';
    }
}

    @Root(name = "s:Body", strict = false)
@NamespaceList({
        @Namespace( prefix = "xsi", reference = "http://www.w3.org/2001/XMLSchema-instance"),
        @Namespace( prefix = "xsd", reference = "http://www.w3.org/2001/XMLSchema")
})
public class AccountInfoResponseBody {

    @Element(name = "GetAccountInfoResponse",required = false)
    private AccountInfoResponseData data;

    public AccountInfoResponseData getData() {
        return data;
    }

    public void setData(AccountInfoResponseData data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "AccountInfoResponseBody{" +
                "data=" + data +
                '}';
    }
}

    @Root(name = "GetAccountInfoResponse", strict = false)
@Namespace(reference = "xxxxxxxxx")
public class AccountInfoResponseData {

    @Element(name = "Status")
    private String status;

    @Element(name = "Message")
    private String message;

    @Element(name = "ErrorMessage")
    private String errorMessage;

    @ElementList(name = "CheckOutItems", inline = true)
    private List<CheckOutItem> checkOutItems;


    public String getStatus() {
        return status;
    }

    public String getMessage() {
        return message;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public List<CheckOutItem> getCheckOutItems() {
        return checkOutItems;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }
    public void setCheckOutItems(List<CheckOutItem> checkOutItems) {
    this.checkOutItems = checkOutItems;
}

}

Main Activity retrofit call

 ApiRepository.getInstance().getAccountInfo(envelope).enqueue(new Callback<AccountInfoResponseEnvelope>() {
  @Override
  public void onResponse(Call<AccountInfoResponseEnvelope> call, Response<AccountInfoResponseEnvelope> response) {
    if (response != null){
      Log.i(TAG, "response: "+response.toString());
      AccountInfoResponseEnvelope info = response.body();

      if (info != null) {
        Log.i(TAG, "body: "+ info.toString());

        String status = info.getBody().getData().getStatus();
        if (status.equals("OK")) {

        }
      }
    }
  }

  @Override
  public void onFailure(Call<AccountInfoResponseEnvelope> call, Throwable t) {
    t.printStackTrace();
  }
});

Here If I try to call this AccountInfoResponseEnvelope getting success 200 message but the body is like below :

I/MainActivity: response: Response{protocol=http/1.1, code=200, message=OK, url=http:xxxxxxx}
body: AccountInfoResponseEnvelope{body=null}

This is my Response XML :

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <AccountInfoResponse xmlns=“XXXXXXXX”>
      <Status>OK</Status>
      <Message>Operation completed successfully</Message>
      <ErrorMessage />
      <CheckOutItems>
        <CheckOutItem>
          <CheckOutStatus>OK</CheckOutStatus>
          <CheckOutErrorMessage />
          <CheckOutUserMessage>Operation completed successfully</CheckOutUserMessage>
          <TitleID>qwerty</TitleID>
          <DueDate>XXXXX</DueDate>
          <FormatLockedIn>N</FormatLockedIn>
          <DownloadableFormats>
            <Name>book</Name>
            <Name>text</Name>
          </DownloadableFormats>
          <TitleName>Test</TitleName>
        </CheckOutItem>
        <CheckOutItem>
          <CheckOutStatus>OK</CheckOutStatus>
          <CheckOutErrorMessage />
          <CheckOutUserMessage>Operation completed successfully</CheckOutUserMessage>
          <TitleID>test</TitleID>
          <DueDate>xxxx</DueDate>
          <FormatLockedIn>N</FormatLockedIn>
          <DownloadableFormats>
            <Name>book</Name>
            <Name>atest</Name>
          </DownloadableFormats>
          <TitleName>test</TitleName>
        </CheckOutItem>
      </CheckOutItems>
    </AccountInfoResponse>
  </s:Body>
</s:Envelope>

What should I do to get the body response here ?

回答1:

You can log the request adding one HttpLoggingInterceptor into the OkHttpClient in order to see what you send to the server:

OkHttpClient.Builder builder = new OkHttpClient.Builder();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addInterceptor(loggingInterceptor);

Afterwards, review the request and try it with postman/SoapUI