Search code examples
androidapache-axisandroid-ksoap2

kSOAP 2 Android - Send complex type to Java Axis2 Webservice


I have written an Axis 2 Java Web Service. In this webservice there is one method called "insert Entry".

From the Android i would like to parse my own object to the webservice but there is a little more that i have to know about the sending process.

Webservice method

public int insertEntry(Object entry)
{
    return 1;
}

The class from the webservice is implementing serializable

Entry object in Android

import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;

import java.util.Hashtable;

public class Entry implements KvmSerializable {

private String destination_appliance;
private String contact;
private String card;
private String tariff;
private String tara_in;
private String reference;

public Entry(String destination_appliance, String contact, String card, String tariff, String tara_in, String reference)
{
    this.destination_appliance = destination_appliance;
    this.contact = contact;
    this.card = card;
    this.tariff = tariff;
    this.tara_in = tara_in;
    this.reference = reference;
}

public String getDestinationAppliance() {
    return destination_appliance;
}

public void setDestinationAppliance(String destination_appliance) {
    this.destination_appliance = destination_appliance;
}

public String getContact() {
    return contact;
}

public void setContact(String contact) {
    this.contact = contact;
}

public String getCard() {
    return card;
}

public void setCard(String card) {
    this.card = card;
}

public String getTariff() {
    return tariff;
}

public void setTariff(String tariff) {
    this.tariff = tariff;
}

public String getTaraIn() {
    return tara_in;
}

public void setTaraIn(String tara_in) {
    this.tara_in = tara_in;
}

public String getReference() {
    return reference;
}

public void setReference(String reference) {
    this.reference = reference;
}

@Override
public Object getProperty(int pid) {
    switch (pid) {
        case 0:
            return this.destination_appliance;

        case 1:
            return this.contact;

        case 2:
            return this.card;

        case 3:
            return this.tariff;

        case 4:
            return this.tara_in;

        case 5:
            return this.reference;

        default:
            break;
    }

    return null;
}

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

@Override
public void getPropertyInfo(int index, Hashtable htable, PropertyInfo info) {
    switch (index) {
        case 0:
            info.type = PropertyInfo.STRING_CLASS;
            info.name = "destination_appliance";
            break;

        case 1:
            info.type = PropertyInfo.STRING_CLASS;
            info.name = "contact";
            break;
        case 2:
            info.type = PropertyInfo.STRING_CLASS;
            info.name = "card";
            break;

        case 3:
            info.type = PropertyInfo.STRING_CLASS;
            info.name = "tariff";
            break;

        case 4:
            info.type = PropertyInfo.STRING_CLASS;
            info.name = "tara_in";
            break;

        case 5:
            info.type = PropertyInfo.STRING_CLASS;
            info.name = "reference";
            break;

    }

}

@Override
public String getInnerText() {
    return null;
}

@Override
public void setInnerText(String s) {

}

@Override
public void setProperty(int index, Object value) {
    switch (index) {
        case 0:
            this.destination_appliance = value.toString();
            break;
        case 1:
            this.contact = value.toString();
            break;
        case 2:
            this.card = value.toString();
            break;
        case 3:
            this.tariff = value.toString();
            break;
        case 4:
            this.tara_in = value.toString();
            break;
        case 5:
            this.reference = value.toString();
            break;
    }
}
}

doBackground method of my AsyncTask

private class InsertEntryAsyncTask extends AsyncTask<Object, Void, Integer> {

    private String resp;
    private KSoapHandler kSoap = new KSoapHandler();
    private static final String METHOD_NAME = "insertEntry";
    private static final String SOAP_ACTION = "XXXX/" + METHOD_NAME;

    @Override
    protected Integer doInBackground(Object... params) {

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        SoapObject request = new SoapObject(kSoap.getNAMESPACE(), METHOD_NAME);

        PropertyInfo prop = new PropertyInfo();

        prop.setName("Entry");
        prop.setValue(params[0]);
        prop.setType(params[0].getClass());
        request.addProperty(prop);

        envelope.setOutputSoapObject(request);

        HttpTransportSE transport = new HttpTransportSE(kSoap.getURL());

        try {
            transport.call(kSoap.getNAMESPACE() + kSoap.getSOAP_ACTION_PREFIX() + METHOD_NAME, envelope);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }

        try {
            SoapObject response = (SoapObject) envelope.getResponse();


        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return 1;
    }

    @Override
    protected void onPostExecute(Integer response) {
    }
}

Execute call from AsyncTask

Entry entry = new Entry("Test","0","0","0","Test", "Test");

InsertEntryAsyncTask asyncTaskInsertEntry = new InsertEntryAsyncTask();

asyncTaskInsertEntry.execute(entry);

Please let me know how i can send the entry object to the Axis2 Webservice.

Is this the right way or are there some bugs in the code?!

Thanks for you help!

Best Regards Florens

----- UPDATE ----

Ok at the moment the request from Android is:

<?xml version="1.0" encoding="UTF-8"?>
<v:Envelope xmlns:v="http://schemas.xmlsoap.org/soap/envelope/" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
   <v:Header />
   <v:Body>
      <n0:insertEntry xmlns:n0="http://wmswebservice.development.ais.at" id="o0" c:root="1">
         <E i:type="n0:Entry">
            <destinationAppliance i:type="d:string">021</destinationAppliance>
            <contact i:type="d:string">0</contact>
            <card i:type="d:string">0</card>
            <tariff i:type="d:string">0</tariff>
            <taraIn i:type="d:string">12</taraIn>
            <reference i:type="d:string">KR</reference>
         </E>
      </n0:insertEntry>
   </v:Body>
</v:Envelope>

And the default request from SoapUI is this one - This works perfect -->

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wms="http://wmswebservice.development.ais.at" xmlns:xsd="http://model.wmswebservice.development.ais.at/xsd">
   <soapenv:Header/>
   <soapenv:Body>
      <wms:insertEntry>
         <!--Optional:-->
         <wms:E>
            <!--Optional:-->
            <xsd:card>?</xsd:card>
            <!--Optional:-->
            <xsd:contact>?</xsd:contact>
            <!--Optional:-->
            <xsd:destinationAppliance>?</xsd:destinationAppliance>
            <!--Optional:-->
            <xsd:reference>?</xsd:reference>
            <!--Optional:-->
            <xsd:taraIn>?</xsd:taraIn>
            <!--Optional:-->
            <xsd:tariff>?</xsd:tariff>
         </wms:E>
      </wms:insertEntry>
   </soapenv:Body>
</soapenv:Envelope>

So how can i create a request like this with kSoap2 ? :/


Solution

  • You have not registered Your Entry in envelope by addMapping. Besides, Your code works just fine. With added mapping (yeah i used mock mapping asdf.com):

    envelope.addMapping("http://asdf.com", "Entry", Entry.class);
    

    it produces nice envelope:

    <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:insertEntry id="o0" c:root="1" xmlns:n0="http://asdf.com">
                <Entry i:type="n0:Entry">
                    <destination_appliance i:type="d:string">Test</destination_appliance>
                    <contact i:type="d:string">0</contact>
                    <card i:type="d:string">0</card>
                    <tariff i:type="d:string">0</tariff>
                    <tara_in i:type="d:string">Test</tara_in>
                    <reference i:type="d:string">Test</reference>
                </Entry>
            </n0:insertEntry>
        </v:Body>
    </v:Envelope>
    

    What is problem - i dont know if its what Your webservice needs. Install SoapUI and play a bit with calling Your WS and You will see what You need. Add also flag transport.debug=true, before transport.call, and print to log etc. request dumps - it helps You to see what You have on out and in.

    Well - Your code with added mapping should make proper call to Your WS as far as i may se "on the look".

    part 2

    Your declared on server side WS interface as

    public int insertEntry(Object entry)
    {
        return 1;
    }
    

    As i mentioned in comments, You may remove addMapping. Request will then carry not i:type="n0:Entry", but i:type="anyType" and it may be - WS consumes the request.

    Else:part 3.

    I have a bit knowledge about Axis WS's. Ive made only clients using Axis. But... in general - to use Entry type (i:type="no:Entry") You have to declare interface as

    public int insertEntry(Entry entry)
    {
        return 1;
    }
    

    where Entry will be additional class on server side. That will be something like such small POJO similiar to that in Your Android code:

    public class Entry {
    public String destination_appliance;
    public String contact;
    public String card;
    public String tariff;
    public String tara_in;
    public String reference;
    }
    

    As far as i know Axis will build such WS. But how to do it i dont know - try uncle Google for example of fe. "Axis webservice complex function argument".

    Or maybe let some Axis professional let us know here :)

    part 4.

    Ok, so - remove addMapping and add envelope.implicitTypes=true. If it still not ok, then (but only then) add line with setNamespace on property Entry.

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.implicitTypes=true;
    SoapObject request = new SoapObject(kSoap.getNAMESPACE(), METHOD_NAME);
    
    PropertyInfo prop = new PropertyInfo();
    
    prop.setName("Entry");
    prop.setValue(params[0]);
    prop.setType(params[0].getClass());
    prop.setNamespace(kSoap.getNAMESPACE());
    request.addProperty(prop);