3

I'm developing an Android app which needs to connect to a .NET SOAP web service and generate/populate a number of objects from the response. I'm totally new to web services and SOAP, and relatively new to Android. The web service has already been built (not by me).

I've been trying to find info on connecting to SOAP web services in Android. The two basic suggestions seem to be:

  1. Don't use SOAP,
  2. If you do use SOAP, use KSOAP2.

I've looked at various tutorials for KSOAP2 but they all seem to deal only with the most basic, primitive types, such as sending 2 ints to get 1 int back, or sending and receiving strings;, however, I need to send custom objects back and forth.

Is it possible to send and receive custom objects using KSOAP2? If so, how easy/difficult is this? Does the XML have to be parsed to create/populate the objects "by hand"?

EDIT/UPDATE: After trying for a while to connect to the existing webservice (takes a String and returns a complex object), and getting an error, I decided to try a simpler approach. I connected to a simpler webservice which takes no parameters, and returns an int. This simpler webservice is hosted in the same place as the original one, and the simple one now works fine for me.

FURTHER UPDATE: All working fine now! Turns out I just had a capitalisation error which was throwing off my parameter.

The final problem was "national" versus "National". Here's the soapUI-generated code:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"     xmlns:tem="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:GetClientByNationalID>
         <!--Optional:-->
         <tem:nationalID>XXXXXXX</tem:nationalID>
      </tem:GetClientByNationalID>
   </soapenv:Body>
</soapenv:Envelope>

And the request code which was being generated by my Java:

<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>
        <GetClientByNationalID xmlns="http://tempuri.org/" id="o0" c:root="1">
            <NationalID i:type="d:string">
                XXXXXXXX
            </NationalID>
        </GetClientByNationalID>
    </v:Body>
</v:Envelope>

My final java code is:

public void webServiceCall() {
    String NAMESPACE = "http://tempuri.org/";
    String METHOD_NAME = "GetClientByNationalID";
    String SOAP_ACTION = "http://tempuri.org/IClientService/GetClientByNationalID"; 

    // unsecure service
    String URL = "http://XXXXXXXXXXXXXXXXXXXX.net/FPUnSecureService/ClientService.svc";

    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); 

    String clientID = "XXXXXXX";

    PropertyInfo pi = new PropertyInfo();
    pi.setName("nationalID"); 
    pi.setValue(clientID); 
    pi.setType(clientID.getClass()); 
    request.addProperty(pi);

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
    envelope.dotNet = true;
    envelope.setOutputSoapObject(request); 

    envelope.addMapping(NAMESPACE, "GetClientByNationalID", new ClientID().getClass());
    Marshal floatMarshal = new MarshalFloat();
    floatMarshal.register(envelope);

    HttpTransportSE t = new HttpTransportSE(URL); 

    ClientID client = new ClientID(); 
    t.debug = true; 

    try { 
        Log.i("webServiceCall", "Trying call to web service");
        t.call(SOAP_ACTION, envelope);
        SoapObject response = (SoapObject) envelope.getResponse();

        Log.i("success", response.getPropertyAsString(0)); 
        Log.i("success", response.getPropertyAsString(1));
        Log.i("success", response.getPropertyAsString(2));
        Log.i("success", response.getPropertyAsString(3));
        Log.i("success", response.getPropertyAsString(4)); 

    } catch (Exception e) {
        Log.e("webServiceCall", "Error calling webservice.");
        e.printStackTrace(); 
        System.out.println("Request: "  + t.requestDump); 
        System.out.println("Response: " + t.responseDump);
    }

}

I am still confused about these lines:

envelope.addMapping(NAMESPACE, "GetClientByNationalID", new ClientID().
Marshal floatMarshal = new MarshalFloat();
floatMarshal.register(envelope);

I think I added the Marshal parts when I was passing an object as a parameter, I'm not sure if I still need them. I'm also not sure about the addMapping call either, and what I should have in there. Thanks.

breadbin
  • 584
  • 1
  • 11
  • 19

2 Answers2

1

Use ksoap2, and check my answers with code examples at the following links: Link1,link2,link3. I wrote some details which will help you understand how to start coding.
let me know if u need help.

UPDATE ( Answering your question about mapping and marshalling)
u use addMapping when you are Sending a complex type ( ie an object) through the soap envelope. How will the webservice recognize the complex type ? u need to create locally a class that implement kvmserializable (as mentionned in my links) which will have same parameter as the object on the server, and then u need to add mapping between it and the class that maps to it on the server, so that the enveloppe when parsed on the server it knows this complex type X map to class X on the server. So if you are not Sending complex type, you don't need to add mapping.(PS:I see that your not sending a complex type since nationalID is of type string. IF lets say nationalID was a complex type of type Z you would do : addMapping(NAMESPACE, Z.class.getSimpleName(), Z.class) )

As for marshalling, it uses java serialization to change Objects to stream of data to be unmarshalled on the web service. So when u are sending a complex type,based on my experience, it is a good practice to add marshalling to change the complex type to streams of data by serializing it. If you find that you don't need it just don't add it, but its always good to understand what are the options out there.

Community
  • 1
  • 1
ccot
  • 1,875
  • 3
  • 36
  • 54
  • Thanks @Shadesco, those are very useful. I'm trying to connect to the webservice now and getting a "org.xmlpull.v1.XmlPullParserException: unexpected type (position:END_DOCUMENT null@1:0 in java.io.InputStreamReader@4052d908)" error. Do you have any ideas about that? – breadbin Feb 06 '12 at 15:59
  • @breadbin it seems like a problem from parsing the response, but anyway i am gonna have to look at some code to be able to help u. re-edit your post add some of your code and tell me where the error is occuring – ccot Feb 06 '12 at 17:15
  • thanks for your response, I have updated the question with more details and code. – breadbin Feb 07 '12 at 10:41
  • @breadbin seems there is a problem with your "String SOAP_ACTION ", are you sure its the right url? or maybe the server as it says requires some added security to it? the simple web service u connected to, does it have the same action as this one? – ccot Feb 07 '12 at 15:39
  • I have gotten past the "ActionNotSupported" error and now am getting a parameter error - which I think is a good sign! I have updated the code and the error message. – breadbin Feb 07 '12 at 16:48
  • @breadbin ok i see it worked, good stuff! about the addMapping, i update my response above check it – ccot Feb 07 '12 at 17:36
0

Look at this http://seesharpgears.blogspot.com/2010/10/ksoap-android-web-service-tutorial-with.html , there are examples of how to pass complex objects.

Marcos
  • 4,643
  • 7
  • 33
  • 60