ClassCastException from ksoap2-android response

45 views
Skip to first unread message

Gabriel Podasca

unread,
Sep 7, 2016, 5:06:00 PM9/7/16
to ksoap2-android

I am a beginner in Java and Android and have struggled for the better part of the day with the following problem:


I use ksoap2 to call a login method from a webservice. I expect to get a User object as response, not a SoapObject.


The call from Android is:

private static final String URL = "http://192.168.0.13:8080/LoginWS/LoginWS?wsdl";
   
private static final String NAMESPACE = "http://ws/";
   
private static final String METHOD_LOGIN = "login";

   
......
   
SoapObject request = new SoapObject(NAMESPACE, METHOD_LOGIN);
           
SoapSerializationEnvelope env =
                   
new SoapSerializationEnvelope(SoapEnvelope.VER11);


            request
.addProperty("user", user);


            env
.setOutputSoapObject(request);
            env
.addMapping(NAMESPACE, "user", User.class);

           
HttpTransportSE transport = new HttpTransportSE(URL);
            transport
.debug = true;
            transport
.call(NAMESPACE + METHOD_LOGIN, env);

           
SoapObject response = (SoapObject) env.getResponse();
           
System.out.println(response);

   
......

The Android User class is:
public class User implements KvmSerializable{


   
private int id;
   
private String username;
   
private String password;
   
private String telephone;

   
public User(){
   
}

   
public User(String username, String password, String telephone){
       
this.username = username;
       
this.password = password;
       
this.telephone = telephone;
   
}

   
public String getUsername() {
       
return username;
   
}

   
public void setUsername(String username) {
       
this.username = username;
   
}

   
public int getId() {
       
return id;
   
}

   
public void setId(int id) {
       
this.id = id;
   
}

   
public String getPassword() {
       
return password;
   
}

   
public void setPassword(String password) {
       
this.password = password;
   
}

   
public String getPhoneNumber() {
       
return telephone;
   
}

   
public void setPhoneNumber(String phoneNumber) {
       
this.telephone = phoneNumber;
   
}

   
@Override
   
public Object getProperty(int i) {
       
switch(i)
       
{
           
case 0:
               
return id;
           
case 1:
               
return username;
           
case 2:
               
return password;
           
case 3:
               
return telephone;
       
}

       
return null;
   
}

   
@Override
   
public int getPropertyCount() {
       
return 4;
   
}

   
@Override
   
public void setProperty(int i, Object o) {
       
switch(i)
       
{
           
case 0:
                id
= Integer.parseInt(o.toString());
               
break;
           
case 1:
                username
= o.toString();
               
break;
           
case 2:
                password
= o.toString();
               
break;
           
case 3:
                telephone
= o.toString();
               
break;
           
default:
               
break;
       
}
   
}

   
@Override
   
public void getPropertyInfo(int i, Hashtable hashtable, PropertyInfo propertyInfo) {
       
switch(i)
       
{
           
case 0:
                propertyInfo
.type = PropertyInfo.INTEGER_CLASS;
                propertyInfo
.name = "id";
               
break;
           
case 1:
                propertyInfo
.type = PropertyInfo.STRING_CLASS;
                propertyInfo
.name = "username";
               
break;
           
case 2:
                propertyInfo
.type = PropertyInfo.STRING_CLASS;
                propertyInfo
.name = "password";
               
break;
           
case 3:
                propertyInfo
.type = PropertyInfo.STRING_CLASS;
                propertyInfo
.name = "telephone";
               
break;
           
default:
               
break;
       
}
   
}
}

 env.getResponse() returns SoapObject, not a User object. Its toString() prints
anyType{id=0; username=john; password=doe; telephone=074000000000; }

I activated the transport debug and saw that responseDump has the value:
<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:loginResponse xmlns:ns2="http://ws/"><user><id>0</id><username>john</username><password>doe</password><telephone>074000000000</telephone></user></ns2:loginResponse></S:Body></S:Envelope>

On the server side:

The WS class:

    @WebService(serviceName = "LoginWS")
    @Stateless()
    public class LoginWS {

    @EJB
    private LoginService userService;

    @WebMethod(operationName = "login")
    @WebResult(name="user")
    public User login(@WebParam(name = "user") User user) {
        return userService.login(user);
    }

   }

The User class:

public class User {
   
private int id;
   
private String username;
   
private String password;
   
private String telephone;

   
public long getId() {
       
return id;
   
}

   
public void setId(int id) {
       
this.id = id;
   
}

   
public String getUsername() {
       
return username;
   
}

   
public void setUsername(String username) {
       
this.username = username;
   
}

   
public String getPassword() {
       
return password;
   
}

   
public void setPassword(String password) {
       
this.password = password;
   
}

   
public String getTelephone() {
       
return telephone;
   
}

   
public void setTelephone(String telephone) {
       
this.telephone = telephone;
   
}


I am a beginner in Java and Android and have struggled for the better part of the day with the following problem:

I use ksoap2 to call a login method from a webservice. I expect to get a User object as response, not a SoapObject.

The call from Android is:

   private static final String URL = "http://192.168.0.13:8080/LoginWS/LoginWS?wsdl";
    private static final String NAMESPACE = "http://ws/";
    private static final String METHOD_LOGIN = "login";

    ......
    SoapObject request = new SoapObject(NAMESPACE, METHOD_LOGIN);
            SoapSerializationEnvelope env =
                    new SoapSerializationEnvelope(SoapEnvelope.VER11);


            request.addProperty("user", user);


            env.setOutputSoapObject(request);
            env.addMapping(NAMESPACE, "user", User.class);

            HttpTransportSE transport = new HttpTransportSE(URL);
            transport.debug = true;
            transport.call(NAMESPACE + METHOD_LOGIN, env);

            SoapObject response = (SoapObject) env.getResponse();
            System.out.println(response);

    ......

The Android User class is:

public class User implements KvmSerializable{


    private int id;
    private String username;
    private String password;
    private String telephone;

    public User(){
    }

    public User(String username, String password, String telephone){
        this.username = username;
        this.password = password;
        this.telephone = telephone;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPhoneNumber() {
        return telephone;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.telephone = phoneNumber;
    }

    @Override
    public Object getProperty(int i) {
        switch(i)
        {
            case 0:
                return id;
            case 1:
                return username;
            case 2:
                return password;
            case 3:
                return telephone;
        }

        return null;
    }

    @Override
    public int getPropertyCount() {
        return 4;
    }

    @Override
    public void setProperty(int i, Object o) {
        switch(i)
        {
            case 0:
                id = Integer.parseInt(o.toString());
                break;
            case 1:
                username = o.toString();
                break;
            case 2:
                password = o.toString();
                break;
            case 3:
                telephone = o.toString();
                break;
            default:
                break;
        }
    }

    @Override
    public void getPropertyInfo(int i, Hashtable hashtable, PropertyInfo propertyInfo) {
        switch(i)
        {
            case 0:
                propertyInfo.type = PropertyInfo.INTEGER_CLASS;
                propertyInfo.name = "id";
                break;
            case 1:
                propertyInfo.type = PropertyInfo.STRING_CLASS;
                propertyInfo.name = "username";
                break;
            case 2:
                propertyInfo.type = PropertyInfo.STRING_CLASS;
                propertyInfo.name = "password";
                break;
            case 3:
                propertyInfo.type = PropertyInfo.STRING_CLASS;
                propertyInfo.name = "telephone";
                break;
            default:
                break;
        }
    }
}

env.getResponse() returns SoapObject, not a User object. Its toString() prints

anyType{id=0; username=john; password=doe; telephone=074000000000; }

I activated the transport debug and saw that responseDump has the value:

<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:loginResponse xmlns:ns2="http://ws/"><user><id>0</id><username>john</username><password>doe</password><telephone>074000000000</telephone></user></ns2:loginResponse></S:Body></S:Envelope>

On the server side:

The WS class:

    @WebService(serviceName = "LoginWS")
    @Stateless()
    public class LoginWS {

    @EJB
    private LoginService userService;

    @WebMethod(operationName = "login")
    @WebResult(name="user")
    public User login(@WebParam(name = "user") User user) {
        return userService.login(user);
    }

   }

The User class:

public class User {
    private int id;
    private String username;
    private String password;
    private String telephone;

    public long getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

The webservice is on the Glassfish server from Netbeans. Its generated wsdl is (http://w8-pc:8080/LoginWS/LoginWS?wsdl):

<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws/" name="LoginWS">
<types>
<xsd:schema>
<xsd:import namespace="http://ws/" schemaLocation="http://w8-pc:8080/LoginWS/LoginWS?xsd=1"/>
</xsd:schema>
</types>
<message name="register">
<part name="parameters" element="tns:register"/>
</message>
<message name="registerResponse">
<part name="parameters" element="tns:registerResponse"/>
    </message>
    <message name="login">
    <part name="parameters" element="tns:login"/>
    </message>
    <message name="loginResponse">
    <part name="parameters" element="tns:loginResponse"/>
    </message>
    <portType name="LoginWS">
    <operation name="register">
    <input wsam:Action="http://ws/LoginWS/registerRequest" message="tns:register"/>
    <output wsam:Action="http://ws/LoginWS/registerResponse" message="tns:registerResponse"/>
    </operation>
    <operation name="login">
    <input wsam:Action="http://ws/LoginWS/loginRequest" message="tns:login"/>
    <output wsam:Action="http://ws/LoginWS/loginResponse" message="tns:loginResponse"/>
    </operation>
    </portType>
    <binding name="LoginWSPortBinding" type="tns:LoginWS">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
    <operation name="register">
    <soap:operation soapAction=""/>
    <input>
    <soap:body use="literal"/>
    </input>
    <output>
    <soap:body use="literal"/>
    </output>
    </operation>
    <operation name="login">
    <soap:operation soapAction=""/>
    <input>
    <soap:body use="literal"/>
    </input>
    <output>
    <soap:body use="literal"/>
    </output>
    </operation>
    </binding>
    <service name="LoginWS">
    <port name="LoginWSPort" binding="tns:LoginWSPortBinding">
    <soap:address location="http://w8-pc:8080/LoginWS/LoginWS"/>
    </port>
    </service>
    </definitions>

Please tell me what I am doing wrong, I need

User user = (User) env.getResponse();




to work, not to give a ClassCastException. I have looked all over the net and this mailing list but didn't find an answer.. Please help

Manfred Moser

unread,
Sep 8, 2016, 2:50:02 PM9/8/16
to ksoap2-...@googlegroups.com
You have to assemble the user object from the properties you get off the soapobject. You have to write the code to do that your self ... 

--
You received this message because you are subscribed to the Google Groups "ksoap2-android" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ksoap2-android+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Gabriel Podasca

unread,
Sep 9, 2016, 4:12:19 AM9/9/16
to ksoap2-android
Then why is KvmSerializable even used? Shouldn't it take care of object mapping through its methods?
For automatic object assembly should the Marshal interface be implemented? 

Thank you
To unsubscribe from this group and stop receiving emails from it, send an email to ksoap2-androi...@googlegroups.com.

Manfred Moser

unread,
Sep 9, 2016, 12:25:30 PM9/9/16
to ksoap2-...@googlegroups.com
Correct... for complete automatic unmarshalling you have to implement the Marshal interface for your webservice return.

The alternative is not doing that and only ingest whatever you actually need from the soapobject and not worry about the rest... 

Manfred

To unsubscribe from this group and stop receiving emails from it, send an email to ksoap2-android+unsubscribe@googlegroups.com.

Gabriel Podasca

unread,
Sep 10, 2016, 5:56:30 AM9/10/16
to ksoap2-android
Ok thank you
Reply all
Reply to author
Forward
0 new messages