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& 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;
}
SOAP, when using HTTP as the transfer mechanism, is sent via HTTP POST requests.
A SOAP message is encoded as an XML document, consisting of an <Envelope> element, which contains an optional <Header> element, and a mandatory <Body> element.
Retrofit is a type-safe REST client for Android, Java and Kotlin developed by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With