I'm currently trying to retrieve an array from my webservice by using regular Ksoap implementation. However, when trying to access this array I am getting the following logcat error:
04-27 00:27:01.772: ERROR/AndroidRuntime(530): Caused by: java.lang.RuntimeException: Unable to
start activity ComponentInfo{android.waiter/android.waiter.TablesActivity}:
java.lang.ClassCastException: org.ksoap2.serialization.SoapPrimitive
It appears that for some reason Soap is not getting along with the way I am casting my property values. Attached is the problem code (and related methods)
public static TableDTO[] RetrieveFromSoap(SoapObject soap)
{
TableDTO[] tables = new TableDTO[soap.getPropertyCount()];
for (int i = 0; i < tables.length-1; i++) {
SoapObject pii = (SoapObject) soap.getProperty(i);
TableDTO table = new TableDTO();
table.setTableID(Integer.parseInt(pii.getProperty(0).toString()));
table.setCapacity(Integer.parseInt(pii.getProperty(1).toString()));
table.setStatusFlag(pii.getProperty(2).toString());
table.setCurrentWaiter(pii.getProperty(3).toString());
tables[i] = table;
}
return tables;
}
TableDTO Information:
#Override
public Object getProperty(int arg0) {
switch(arg0)
{
case 0:
return TableID;
case 1:
return Capacity;
case 2:
return StatusFlag;
case 3:
return currentWaiter;
}
return null;
}
#Override
public int getPropertyCount() {
// TODO Auto-generated method stub
return 3;
}
#Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo info) {
switch(arg0){
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "TableID";
break;
case 1:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "Capacity";
break;
case 2:
info.type = PropertyInfo.STRING_CLASS;
info.name = "StatusFlag";
break;
case 3:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "currentWaiter";
break;
default:break;
}
}
#Override
public void setProperty(int arg0, Object value) {
switch(arg0)
{
case 0:
TableID = Integer.parseInt(value.toString());
break;
case 1:
Capacity = Integer.parseInt(value.toString());
break;
case 2:
StatusFlag = value.toString();
break;
case 3:
currentWaiter = value.toString();
break;
default :
break;
}
}
The problem is with the line
SoapObject pii = (SoapObject) soap.getProperty(i);
It does not like the casting there. I'm at a loss on how to fix this.
Thanks for your time and help!
Instead of using
SoapObject response = (SoapObject)envelope.getResponse();
Use
SoapObject response = (SoapObject)envelope.bodyIn;
That worked for me.
Related
I'm trying to send complex object to webmethod via ksoap2. A problem occurs when IDE execute AndroidHttpTransport.call command, it sends that error;
java.lang.RuntimeException: Cannot serialize: [webServiceClasses.movementItem#4123d840]
I sent parameter to webmethod which is below;
[WebMethod]
public TransferReturn ApplyVanToVanMovement(vanToVanMovement vMovement)
{
OracleConnection opCnn = new OracleConnection(Settings.Instance.GetConnectionString());
opCnn.Open();
DBOperations dbOp = new DBOperations();
.
.
.
}
Here is my code that sent paramateres to webmethod;
public static TransferReturn ApplyVanToVanMovement(TransferReturn pTransferReturn, vanToVanMovement vMovement)
throws Exception {
String NAMESPACE = "http://tempuri.org/";
String METHOD_NAME = "ApplyVanToVanMovement";
String SOAP_ACTION = "http://tempuri.org/ApplyVanToVanMovement";
String URL;
if (Settings.instance().getDocNum().isApn == 0)
URL = Settings.instance().getDocNum().WANIP + Settings.instance().getDocNum().WANTransferServiceUrl;
else
URL = Settings.instance().getDocNum().LANIP + Settings.instance().getDocNum().LANTransferServiceUrl;
PropertyInfo pi = new PropertyInfo();
pi.setName("vanToVanMovement");
pi.setValue(vMovement);
pi.setType(vMovement.getClass());
Request.addProperty(pi);
ArrayList<movementItem> alMi = vMovement.getItemCollectionField();
for (int i = 0; i < alMi.size(); i++) {
PropertyInfo pi2 = new PropertyInfo();
pi2.setName("movementItem" + i);
pi2.setValue(alMi.get(i));
pi2.setType(movementItem.class);
Request.addProperty(pi2);
}
/*
* Set the web service envelope
*/
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(Request);
envelope.addMapping(NAMESPACE, "vanToVanMovement", new vanToVanMovement().getClass());
for (int i = 0; i < alMi.size(); i++) {
envelope.addMapping(NAMESPACE, "movementItem" + i, movementItem.class);
}
MarshalDouble marshaldDouble = new MarshalDouble();
marshaldDouble.register(envelope);
AndroidHttpTransport androidHttpTransport = new AndroidHttpTransport(URL);
/*
* Call the web service and retrieve result ... how luvly <3
*/SoapObject response = null;
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
response = (SoapObject) envelope.getResponse();
} catch (Exception e) {
e.printStackTrace();
}
// (SoapObject) wsClass.InvokeMethodMarshal(pInfo);
pTransferReturn = (TransferReturn) DBLayout.setSoapObjectToClass(response, pTransferReturn);
return pTransferReturn;
}
My classes, first one is parameter that i sent, second one is property of first one as array(I tried same thing with Vector instead of ArrayList, nothing changed.);
public class vanToVanMovement implements WebServiceReturn {
private long companyIdField;
private long branchIdField;
private long createdUserIdField;
private long fromWarehouseIdField;
private long toWarehouseIdField;
private long representativeIdField;
private long routeIdField;
private long vehicleIdField;
private ArrayList<movementItem> itemCollectionField;
public vanToVanMovement() {
}
public long getCompanyIdField() {
return companyIdField;
}
public void setCompanyIdField(long companyIdField) {
this.companyIdField = companyIdField;
}
public long getBranchIdField() {
return branchIdField;
}
public void setBranchIdField(long branchIdField) {
this.branchIdField = branchIdField;
}
public long getCreatedUserIdField() {
return createdUserIdField;
}
public void setCreatedUserIdField(long createdUserIdField) {
this.createdUserIdField = createdUserIdField;
}
public long getFromWarehouseIdField() {
return fromWarehouseIdField;
}
public void setFromWarehouseIdField(long fromWarehouseIdField) {
this.fromWarehouseIdField = fromWarehouseIdField;
}
public long getToWarehouseIdField() {
return toWarehouseIdField;
}
public void setToWarehouseIdField(long toWarehouseIdField) {
this.toWarehouseIdField = toWarehouseIdField;
}
public long getRepresentativeIdField() {
return representativeIdField;
}
public void setRepresentativeIdField(long representativeIdField) {
this.representativeIdField = representativeIdField;
}
public long getRouteIdField() {
return routeIdField;
}
public void setRouteIdField(long routeIdField) {
this.routeIdField = routeIdField;
}
public long getVehicleIdField() {
return vehicleIdField;
}
public void setVehicleIdField(long vehicleIdField) {
this.vehicleIdField = vehicleIdField;
}
public ArrayList<movementItem> getItemCollectionField() {
return itemCollectionField;
}
public void setItemCollectionField(ArrayList<movementItem> itemCollectionField) {
this.itemCollectionField = itemCollectionField;
}
public Object getProperty(int index) {
switch (index) {
case 0:
return companyIdField;
case 1:
return branchIdField;
case 2:
return createdUserIdField;
case 3:
return fromWarehouseIdField;
case 4:
return toWarehouseIdField;
case 5:
return representativeIdField;
case 6:
return routeIdField;
case 7:
return vehicleIdField;
case 8:
return itemCollectionField;
default:
return null;
}
}
public int getPropertyCount() {
return 9;
}
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo pInfo) {
switch (index) {
case 0:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "companyIdField";
break;
case 1:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "branchIdField";
break;
case 2:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "createdUserIdField";
break;
case 3:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "fromWarehouseIdField";
break;
case 4:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "toWarehouseIdField";
break;
case 5:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "representativeIdField";
break;
case 6:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "routeIdField";
break;
case 7:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "vehicleIdField";
break;
case 8:
pInfo.type = PropertyInfo.OBJECT_CLASS;
pInfo.name = "itemCollectionField";
break;
default:
break;
}
}
public void setProperty(int index, Object obj) {
switch (index) {
case 0:
companyIdField = Long.valueOf(obj.toString());
break;
case 1:
branchIdField = Long.valueOf(obj.toString());
break;
case 2:
createdUserIdField = Long.valueOf(obj.toString());
break;
case 3:
fromWarehouseIdField = Long.valueOf(obj.toString());
break;
case 4:
toWarehouseIdField = Long.valueOf(obj.toString());
break;
case 5:
representativeIdField = Long.valueOf(obj.toString());
break;
case 6:
routeIdField = Long.valueOf(obj.toString());
break;
case 7:
vehicleIdField = Long.valueOf(obj.toString());
break;
case 8:
itemCollectionField = (ArrayList<movementItem>) obj;
break;
default:
break;
}
}
public int getArrayNumber(String s) {
int i = -1;
if (s.equals("companyIdField"))
i = 0;
if (s.equals("branchIdField"))
i = 1;
if (s.equals("createdUserIdField"))
i = 2;
if (s.equals("fromWarehouseIdField"))
i = 3;
if (s.equals("toWarehouseIdField"))
i = 4;
if (s.equals("representativeIdField"))
i = 5;
if (s.equals("routeIdField"))
i = 6;
if (s.equals("vehicleIdField"))
i = 7;
if (s.equals("itemCollectionField"))
i = 8;
return i;
}
}
public class movementItem implements WebServiceReturn {
private long itemIdField;
private long unitSetIdField;
private long unitIdField;
private long unitSetId2Field;
private long unitId2Field;
private double convFact1Field;
private double convFact2Field;
private double planQuantityField;
private double planQuantity1Field;
private double planQuantity2Field;
public movementItem() {
}
public long getItemIdField() {
return itemIdField;
}
public void setItemIdField(long itemIdField) {
this.itemIdField = itemIdField;
}
public long getUnitSetIdField() {
return unitSetIdField;
}
public void setUnitSetIdField(long unitSetIdField) {
this.unitSetIdField = unitSetIdField;
}
public long getUnitIdField() {
return unitIdField;
}
public void setUnitIdField(long unitIdField) {
this.unitIdField = unitIdField;
}
public long getUnitSetId2Field() {
return unitSetId2Field;
}
public void setUnitSetId2Field(long unitSetId2Field) {
this.unitSetId2Field = unitSetId2Field;
}
public long getUnitId2Field() {
return unitId2Field;
}
public void setUnitId2Field(long unitId2Field) {
this.unitId2Field = unitId2Field;
}
public double getConvFact1Field() {
return convFact1Field;
}
public void setConvFact1Field(double convFact1Field) {
this.convFact1Field = convFact1Field;
}
public double getConvFact2Field() {
return convFact2Field;
}
public void setConvFact2Field(double convFact2Field) {
this.convFact2Field = convFact2Field;
}
public double getPlanQuantityField() {
return planQuantityField;
}
public void setPlanQuantityField(double planQuantityField) {
this.planQuantityField = planQuantityField;
}
public double getPlanQuantity1Field() {
return planQuantity1Field;
}
public void setPlanQuantity1Field(double planQuantity1Field) {
this.planQuantity1Field = planQuantity1Field;
}
public double getPlanQuantity2Field() {
return planQuantity2Field;
}
public void setPlanQuantity2Field(double planQuantity2Field) {
this.planQuantity2Field = planQuantity2Field;
}
public Object getProperty(int index) {
switch (index) {
case 0:
return itemIdField;
case 1:
return unitSetIdField;
case 2:
return unitIdField;
case 3:
return unitSetIdField;
case 4:
return unitSetId2Field;
case 5:
return unitId2Field;
case 6:
return convFact1Field;
case 7:
return convFact2Field;
case 8:
return planQuantityField;
case 9:
return planQuantity1Field;
default:
return null;
}
}
public int getPropertyCount() {
return 10;
}
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo pInfo) {
switch (index) {
case 0:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "itemIdField";
break;
case 1:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "unitSetIdField";
break;
case 2:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "unitIdField";
break;
case 3:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "unitSetId2Field";
break;
case 4:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "unitId2Field";
break;
case 5:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "convFact1Field";
break;
case 6:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "convFact2Field";
break;
case 7:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "planQuantityField";
break;
case 8:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "planQuantity1Field";
break;
case 9:
pInfo.type = PropertyInfo.LONG_CLASS;
pInfo.name = "planQuantity2Field";
break;
default:
break;
}
}
public void setProperty(int index, Object obj) {
switch (index) {
case 0:
itemIdField = Long.valueOf(obj.toString());
break;
case 1:
unitSetIdField = Long.valueOf(obj.toString());
break;
case 2:
unitIdField = Long.valueOf(obj.toString());
break;
case 3:
unitSetId2Field = Long.valueOf(obj.toString());
break;
case 4:
unitId2Field = Long.valueOf(obj.toString());
break;
case 5:
convFact1Field = (double)Double.valueOf(obj.toString());
break;
case 6:
convFact2Field = (double)Double.valueOf(obj.toString());
break;
case 7:
planQuantityField = (double)Double.valueOf(obj.toString());
break;
case 8:
planQuantity1Field = (double)Double.valueOf(obj.toString());
break;
case 9:
planQuantity2Field = (double)Double.valueOf(obj.toString());
break;
default:
break;
}
}
public int getArrayNumber(String s) {
int i = -1;
if (s.equals("itemIdField"))
i = 0;
if (s.equals("unitSetIdField"))
i = 1;
if (s.equals("unitIdField"))
i = 0;
if (s.equals("unitSetId2Field"))
i = 1;
if (s.equals("unitId2Field"))
i = 0;
if (s.equals("convFact1Field"))
i = 1;
if (s.equals("convFact2Field"))
i = 0;
if (s.equals("planQuantityField"))
i = 1;
if (s.equals("planQuantity1Field"))
i = 0;
if (s.equals("planQuantity2Field"))
i = 1;
return i;
}
these two classes implement from ;
public interface WebServiceReturn extends KvmSerializable {
public int getArrayNumber(String s);
}
and at last, my marshaling metod, which is utilized to serialize doubles;
public class MarshalDouble implements Marshal {
public Object readInstance(XmlPullParser parser, String namespace, String name,
PropertyInfo expected) throws IOException, XmlPullParserException {
return Double.parseDouble(parser.nextText());
}
public void register(SoapSerializationEnvelope cm) {
cm.addMapping("http://tempuri.org/", "double", Double.class, this);
}
public void writeInstance(XmlSerializer writer, Object obj) throws IOException {
writer.text(obj.toString());
}
}
I'm building my first application in android which consumes a wcf service.I'm using ksoap2 to parse the response.The response is actually an array of objects defined in C#.I did this following this really helpful guide.Now my problem is that I need to consume a wcf service which returns again an array of objects in C# but this time some properties of these objects are other objects.So my question is how can I map the inner objects so that i can parse their properties?
In case I was unclear, I need to parse an object like this:
public class OutterObject {
private InnerObject1 io1;
private InnerObject2 io2;
}
Hope I was clear enough
Ok this is my simplified code i can't post all of it just the portion i think is at fault
SoapObject Request = new SoapObject(NAMESPACE, METHOD_NAME);
Request.addProperty("connString",args.get(0));
Request.addProperty("ClCode", args.get(1));
Request.addProperty("TeCode", args.get(2));
Request.addProperty("CourseDate", args.get(3));
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
envelope.addMapping(namespace, "SRV_WeekProgramm",newSRV_WeekProgramm().getClass());
envelope.addMapping(namespace, "Course", new Course().getClass());
envelope.addMapping(namespace, "StudentHours", new StudentHours().getClass());
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.call(SOAP_ACTION, envelope);
Course response = (Course)envelope.bodyIn; //this is where it crashes
and this is the thrown exception: java.lang.ClassCastException: org.ksoap2.serialization.SoapObject cannot be cast to connectionInitializer.Course
Here is an example that worked for me.
This is response message type from web service
<message name="loginUserResponse">
<part name="code" type="xsd:int"/>
<part name="desc" type="xsd:string"/>
<part name="user" type="tns:user"/>
</message>
The method loginUser definition
<operation name="loginUser">
<documentation>Login user.</documentation>
<input message="tns:loginUserRequest"/>
<output message="tns:loginUserResponse"/>
</operation>
Class UserResponse (Outter) contains User property:
public class UserResponse implements KvmSerializable {
public int code;
public String desc;
public User user;
public Object getProperty(int arg0) {
switch (arg0) {
case 0:
return code;
case 1:
return desc;
case 2:
return user;
default:
break;
}
return null;
}
public int getPropertyCount() {
return 3;
}
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
switch (index) {
case 0:
info.type = PropertyInfo.STRING_CLASS;
info.name = "code";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "desc";
break;
case 2:
info.type = User.class;
info.name = "user";
break;
default:
break;
}
}
public void setProperty(int index, Object value) {
switch (index) {
case 0:
this.code = Integer.parseInt(value.toString());
break;
case 1:
this.desc = value.toString();
break;
case 2:
this.user = (User) value;
default:
break;
}
}
}
And the User class (Inner)
public class User implements KvmSerializable {
public int user_id;
public String username;
public String email;
public String password;
public User() {
}
public Object getProperty(int index) {
switch (index) {
case 0:
return user_id;
case 1:
return username;
case 2:
return email;
case 3:
return password;
default:
return null;
}
}
public int getPropertyCount() {
return 4;
}
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
switch (index) {
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "user_id";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "username";
break;
case 2:
info.type = PropertyInfo.STRING_CLASS;
info.name = "email";
break;
case 3:
info.type = PropertyInfo.STRING_CLASS;
info.name = "password";
break;
default:
break;
}
}
public void setProperty(int index, Object value) {
if(null == value)
value = "";
switch (index) {
case 0:
user_id = Integer.parseInt(value.toString());
break;
case 1:
username = value.toString();
break;
case 2:
email = value.toString();
break;
case 3:
password = value.toString();
break;
}
}
This is important: make sure you register the keys for both outter class and inner class.
envelope.addMapping(NAMESPACE, "loginUserResponse", UserResponse.class);
envelope.addMapping(NAMESPACE, "user", User.class);
Finally, you can get the result by casting:
HttpTransportSE androidHttpTransport = new HttpTransportSE(SERVER_URL); //open the requisition
androidHttpTransport.call(SOAP_ACTION, envelope);// call
UserResponse response = (UserResponse)envelope.bodyIn;
Hope this help!
I am trying to send a complex object through a soap service call in an android application. I am getting a quite weird error.
The class that I am trying to serialize and send (and the one that are included to it) is the following:
public class TSavedMessage extends BaseObject{
public static Class TSAVEDMESSAGE_CLASS = new TSavedMessage().getClass();
protected String sToken;
protected String dateDeferredDelivery;
protected int idDepartment;
protected boolean bDraft;
protected String txtRelationsType;
protected String txtRelatedIds;
protected int idForwardOf;
protected int idReplyOf;
protected String numPriority;
protected boolean bReadReceipt;
protected boolean bDeliveryReport;
protected String txtKeywords;
protected int numTimeOffset;
protected String txtTimeZone;
protected String txtSubject;
protected String txtBody;
protected TRecipient[] recipients;
public TSavedMessage() {
}
public TSavedMessage(String sToken, String dateDeferredDelivery, int idDepartment, boolean bDraft, String txtRelationsType, String txtRelatedIds, int idForwardOf, int idReplyOf, String numPriority, boolean bReadReceipt, boolean bDeliveryReport, String txtKeywords, int numTimeOffset, String txtTimeZone, String txtSubject, String txtBody, TRecipient[] recipients, int[] vesselRelations) {
this.sToken = sToken;
this.dateDeferredDelivery = dateDeferredDelivery;
this.idDepartment = idDepartment;
this.bDraft = bDraft;
this.txtRelationsType = txtRelationsType;
this.txtRelatedIds = txtRelatedIds;
this.idForwardOf = idForwardOf;
this.idReplyOf = idReplyOf;
this.numPriority = numPriority;
this.bReadReceipt = bReadReceipt;
this.bDeliveryReport = bDeliveryReport;
this.txtKeywords = txtKeywords;
this.numTimeOffset = numTimeOffset;
this.txtTimeZone = txtTimeZone;
this.txtSubject = txtSubject;
this.txtBody = txtBody;
this.recipients = recipients;
}
public String getSToken() {
return sToken;
}
public void setSToken(String sToken) {
this.sToken = sToken;
}
public String getDateDeferredDelivery() {
return dateDeferredDelivery;
}
public void setDateDeferredDelivery(String dateDeferredDelivery) {
this.dateDeferredDelivery = dateDeferredDelivery;
}
public int getIdDepartment() {
return idDepartment;
}
public void setIdDepartment(int idDepartment) {
this.idDepartment = idDepartment;
}
public boolean isBDraft() {
return bDraft;
}
public void setBDraft(boolean bDraft) {
this.bDraft = bDraft;
}
public String getTxtRelationsType() {
return txtRelationsType;
}
public void setTxtRelationsType(String txtRelationsType) {
this.txtRelationsType = txtRelationsType;
}
public String getTxtRelatedIds() {
return txtRelatedIds;
}
public void setTxtRelatedIds(String txtRelatedIds) {
this.txtRelatedIds = txtRelatedIds;
}
public int getIdForwardOf() {
return idForwardOf;
}
public void setIdForwardOf(int idForwardOf) {
this.idForwardOf = idForwardOf;
}
public int getIdReplyOf() {
return idReplyOf;
}
public void setIdReplyOf(int idReplyOf) {
this.idReplyOf = idReplyOf;
}
public String getNumPriority() {
return numPriority;
}
public void setNumPriority(String numPriority) {
this.numPriority = numPriority;
}
public boolean isBReadReceipt() {
return bReadReceipt;
}
public void setBReadReceipt(boolean bReadReceipt) {
this.bReadReceipt = bReadReceipt;
}
public boolean isBDeliveryReport() {
return bDeliveryReport;
}
public void setBDeliveryReport(boolean bDeliveryReport) {
this.bDeliveryReport = bDeliveryReport;
}
public String getTxtKeywords() {
return txtKeywords;
}
public void setTxtKeywords(String txtKeywords) {
this.txtKeywords = txtKeywords;
}
public int getNumTimeOffset() {
return numTimeOffset;
}
public void setNumTimeOffset(int numTimeOffset) {
this.numTimeOffset = numTimeOffset;
}
public String getTxtTimeZone() {
return txtTimeZone;
}
public void setTxtTimeZone(String txtTimeZone) {
this.txtTimeZone = txtTimeZone;
}
public String getTxtSubject() {
return txtSubject;
}
public void setTxtSubject(String txtSubject) {
this.txtSubject = txtSubject;
}
public String getTxtBody() {
return txtBody;
}
public void setTxtBody(String txtBody) {
this.txtBody = txtBody;
}
public TRecipient[] getRecipients() {
return recipients;
}
public void setRecipients(TRecipient[] recipients) {
this.recipients = recipients;
}
public Object getProperty(int index) {
switch (index) {
case 0:
return sToken;
case 1:
return dateDeferredDelivery;
case 2:
Integer iDepartment = new Integer(idDepartment);
return iDepartment;
case 3:
Boolean isDraft = new Boolean(bDraft);
return isDraft;
case 4:
return txtRelationsType;
case 5:
return txtRelatedIds;
case 6:
Integer iForwardOf = new Integer(idForwardOf);
return iForwardOf;
case 7:
Integer iReplyOf = new Integer(idReplyOf);
return iReplyOf;
case 8:
return numPriority;
case 9:
Boolean isReadReceipt = new Boolean(bReadReceipt);
return isReadReceipt;
case 10:
Boolean isDeliveryReport = new Boolean(bDeliveryReport);
return isDeliveryReport;
case 11:
return txtKeywords;
case 12:
Integer iTimeOffset = new Integer(numTimeOffset);
return iTimeOffset;
case 14:
return txtTimeZone;
case 15:
return txtSubject;
case 16:
return txtBody;
case 17:
return recipients; // complex type
default:
return null;
}
}
public int getPropertyCount() {
return 18;
}
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) {
switch (index) {
case 0:
info.type = PropertyInfo.STRING_CLASS;
info.name = "sToken";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "dateDeferredDelivery";
break;
case 2:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "idDepartment";
break;
case 3:
info.type = PropertyInfo.BOOLEAN_CLASS;
info.name = "bDraft";
break;
case 4:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtRelationsType";
break;
case 5:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtRelatedIds";
break;
case 6:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "idForwardOf";
break;
case 7:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "idReplyOf";
break;
case 8:
info.type = PropertyInfo.STRING_CLASS;
info.name = "numPriority";
break;
case 9:
info.type = PropertyInfo.BOOLEAN_CLASS;
info.name = "bReadReceipt";
break;
case 10:
info.type = PropertyInfo.BOOLEAN_CLASS;
info.name = "bDeliveryReport";
break;
case 11:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtKeywords";
break;
case 12:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "numTimeOffset";
break;
case 14:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtTimeZone";
break;
case 15:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtSubject";
break;
case 16:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtBody";
break;
case 17:
info.type = PropertyInfo.VECTOR_CLASS;
info.name = "recipients"; // complex type
break;
default:
break;
}
}
public void setProperty(int index, Object value) {
switch (index) {
case 0:
sToken = value.toString();
break;
case 1:
dateDeferredDelivery = value.toString();
break;
case 2:
idDepartment = Integer.parseInt(value.toString());
break;
case 3:
if(value.toString().equalsIgnoreCase("false")) bDraft = false;
else bDraft = true;
break;
case 4:
txtRelationsType = value.toString();
break;
case 5:
txtRelatedIds = value.toString();
break;
case 6:
idForwardOf = Integer.parseInt(value.toString());
break;
case 7:
idReplyOf = Integer.parseInt(value.toString());
break;
case 8:
numPriority = value.toString();
break;
case 9:
if(value.toString().equalsIgnoreCase("false")) bReadReceipt = false;
else bReadReceipt = true;
break;
case 10:
if(value.toString().equalsIgnoreCase("false")) bDeliveryReport = false;
else bDeliveryReport = true;
break;
case 11:
txtKeywords = value.toString();
break;
case 12:
numTimeOffset = Integer.parseInt(value.toString());
break;
case 14:
txtTimeZone = value.toString();
break;
case 15:
txtSubject = value.toString();
break;
case 16:
txtBody = value.toString();
break;
case 17:
recipients = (TRecipient[]) value; // complex type
break;
default:
break;
}
}
}
public class TRecipient extends BaseObject{
public static Class TRECIPIENT_CLASS = new TRecipient().getClass();
protected int idRecipient;
protected String txtRealAddress;
protected String Visibility;
public TRecipient() {
}
public TRecipient(int idRecipient, String txtRealAddress, String visibility) {
this.idRecipient = idRecipient;
this.txtRealAddress = txtRealAddress;
this.Visibility = visibility;
}
public int getIdRecipient() {
return idRecipient;
}
public void setIdRecipient(int idRecipient) {
this.idRecipient = idRecipient;
}
public String getTxtRealAddress() {
return txtRealAddress;
}
public void setTxtRealAddress(String txtRealAddress) {
this.txtRealAddress = txtRealAddress;
}
public String getVisibility() {
return Visibility;
}
public void setVisibility(String visibility) {
this.Visibility = visibility;
}
public Object getProperty(int index) {
switch (index) {
case 0:
Integer iRecipient = new Integer(idRecipient);
return iRecipient;
case 1:
return txtRealAddress;
case 2:
return Visibility;
default:
return null;
}
}
public int getPropertyCount() {
return 3;
}
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) {
switch (index) {
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "idRecipient";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "txtRealAddress";
break;
case 2:
info.type = PropertyInfo.STRING_CLASS;
info.name = "Visibility";
break;
default:
break;
}
}
public void setProperty(int index, Object value) {
switch (index) {
case 0:
idRecipient = Integer.parseInt(value.toString());
break;
case 1:
txtRealAddress = value.toString();
break;
case 2:
Visibility = value.toString();
break;
default:
break;
}
}
}
The method that sends the request is the following:
TSavedMessage msgTemp = new TSavedMessage();
msgTemp.setSToken(LoginActivity.sToken);
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
msgTemp.setDateDeferredDelivery(dateFormat.format(date));
msgTemp.setIdDepartment(datasource.getDepartmentID(departmentString));
msgTemp.setBDraft(false);
msgTemp.setTxtRelationsType("");
msgTemp.setTxtRelatedIds("");
msgTemp.setIdForwardOf(params[1]);
msgTemp.setIdReplyOf(params[2]);
msgTemp.setNumPriority("Normal");
msgTemp.setBReadReceipt(false);
msgTemp.setBDeliveryReport(false);
msgTemp.setTxtKeywords(keywords.getText().toString());
msgTemp.setNumTimeOffset(0);
msgTemp.setTxtTimeZone("0");
msgTemp.setTxtSubject(subject.getText().toString());
msgTemp.setTxtBody(body.getText().toString());
TRecipient[] recarrayTemp = new TRecipient[1];
recarrayTemp[0] = new TRecipient(0, "nickvoulgaris#hotmail.com", "To");
msgTemp.setRecipients(recarrayTemp);
SoapObject recipients = new SoapObject(LoginActivity.NAMESPACE, "Recipients");
SoapObject recarray[] = new SoapObject[1];
for (int i = 0; i < 1; i++){
recarray[i] = new SoapObject(BaseObject.NAMESPACE, "TRecipient");
recarray[i].addProperty("idRecipient", Integer.toString(0));
recarray[i].addProperty("txtRealAddress", "nickvoulgaris#hotmail.com");
recarray[i].addProperty("Visibility", "To");
recipients.addProperty("TRecipient", recarray[i]);
}
SoapObject msg = new SoapObject(BaseObject.NAMESPACE, "MessageToSend");
msg.addProperty("sToken", LoginActivity.sToken);
msg.addProperty("dateDeferredDelivery", msgTemp.getDateDeferredDelivery());
msg.addProperty("idDepartment", Integer.toString(msgTemp.getIdDepartment()));
msg.addProperty("bDraft", "false");
msg.addProperty("txtRelationsType", Integer.toString(0));
msg.addProperty("txtRelatedIds", Integer.toString(0));
msg.addProperty("idForwardOf", Integer.toString(0));
msg.addProperty("idReplyOf", Integer.toString(0));
msg.addProperty("numPriority", msgTemp.getNumPriority());
msg.addProperty("bReadReceipt", "false");
msg.addProperty("bDeliveryReport", "false");
msg.addProperty("txtKeywords", msgTemp.getTxtKeywords());
msg.addProperty("numTimeOffset", msgTemp.getNumTimeOffset());
msg.addProperty("txtTimeZone", msgTemp.getTxtTimeZone());
msg.addProperty("txtSubject", msgTemp.getTxtSubject());
msg.addProperty("txtBody", msgTemp.getTxtBody());
msg.addProperty("Recipients", recipients);
SoapObject rpc = new SoapObject(BaseObject.NAMESPACE, METHOD_NAME);
rpc.addProperty("sToken", LoginActivity.sToken);
rpc.addProperty("MessageToSend", msg);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.encodingStyle = SoapSerializationEnvelope.XSD;
try {
HttpTransportSE androidHttpTransport = new HttpTransportSE(LoginActivity.URL);
androidHttpTransport.debug = true;
androidHttpTransport.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
androidHttpTransport.call(SOAP_ACTION, envelope);
System.out.println("=== " + envelope.getResponse().toString());
}
catch(XmlPullParserException e) {
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
Finally, the error that I'm getting is this one:
SoapFault - faultcode: 'EConvertError' faultstring: '''0nickvoulgaris#hotmail.comTo'' is not a valid integer value'
faultactor: 'null' detail: null
It is quite unfortunate that the error points me to nowhere. I cannot understand why is trying to pass these 3 fields as an Integer. Also what troubles me is the fact that there is a triple quote in the left hand side and a double one in the right hand side.
Any thoughts could prove extremely valuable. Thanks in advance.
Also, the soap object that this code generates and tries to send seems perfectly ok. It is the following:
MobSaveMessage{
sToken=MOB-2704FB8FFBC946469408A3BEE90CA163;
MessageToSend=MessageToSend{
sToken=MOB-2704FB8FFBC946469408A3BEE90CA163;
dateDeferredDelivery=2012/07/25 13:30:36;
idDepartment=18;
bDraft=false;
txtRelationsType=0;
txtRelatedIds=0;
idForwardOf=0;
idReplyOf=0;
numPriority=Normal;
bReadReceipt=false;
bDeliveryReport=false;
txtKeywords=key;
numTimeOffset=0;
txtTimeZone=0;
txtSubject=sub;
txtBody=mail;
Recipients=Recipients{
TRecipient=TRecipient{
idRecipient=0;
txtRealAddress=nickvoulgaris#hotmail.com;
Visibility=To;
};
};
};
}
After all it turns out that we had a wrong version of the WSDL file sent to us along with the specifications. I'm really sorry if I put anyone into trouble. Not really my fault. I'm just responding in case anyone bumps into the question.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="checkpoint">
<SOAP-ENV:Body>
<ns1:getPedidoResponse xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/">
<tabla xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="tns:pedidos[1]">
<item xsi:type="tns:pedidos">
<ID_PEDIDO xsi:type="xsd:int">1</ID_PEDIDO>
<RUT_CLIENTE xsi:type="xsd:int">1234</RUT_CLIENTE>
<ID_PAQUETE xsi:type="xsd:int">1</ID_PAQUETE>
<RUT_EMPLEADO xsi:type="xsd:int">5678</RUT_EMPLEADO>
<DIRECCION xsi:type="xsd:string">la moenda</DIRECCION>
<LATITUD xsi:type="xsd:string">-33,44291</LATITUD>
<lONGITUD xsi:type="xsd:string">-70,65386</lONGITUD>
<ESTADO xsi:type="xsd:int">1</ESTADO>
</item>
</tabla>
</ns1:getPedidoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And this is my class:
public class Pedidos implements KvmSerializable {
public int ID_PEDIDO;
public int RUT_CLIENTE;
public int ID_PAQUETE;
public int RUT_EMPLEADO;
public String DIRECCION;
public String LATITUD;
public String lONGITUD;
public int ESTADO;
public Pedidos(){}
#Override
public Object getProperty(int arg0) {
switch (arg0){
case 0:
return ID_PEDIDO;
case 1:
return RUT_CLIENTE;
case 2:
return ID_PAQUETE;
case 3:
return RUT_EMPLEADO;
case 4:
return DIRECCION;
case 5:
return LATITUD;
case 6:
return lONGITUD;
case 7:
return ESTADO;
default:
return null;
}
}
#Override
public int getPropertyCount() {
return 7;
}
#Override
public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) {
switch (arg0){
case 0:
arg2.type = PropertyInfo.INTEGER_CLASS;
arg2.name = "ID_PEDIDO";
break;
case 1:
arg2.type = PropertyInfo.INTEGER_CLASS;
arg2.name = "RUT_CLIENTE";
break;
case 2:
arg2.type = PropertyInfo.INTEGER_CLASS;
arg2.name = "ID_PAQUETE";
break;
case 3:
arg2.type = PropertyInfo.INTEGER_CLASS;
arg2.name = "RUT_EMPLEADO";
break;
case 4:
arg2.type = PropertyInfo.STRING_CLASS;
arg2.name = "DIRECCION";
break;
case 5:
arg2.type = PropertyInfo.STRING_CLASS;
arg2.name = "LATITUD";
break;
case 6:
arg2.type = PropertyInfo.STRING_CLASS;
arg2.name = "lONGITUD";
break;
case 7:
arg2.type = PropertyInfo.INTEGER_CLASS;
arg2.name = "ESTADO";
break;
default:
break;
}
}
#Override
public void setProperty(int arg0, Object arg1) {
switch(arg0){
case 0:
ID_PEDIDO = Integer.parseInt(arg1.toString());
break;
case 1:
RUT_CLIENTE = Integer.parseInt(arg1.toString());
case 2:
ID_PAQUETE = Integer.parseInt(arg1.toString());
case 3:
RUT_EMPLEADO = Integer.parseInt(arg1.toString());
case 4:
DIRECCION = arg1.toString();
case 5:
LATITUD = arg1.toString();
case 6:
lONGITUD = arg1.toString();
case 7:
ESTADO = Integer.parseInt(arg1.toString());
default:
}
}
}
And here i make the call:
public class MainActivity extends Activity {
static final String SOAP_ACTION="http://192.168.117.1/ws_checkpoint.php/getPedido";
static final String METHOD_NAME="getPedido";
static final String NAMESPACE="checkpoint";
static final String URL="http://192.168.117.1/ws_checkpoint.php";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("pRutEmpleado",5678);
SoapObject result;
HttpTransportSE httpt = new HttpTransportSE(URL);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.addMapping(NAMESPACE, "checkpoint", Pedidos.class);
envelope.dotNet = false;
envelope.bodyOut = request;
try
{
httpt.debug = true;
httpt.call(SOAP_ACTION, envelope);
result = (SoapObject)envelope.bodyIn;
Vector<Pedidos> result_array = (Vector<Pedidos>)envelope.getResponse();
if(result_array != null){
for (Pedidos current_crop: result_array){
System.out.println(current_crop.RUT_EMPLEADO);
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
The error is :
java.lang.ClassCastException: org.ksoap2.serialization.SoapObject
when i trying to print current_crop.RUT_EMPLEADO.
I think this is due to AndroidHttpTransport, please check this out How to call a .NET Webservice from Android using KSOAP2?
and http://seesharpgears.blogspot.com/2010/11/basic-ksoap-android-tutorial.html
Thank you.
I am getting a "casting" error on a property of complex object that is sent to a .NET web service using KSOAP2 from an Android device. The property is an array of complex objects. The documentation on the internet has helped me send and receive simple data types (strings, ints, dates, etc). I can even read an array of complex objects from a .NET web service. I just cannot send back an array of complex objects to the web service. Please help. Here is what I have:
Environment:
Client = Android Development using the latest KSOAP lib for communication.
Server = .NET Web Service (Visual Studio 2008). Note: this is NOT WCF.
.NET Web Service:
[SoapRpcMethod(), WebMethod]
public void WriteCaseInfo(CaseInformation caseInfo)
{
...
...
}
ANDROID CLIENT CODE:
Parent Class Sent as Complex Parameter:
public class CaseInformation extends IABaseKSoap2Serializable
{
public String Name;
public int Id;
public Vector<MultiPartDataElement> SiteListItems = new Vector<MultiPartDataElement>();
#Override
public Object getProperty(int arg0)
{
switch(arg0)
{
case 0:
return Name;
case 1:
return Id;
case 2:
return SiteListItems;
}
return null;
}
#Override
public int getPropertyCount()
{
return 3;
}
#Override
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info)
{
switch(index)
{
case 0:
info.type = PropertyInfo.STRING_CLASS;
info.name = "Name";
break;
case 1:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "Id";
break;
case 2:
info.type = new Vector<MultiPartDataElement>().getClass();
info.name = "SiteListItems";
break;
default:break;
}
}
#Override
public void setProperty(int index, Object value)
{
switch(index)
{
case 0:
Name = value.toString();
break;
case 1:
Id = Integer.parseInt(value.toString());
break;
case 2:
SiteListItems = (Vector<MultiPartDataElement>)value;
break;
default:
break;
}
}
}
Note: If I remove the SiteListItems property from the client code and the web service, everything works.
Complex Class used in Array within the above object:
public class MultiPartDataElement extends IABaseKSoap2Serializable
{
public int Id;
public String Name;
// default constructor
public MultiPartDataElement()
{
}
// overloaded constructor
public MultiPartDataElement(int id, String name)
{
Id = id;
Name = name;
}
#Override
public Object getProperty(int arg0)
{
switch(arg0)
{
case 0:
return Id;
case 1:
return Name;
}
return null;
}
#Override
public int getPropertyCount()
{
return 2;
}
#Override
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info)
{
switch(index)
{
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "Id";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "Name";
break;
default:break;
}
}
#Override
public void setProperty(int index, Object value)
{
switch(index)
{
case 0:
Id = Integer.parseInt(value.toString());
break;
case 1:
Name = value.toString();
break;
default:
break;
}
}
}
Code to Send object as a Parameter to the .Net Web Service:
public static boolean WriteCaseInfo()
{
boolean status = false;
CaseInformation caseInfo = new CaseInformation();
caseInfo.Id = 2725;
caseInfo.Name = "Craig M. Buck";
caseInfo.SiteListItems = new Vector<MultiPartDataElement>();
caseInfo.SiteListItems.add(new MultiPartDataElement(1, "CMB1"));
caseInfo.SiteListItems.add(new MultiPartDataElement(2, "CMB2"));
String methodName = "WriteCaseInfo";
SoapObject request = new SoapObject(NAMESPACE, methodName);
request.addProperty("caseInfo", caseInfo);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = request;
envelope.dotNet = false;
envelope.encodingStyle = SoapSerializationEnvelope.XSD;
envelope.addMapping(IABaseKSoap2Serializable.NAMESPACE, "MultiPartDataElement", new MultiPartDataElement().getClass());
envelope.addMapping(IABaseKSoap2Serializable.NAMESPACE, "CaseInformation", new CaseInformation().getClass());
HttpTransportSE transport = new HttpTransportSE(WebAPIURL + CaseServicesURL);
transport.debug = true;
transport.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
try
{
List<HeaderProperty> headers = BuildHeader();
transport.call(NAMESPACE + methodName, envelope, headers);
String requestDump = transport.requestDump;
String soapDump = transport.responseDump;
SoapObject response = (SoapObject) envelope.bodyIn;
if(response != null)
status = new Boolean(response.getProperty(0).toString());
}
catch(Exception e)
{
status = false;
}
return status;
}
Request Dump from KSOAP:
<?xml version="1.0" encoding="utf-8"?><v:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/"><v:Header /><v:Body><n0:WriteCaseInfo id="o0" c:root="1" xmlns:n0="http://www.medical.draeger.com/webservices/"><caseInfo i:type="n1:CaseInformation" xmlns:n1="http://www.medical.draeger.com/webservices/encodedTypes"><Name i:type="d:string">Craig M. Buck</Name><Id i:type="d:int">2725</Id><SiteListItems i:type="c:Array" c:arrayType="d:anyType[2]"><item i:type="n1:MultiPartDataElement"><Id i:type="d:int">1</Id><Name i:type="d:string">CMB1</Name></item><item i:type="n1:MultiPartDataElement"><Id i:type="d:int">2</Id><Name i:type="d:string">CMB2</Name></item></SiteListItems></caseInfo></n0:WriteCaseInfo></v:Body></v:Envelope>
Note: What I think the issue is, is that the array is defined as "anyTyp" and not MultiPartDataElement -> ... the question is what am I doing wrong here??
Response Dump from KSOAP (After Call):
SoapException: Server was unable to read request. ---> System.InvalidOperationException: There is an error in XML document (1, 828). ---> System.InvalidCastException: Cannot assign object of type System.Object[] to an object of type Draeger.IT.Platform.Web.WebServices.MultiPartDataElement[]
I've had similar problem. You might want to try my personal solution.
http://www.codeproject.com/Tips/222578/Android-access-to-NET-Web-Service-with-object-as-p
You could do this:
int propertyCount = countryDetails.getPropertyCount();
ArrayList list = new ArrayList(propertyCount);
lv_arr = new String[propertyCount];
for (int i = 0; i < propertyCount; i++) {
Object property = countryDetails.getProperty(i);
if (property instanceof SoapObject) {
SoapObject countryObj = (SoapObject) property;
String countryName = countryObj.getProperty("countryName").toString();
list.add(countryName);
}
}
from : Parsing ksoap2 response