Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
323 views
in Technique[技术] by (71.8m points)

android - Post soap xml request with Retrofit

I am trying to post an soap xml with Retrofit but it's failing, I'm using a Simple XML Framework to model a SOAP request that looks like this:

Request XML

@Root(name = "soap12:Envelope")
@NamespaceList({
        @Namespace(reference = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi"),
        @Namespace(reference = "http://www.w3.org/2001/XMLSchema", prefix = "xsd"),
        @Namespace(prefix = "soap12", reference = "http://www.w3.org/2003/05/soap-envelope")
})
@Element(name = "soap12:Body")
public class GeoIP {

    @Namespace(reference = "http://www.webservicex.net/")
    @Element(name="GetGeoIP")
    private GetGeoIP GetGeoIP;

    public GetGeoIP getGetGeoIP() {
        return GetGeoIP;
    }

    public void setGetGeoIP(GetGeoIP getGeoIP) {
        this.GetGeoIP = getGeoIP;
    }

    @Namespace(reference = "http://www.webservicex.net/")
    public static class GetGeoIP{
        @Element(name = "IPAddress")
        private String IPAddress;

        public String getIP() {
            return IPAddress;
        }

        public void setIP(String IP) {
            this.IPAddress = IP;
        }
    }
}

Expected output:

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <GetGeoIPResponse xmlns="http://www.webservicex.net/">
      <GetGeoIPResult>
        <ReturnCode>int</ReturnCode>
        <IP>string</IP>
        <ReturnCodeDetails>string</ReturnCodeDetails>
        <CountryName>string</CountryName>
        <CountryCode>string</CountryCode>
      </GetGeoIPResult>
    </GetGeoIPResponse>
  </soap12:Body>
</soap12:Envelope>

Failure Output

<--- HTTP 500 http://www.webservicex.net/geoipservice.asmx (2240ms)
06-15 08:22:09.567 26327-26359/com. D/Retrofit: : HTTP/1.1 500 Internal Server Error
06-15 08:22:09.567 26327-26359/com.a D/Retrofit: Cache-Control: private
06-15 08:22:09.567 26327-26359/com.a.mfmpay D/Retrofit: Content-Length: 1188
06-15 08:22:09.567 26327-26359/com.a D/Retrofit: Content-Type: text/xml; charset=utf-8
06-15 08:22:09.567 26327-26359/com.a D/Retrofit: Date: Wed, 15 Jun 2016 03:22:00 GMT
06-15 08:22:09.567 26327-26359/com.a D/Retrofit: OkHttp-Received-Millis: 1465960929564
06-15 08:22:09.567 26327-26359/com.a D/Retrofit: OkHttp-Response-Source: NETWORK 500
06-15 08:22:09.567 26327-26359/com.a D/Retrofit: OkHttp-Selected-Protocol: http/1.1
06-15 08:22:09.567 26327-26359/com.a D/Retrofit: OkHttp-Sent-Millis: 1465960928849
06-15 08:22:09.567 26327-26359/com.a D/Retrofit: Server: Microsoft-IIS/7.0
06-15 08:22:09.567 26327-26359/com.a D/Retrofit: X-AspNet-Version: 4.0.30319
06-15 08:22:09.567 26327-26359/com.a D/Retrofit: X-Powered-By: ASP.NET
                                                                  at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean&amp; abortProcessing)</faultstring><detail /></soap:Fault></soap:Body></soap:Envelope>
06-15 08:22:09.570 26327-26359/com.a D/Retrofit: <--- END HTTP (1188-byte body)
06-15 08:22:09.571 26327-26327/com.a V/TAG: 500 Internal Server Error

EndPoint Interface

public interface MagentoApi {
@Headers({"Content-Type: application/soap+xml; charset=utf-8"})
    @POST("/geoipservice.asmx")
    public void requestGeo(@Body GeoIP.GetGeoIP body,Callback<GeoIPResponse> cb);
}

Main Class Code

    GeoIP.GetGeoIP request = new GeoIP.GetGeoIP();
        request.setIP("192.168.1.1");

        RestAdapter restAdapter = getRestAdapter();
        MagentoApi api = restAdapter.create(MagentoApi.class);

        api.requestGeo(request, cb);

retrofit.Callback<GeoIPResponse> cb = new retrofit.Callback<GeoIPResponse>() {
    @Override
    public void success(GeoIPResponse geoIPResponse, retrofit.client.Response response) {
        Log.v("TAG", String.valueOf(response.getStatus()));
    }

    @Override
    public void failure(RetrofitError error) {
Log.v("TAG",error.getLocalizedMessage());
    }
};
    public static RestAdapter getRestAdapter() {
        Strategy strategy = new AnnotationStrategy();
        Serializer serializer = new Persister(strategy);

        OkHttpClient okHttpClient = new OkHttpClient();
        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("http://www.webservicex.net")
                .setClient(new OkClient(okHttpClient))
                .setConverter(new SimpleXMLConverter(serializer))
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .build();

        return restAdapter;
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I have made one sample for this kind of webservices. (using webservicex as example, too). You can see it at my blog or in my github

UPDATE

Needed libraries:

...
    compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
    compile 'com.squareup.okhttp3:okhttp:3.3.1'
    compile 'com.squareup.okhttp3:okhttp-urlconnection:3.3.1'

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile ('com.squareup.retrofit2:converter-simplexml:2.1.0'){
        exclude group: 'stax', module: 'stax-api'
        exclude group: 'stax', module: 'stax'
        exclude group: 'xpp3', module: 'xpp3'
    }
...

The sample is for this webservice: http://www.webservicex.net/New/Home/ServiceDetail/42

First of all, you have to create Retrofit instance:

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();

Retrofit retrofit =  new Retrofit.Builder()
        .addConverterFactory(SimpleXmlConverterFactory.create(serializer))
        .baseUrl("http://www.webservicex.net/")
        .client(okHttpClient)
        .build();

After that, you have to create the API object:

    public interface UsStatesApi {

    @Headers({
            "Content-Type: text/xml",
            "Accept-Charset: utf-8"
    })
    @POST("/uszip.asmx")
    Call<UsStatesResponseEnvelope> requestStateInfo(@Body UsStatesRequestEnvelope body);

}

For creating your entities, you have to annotate them correctly. These are the request classes (response classes are made in the same way):

class: UsStatesRequestEnvelope

@Root(name = "soap12:Envelope")
@NamespaceList({
        @Namespace( prefix = "xsi", reference = "http://www.w3.org/2001/XMLSchema-instance"),
        @Namespace( prefix = "xsd", reference = "http://www.w3.org/2001/XMLSchema"),
        @Namespace( prefix = "soap12", reference = "http://www.w3.org/2003/05/soap-envelope")
})
public class UsStatesRequestEnvelope {

    @Element(name = "soap12:Body", required = false)
    private UsStatesRequestBody body;

    public UsStatesRequestBody getBody() {
        return body;
    }

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

class : UsStatesRequestBody

@Root(name = "soap12:Body", strict = false)
public class UsStatesRequestBody {

    @Element(name = "GetInfoByState",required = false)
    private UsStatesRequestData usStatesRequestData;

    public UsStatesRequestData getUsStatesRequestData() {
        return usStatesRequestData;
    }

    public void setUsStatesRequestData(UsStatesRequestData usStatesRequestData) {
        this.usStatesRequestData = usStatesRequestData;
    }
}

class: UsStatesRequestData

@Root(name = "GetInfoByState", strict = false)
@Namespace(reference = "http://www.webserviceX.NET")
public class UsStatesRequestData {

    @Element(name = "USCity", required = false)
    private String city;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...