2014-11-18 2 views
0

У меня возникли трудности с использованием библиотеки kSOAP2 для android. Я могу отправлять запросы и получать ответ, но я хотел бы отобразить содержимое ответа на простой Java-объект. В основном kSOAP2 позволяет вам это сделать, указав параметры отображения в метод addMapping(). В любом случае у меня возникает исключение класса при попытке передать ответ на мой объект Java. Вот моя реализация:kSoap2 класс сопоставления POJO класс исключение

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

А вот запрос и ответ я получаю, все они хороши:

Запрос:

<?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> 

Ответ:

<?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> 

И вот ошибка, которую я получаю при попытке создать мой 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 

Любая помощь будет замечательной, так как это последний шаг, чтобы заставить меня перейти к реализации моего веб-сервиса.

Спасибо!

UPDATE:

Вот мой класс для моего клиента. У меня теперь есть ошибка при попытке сопоставить клиента с моим классом RexUser. Я добавил карту envelope.addMapping("rexwebservices","RexUser",RexUser.class); в свой конверт. У меня есть ошибка Caused by: java.lang.RuntimeException: Unknown Property: FirstName , когда дело доходит до сохранения данных клиента в пользовательский объект.

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; 
     } 

    } 
} 

ответ

1

Сначала убедитесь, что пространство имен для большинства внешнего объекта в Вашей структуре (GetCustomerByIdPwdResponse) является «rexwebservices», так что добавление отображение будет СТГ. например:

envelope.addMapping("rexwebservices", "GetCustomerByIdPwdResponse", GetCustomerByIdPwdResponse.class); 
envelope.addMapping("rexwebservices", "GetCustomerByIdPwdResult", GetCustomerByIdPwdResult.class); 

Вторая вещь - класс, который вы определили, является только внешней коробкой вашего ответа. Я попытался определить сериализуемый ответ и первый уровень вашей структуры. Ответ, который вы включили, был правильно разобран.

public class GetCustomerByIdPwdResponse implements KvmSerializable { 
    GetCustomerByIdPwdResult getCustomerByIdPwdResult; 

     @Override 
     public Object getProperty(int arg0) { 
      if(arg0==0){ 
       return getCustomerByIdPwdResult; 
      } 
      return null; 
     } 

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

     @Override 
     public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) { 
      if(arg0==0){ 
       arg2.name="GetCustomerByIdPwdResult"; 
       arg2.type=GetCustomerByIdPwdResult.class; 
      } 
     } 

     @Override 
     public void setProperty(int arg0, Object arg1) { 
      if(arg0==0){ 
       getCustomerByIdPwdResult=(GetCustomerByIdPwdResult)arg1; 
      } 
     } 
} 

public class GetCustomerByIdPwdResult implements KvmSerializable { 
    SoapObject Customer; //here goes Customer class ofcourse 
    String ErrorMessage; 
    String SessionId; 

    @Override 
    public Object getProperty(int arg0) { 
     switch(arg0){ 
     case 0: return Customer; 
     case 1: return ErrorMessage; 
     case 2: return SessionId; 
     } 
     return null; 
    } 

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

    @Override 
    public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) { 
     switch(arg0){ 
     case 0: arg2.name="Customer"; arg2.type=SoapObject.class;break; //Customer class 
     case 1: arg2.name="ErrorMessage"; arg2.type=PropertyInfo.STRING_CLASS;break; 
     case 2: arg2.name="SessionId"; arg2.type=PropertyInfo.STRING_CLASS;break; 
     } 
    } 

    @Override 
    public void setProperty(int arg0, Object arg1) { 
     switch(arg0){ 
     case 0: Customer=(SoapObject)arg1;break;//Customer class 
     case 1: ErrorMessage=(String)arg1;break; 
     case 2: SessionId=(String)arg1;break; 
     } 
    } 
} 

Я оставил класс клиентов для вас - вот почему поле клиента в классе GetCustomerByIdPwdResult объявлен как SoapObject.

Надеюсь, это поможет. Marcin

+0

Привет Marcin и спасибо за ваш ответ. Я обязательно попробую это и вернусь к тебе =) – user3476114

+0

Привет снова Марцин. Я пытаюсь решить ваше решение, и оно работает до тех пор, пока мне не нужно отображать примитивные типы. См. Мой обновленный вопрос, чтобы увидеть класс клиента. Это уже огромный шаг, который вы позволили мне поблагодарить за это =) – user3476114

+0

Метод getPropertyInfo должен возвращать точное имя тега. Итак arg2.name = "Имя"; должен быть arg2.name = "FirstName"; Я не знаю, использует ли его a, но для предопределенных типов использует поле из информации о свойствах. Fe. arg2.type = PropertyInfo.STRING_CLASS; и так далее. – mmprog