Search code examples
javaandroidxmlksoap2

Can I use KSoap2 to send a static XML file as a request


I am using KSoap2 to try to build the XML file request below.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:_5="www.444.com">

<soapenv:Header/>
  <soapenv:Body>
  <_5:GetStaff>
     <!--Optional:-->
     <_5:Request>
        <!--Optional:-->
        <_5:SourceCredentials>
           <!--Optional:-->
           <_5:SourceName>sourcename</_5:SourceName>
           <!--Optional:-->
           <_5:Password>password=</_5:Password>
           <!--Optional:-->
           <_5:SiteIDs>
              <!--Zero or more repetitions:-->
              <_5:int>1111</_5:int>
           </_5:SiteIDs>
              </_5:SourceCredentials>
          </_5:Request>
       </_5:GetStaff>
    </soapenv:Body>
</soapenv:Envelope>

I've attempted to take this and generate the following code but it seems the child elements are causing me problems. I'm new to Ksoap2 and can't find a clear solution to structuring.

    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

        request.addProperty("SourceName", "sourcename");
        request.addProperty("Password", "password=");
        request.addProperty("int", "1111");

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

        HttpTransportSE htse = new HttpTransportSE(URL);

        try{
            htse.call(SOAP_ACTION, envelope);
            SoapPrimitive resultString = (SoapPrimitive) envelope.getResponse();

           ret = resultString.toString();
        }
        catch(Exception e){
            e.printStackTrace();
        }

How would i used KSoap2 to build the tree in order for the child elements to be accessed correctly. The api doesn't respond correctly without this structure.

Is there a way to send this xml file out of maybe an xml resource directly?

or is there another way?

UPDATE: tried to make classes for complex elements

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

import java.util.Hashtable;

/**
* Created by randypfohl on 7/15/15.
*/
public class SourceCredentials implements KvmSerializable {

//Xml variables
private String sourceName;
private String password;
private SiteIDs site;

public SourceCredentials() {
}

public void setSourceName(String sourceName) {
    this.sourceName = sourceName;
}

public String getSourceName() {
    return this.sourceName;
}

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

public String getPassword() {
    return this.password;
}

public void setSiteIDs(SiteIDs site) {
    this.site = site;
}

@Override
public Object getProperty(int index) {

    Object toreturn = null;

    switch (index) {
        case 0:
            toreturn = this.sourceName;
        case 1:
            toreturn = this.password;
        case 2:
            toreturn = this.site;
        default:
            break;
    }
    return toreturn;
}

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


        @Override
        public void setProperty ( int index, Object value){
            switch (index) {
                case 0:
                    this.sourceName = value.toString();
                    break;
                case 1:
                    this.password = value.toString();
                    break;
                case 2:
                    site.setProperty(0, value);
                    break;
            }

        }

        @Override
        public void getPropertyInfo ( int index, Hashtable hashtable, PropertyInfo propertyInfo){
        switch (index) {
            case 0:
                propertyInfo.name = "SourceName";
                propertyInfo.type = PropertyInfo.STRING_CLASS;
                break;
            case 1:
                propertyInfo.name = "Password";
                propertyInfo.type = PropertyInfo.STRING_CLASS;
                break;
            case 2:
                propertyInfo.name = "SiteIDs";
                propertyInfo.type = SiteIDs.class;
                break;
            default:
                break;
        }
    }

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

    @Override
    public void setInnerText (String s){

    }
}

and this is the siteids class.

import java.util.Hashtable;
import java.util.Vector;
import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;

public class SiteIDs extends Vector<Integer> implements KvmSerializable {

@Override
public Object getProperty(int arg0) {
    return this.get(arg0);
}

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

@Override
public void setInnerText (String s){

}

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

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

@Override
public void setProperty(int arg0, Object arg1) {
    this.add(Integer.valueOf(arg1.toString()));
}
}

this is the code that i created.

/* String ret ="fail";

        SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

        SourceCredentials sourceCredentials = new SourceCredentials();
        sourceCredentials.setProperty(0, "name");
        sourceCredentials.setProperty(1, "password");

        SiteIDs siteIDS = new SiteIDs();
        siteIDS.setProperty(0, "1100");
        sourceCredentials.setSiteIDs(siteIDS);

        request.addProperty("SourceCredentials", sourceCredentials);

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

        envelope.addMapping(NAMESPACE, SourceCredentials.class.getSimpleName(), SourceCredentials.class);
        envelope.addMapping(NAMESPACE, SiteIDs.class.getSimpleName(), SiteIDs.class);

        try{
            HttpTransportSE htse = new HttpTransportSE(URL);
            htse.debug = true;
            htse.setXmlVersionTag("<!--?xml version=\"1.0\" encoding= \"UTF-8\" ?-->");
            htse.call(SOAP_ACTION, envelope);
            SoapPrimitive resultString = (SoapPrimitive) envelope.getResponse();

           ret = resultString.toString();
            System.out.println(ret);
        }
        catch(Exception e){
            e.printStackTrace();
        }

        return ret;

I can't figure it out. i seem to always get a strange error.

 SoapFault - faultcode: 'soap:Server' faultstring: 'Server was unable to process request. ---> Object reference not set to an instance of an object.' faultactor: 'null' detail: org.kxml2.kdom.Node@b1eb5d78

Solution

  • You have to create serializable objects and pass them to the SOAP object.

    public class SourceCredentials implements KvmSerializable {
    
        //Xml variables
        private String sourceName;
        private String password;
        private SiteIDs siteIDs;
    
    
        public SourceCredentials(){
        }
    
        public setSourceName(String sourceName){
            this.sourceName = sourceName;
        }
    
        public String getSourceName(){
            return this.sourceName;
        }
    
        public setPassword(String password){
            this.password = password;
        }
    
        public String getPassword(){
            return this.password;
        }
    
        public setSiteIDs(SiteIDs siteIDs){
            this.siteIDs = siteIDs;
        }
    
        public getSiteIDs(){
            return this.siteIDs;
        }
    
        @Override
        public Object getProperty(int index) {
    
            switch(index){
                case 0:
                    return this.sourceName;
                case 1:
                    return this.password;
                case 2:
                    return this.siteIDs;
                default:
                    break
        }
    
        @Override
        public int getPropertyCount() {
            return 3;
    
    
        @Override
        public void setProperty(int index, Object value) {
            switch(index){
                case 0:
                    this.sourceName = value.toString();
                    break;
                case 1:
                    this.password = value.toString();
                    break;
                case 2:
                    this.siteIDs = (SiteIDs) value;                    
                    break;
            }
    
        }
    
        @Override
        public void getPropertyInfo(int index, Hashtable hashtable, PropertyInfo propertyInfo) {
            switch (index){
                case 0:
                    propertyInfo.name = "SourceName";
                    propertyInfo.type = PropertyInfo.STRING_CLASS;
                    break;
                case 1:
                    propertyInfo.name = "Password";
                    propertyInfo.type = PropertyInfo.STRING_CLASS;
                    break;
                case 2:
                    propertyInfo.name = "SiteIDs";
                    propertyInfo.type = PropertyInfo.OBJECT_CLASS;
                    break;
                default:
                    break;
            }
        }
    
        @Override
        public String getInnerText() {
            return null;
        }
    
        @Override
        public void setInnerText(String s) {
    
        }
    

    And you do the same with SiteIds

    Then you pass the Soap object.

    EDIT

    You try this?

    SourceCredentials sourceCredentials = new SourceCredentials();
    
    //Create SiteIDs KvmSerializable object
    SiteIDs siteIDS = new SiteIDS();
    siteIDS.setInt(1111)
    
    //Setters
    sourceCredentials.setSourceName("sourcename");
    sourceCredentials.setPassword("password=");
    sourceCredentials.setSiteIDS(siteIDS);
    
    
    request.addProperty("SourceCredentials", sourceCredentials);
    

    EDIT 2

    Try this

    SiteIDS.java

    public class SiteIDs implements KvmSerializable {
    
        private List<Integer> Int; //change name of variable, int it's a reserved name
    
        public SiteIDs() {
        }
    
        public List<Integer> getInt() {
            return Int;
        }
    
        public void setInt(List<Integer> anInt) {
            Int = anInt;
        }
    
        @Override
        public Object getProperty(int i) {
            switch (i){
                case 0:
                    return Int;
                default:
                    break;
            }
            return null;
        }
    
        @Override
        public int getPropertyCount() {
            return 1;
        }
    
        @Override
        public void setProperty(int i, Object value) {
            switch (i) {
                case 0:
                    this.Int = (List<Integer>) value;
                    break;
                default:
                    break;
            }
        }
    
        @Override
        public void getPropertyInfo(int i, Hashtable hashtable, PropertyInfo propertyInfo) {
            switch (i) {
                case 0:
                    propertyInfo.name = "int";
                    propertyInfo.type = List.class;
                    break;
                default:
                    break;
            }
        }
    
        @Override
        public String getInnerText() {
            return null;
        }
    
        @Override
        public void setInnerText(String s) {
    
        }
    

    And this:

    SourceCredentials sourceCredentials = new SourceCredentials();
    
        //Create SiteIDs KvmSerializable object
          SiteIDs siteIDS = new SiteIDS();
          List<Integer> ints = new ArrayList<Integer>();
          ints.add(1111); //add one o more ints
          siteIDS.setInts(ints);
       //Setters
          sourceCredentials.setSourceName("sourcename");
          sourceCredentials.setPassword("password=");
          sourceCredentials.setSiteIDS(siteIDS);
    
    
          request.addProperty("SourceCredentials", sourceCredentials);