I have difficulties using kSOAP2 library for android. I am able to send requests and get the response, but I would like to map the contents of the response to a plain java object. Basically kSOAP2 allows you to do that by specifying the parameters of the mapping into the addMapping() method. Anyway I am having a class cast exception when trying to cast the response to my Java object. Here is my implementation :
final SoapSerializationEnvelope envelope = LoginInfo.buildLoginObject(login,password);
envelope.addMapping(NAMESPACE, "GetCustomerByIdPwdResponse", new GetCustomerByIdPwdResponse().getClass());
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
HttpTransportSE httpTransport = new HttpTransportSE("URL");
httpTransport.debug = true;
try {
httpTransport.call(URL, envelope);
Log.d("SOAP OBJECT SENT",httpTransport.requestDump);
Log.d("SOAP OBJECT RESPONSE",httpTransport.responseDump);
GetCustomerByIdPwdResponse customerByIdPwd = (GetCustomerByIdPwdResponse)envelope.bodyIn;
} catch (IOException | XmlPullParserException e) {
e.printStackTrace();
}
return null;
}
}.execute();
And here is the request and response I get, they are all good :
Request :
<?xml version="1.0" encoding="UTF-8"?>
<v:Envelope xmlns:v="http://www.w3.org/2003/05/soap-envelope" xmlns:c="http://www.w3.org/2003/05/soap-encoding" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<v:Header>
<n0:To xmlns:n0="http://www.w3.org/2005/08/addressing">To</n0:To>
<n1:Action xmlns:n1="http://www.w3.org/2005/08/addressing">rexwebservices/IWebShopServices/GetCustomerByIdPwd</n1:Action>
</v:Header>
<v:Body>
<GetCustomerByIdPwd xmlns="rexwebservices" xmlns:ns2="http://schemas.datacontract.org/2004/07/RexWebServices" xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/" id="o0" c:root="1">
<loginMail i:type="d:string">...</loginMail>
<pwdSHA1 i:type="d:string">...</pwdSHA1>
</GetCustomerByIdPwd>
</v:Body>
Response :
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">rexwebservices/IWebShopServices/GetCustomerByIdPwdResponse</a:Action>
</s:Header>
<s:Body>
<GetCustomerByIdPwdResponse xmlns="rexwebservices">
<GetCustomerByIdPwdResult xmlns:b="http://schemas.datacontract.org/2004/07/RexWebServices" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<b:Customer>
<b:FirstName>...</b:FirstName>
<b:Id>...</b:Id>
<b:IsActived>true</b:IsActived>
<b:IsLockedOut>false</b:IsLockedOut>
<b:IsNewsLetterAccepted>false</b:IsNewsLetterAccepted>
<b:LandLinePhone />
<b:LastName>...</b:LastName>
<b:LoginMail>...</b:LoginMail>
<b:MobilePhone />
<b:Title>Mr</b:Title>
</b:Customer>
<b:ErrorMessage>+00X00000</b:ErrorMessage>
<b:SessionId>SID</b:SessionId>
</GetCustomerByIdPwdResult>
</GetCustomerByIdPwdResponse>
</s:Body>
</s:Envelope>
And here is the error I get when trying to create my POJO :
11-18 11:36:57.967: E/AndroidRuntime(19208): Caused by: java.lang.ClassCastException: org.ksoap2.serialization.SoapObject cannot be cast to com.example.ksoaptest.GetCustomerByIdPwdResponse
11-18 11:36:57.967: E/AndroidRuntime(19208): at com.example.ksoaptest.MainActivity$2.doInBackground(MainActivity.java:70)
11-18 11:36:57.967: E/AndroidRuntime(19208): at com.example.ksoaptest.MainActivity$2.doInBackground(MainActivity.java:1)
11-18 11:36:57.967: E/AndroidRuntime(19208): at android.os.AsyncTask$2.call(AsyncTask.java:288)
11-18 11:36:57.967: E/AndroidRuntime(19208): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
11-18 11:36:57.967: E/AndroidRuntime(19208): ... 4 more
Any help would be great since it's the last step to get me going towards my web service implementation.
Thanks !
UPDATE :
Here is my class for my customer. I now have an error when trying to map the customer to my RexUser class.
I added the envelope.addMapping("rexwebservices","RexUser",RexUser.class);
mapping to my envelope.
I have an Caused by: java.lang.RuntimeException: Unknown Property: FirstName
error when it comes to saving the customer data into the user object.
public class RexUser implements KvmSerializable{
public static final int FIRSTNAME = 0;
public static final int ID = 1;
public static final int LASTNAME = 6;
public static final int LOGINMAIL = 7;
public static final int MOBILEPHONE = 8;
public static final int LANDLINEPHONE = 5;
public static final int TITLE = 9;
public static final int IS_ACTIVATED = 2;
public static final int IS_LOCKED_OUT = 3;
public static final int IS_NEWSLETTER_ACCEPTED = 4;
String FirstName;
long Id;
boolean IsActived;
boolean IsLockedOut;
boolean IsNewsLetterAccepted;
String LandLinePhone;
String LastName;
String LoginMail;
String MobilePhone;
String Title;
public RexUser(String firstName, long id, boolean isActivated,
boolean isLockedOut, boolean isNewsLetterAccepted,
String landLinePhone, String lastName, String loginMail,
String mobilePhone, String title) {
super();
this.FirstName = firstName;
this.Id = id;
this.IsActived = isActivated;
this.IsLockedOut = isLockedOut;
this.IsNewsLetterAccepted = isNewsLetterAccepted;
this.LandLinePhone = landLinePhone;
this.LastName = lastName;
this.LoginMail = loginMail;
this.MobilePhone = mobilePhone;
this.Title = title;
}
public RexUser() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
HashMap<String,Object> desc = new HashMap<String,Object>();
desc.put("First name",FirstName);
desc.put("ID",Id);
desc.put("is Actived", IsActived);
desc.put("is Locked Out",IsLockedOut);
desc.put("isNewsLetterAccepted", IsNewsLetterAccepted);
desc.put("Land Line Phone", LandLinePhone);
desc.put("lastname", LastName);
desc.put("login Mail", LoginMail);
desc.put("mobile phone",MobilePhone);
desc.put("title", Title);
return desc.toString();
}
@Override
public Object getProperty(int arg0) {
switch(arg0){
case 0:
return FirstName;
case 1:
return Id;
case 2:
return IsActived;
case 3:
return IsLockedOut;
case 4:
return IsNewsLetterAccepted;
case 5:
return LandLinePhone;
case 6:
return LastName;
case 7:
return LoginMail;
case 8:
return MobilePhone;
case 9:
return Title;
default:
return null;
}
}
@Override
public int getPropertyCount() {
return 10;
}
@Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) {
switch(arg0){
case 0:
arg2.name = "First Name";
arg2.type = String.class;
break;
case 1:
arg2.name = "ID";
arg2.type = int.class;
break;
case 2:
arg2.name = "Is Actived";
arg2.type = boolean.class;
break;
case 3:
arg2.name = "Is Locked Out";
arg2.type = boolean.class;
break;
case 4:
arg2.name = "Is Newsletter Accepted";
arg2.type = boolean.class;
break;
case 5:
arg2.name = "Landline Phone";
arg2.type = String.class; break;
case 6:
arg2.name = "Last Name";
arg2.type = String.class;
break;
case 7:
arg2.name = "Login mail";
arg2.type = String.class;
break;
case 8:
arg2.name = "Mobile Phone";
arg2.type = String.class;
break;
case 9:
arg2.name = "Title";
arg2.type = String.class;
break;
default:
break;
}
}
@Override
public void setProperty(int arg0, Object arg1) {
switch(arg0){
case 0:
FirstName = (String)arg1;
break;
case 1:
Id = (int)arg1;
break;
case 2:
IsActived = (boolean)arg1;
break;
case 3:
IsLockedOut = (boolean)arg1;
break;
case 4:
IsNewsLetterAccepted = (boolean)arg1;
break;
case 5:
LandLinePhone = (String)arg1;
break;
case 6:
LastName = (String)arg1;
break;
case 7:
LoginMail = (String)arg1;
break;
case 8:
MobilePhone = (String)arg1;
break;
case 9:
Title = (String)arg1;
break;
default:
break;
}
}
}
First make sure that namespace for most outer object in Your structure (GetCustomerByIdPwdResponse) is "rexwebservices", so adding mapping will be sth. like that:
Second thing - class that You defined is only outer box of Your response. I tried to define serializable of response and first level of Your structure. The response You included was correctly parsed to them.
I left Customer class for You - that is why Customer field in GetCustomerByIdPwdResult class is declared as SoapObject.
Hope it will help. Marcin