Ksoap2 Android - how to specify a namespace for the child properties of a complex object?
Asked Answered
A

2

6

I'm trying to upload a complex object to a WCF webservice using KSoap2 Android and having some difficulty doing this. I have achieved successful calls to the webservice when I use SoapUI and fill in the data by hand. The successful SoapUI-generated request is as follows:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:fpm="http://schemas.datacontract.org/2004/07/FPMobileServices">
<soapenv:Header/>
<soapenv:Body>
  <tem:CommitOne>
     <tem:qr>
        <fpm:ClientID>8aa2f6a4-4d15-4b4c-9cac-fb2478d0d27a</fpm:ClientID>
        <fpm:CreatedBy>admin</fpm:CreatedBy>
        <fpm:CreatedDate>2012-03-01T19:50:37</fpm:CreatedDate>
        <fpm:DimensionID>8a02a339-b5a7-4c76-b95f-5891ef57736d</fpm:DimensionID>
        <fpm:ImageID>b76c7bcc-a8f8-49ff-94c6-08cd2e05b1a8</fpm:ImageID>
        <fpm:IndicatorID>4637b333-701d-4d03-a708-4de48569be84</fpm:IndicatorID>
        <fpm:LoanOperationNumber>6-2011-72978</fpm:LoanOperationNumber>
        <fpm:ModifiedBy>admin</fpm:ModifiedBy>
        <fpm:ModifiedDate>2012-03-01T19:50:37</fpm:ModifiedDate>
        <fpm:QuestionaireCompletedDate>2012-03-01T19:50:54</fpm:QuestionaireCompletedDate>
        <fpm:QuestionnaireID>99967f70-8161-4922-929f-03136a389ba6</fpm:QuestionnaireID>
        <fpm:ResultID>95fa03b5-80af-479d-9dec-f2bf94baf3cd</fpm:ResultID>
        <fpm:ResultWeighting>0</fpm:ResultWeighting>
        <fpm:StatusLevelID>03a91cd6-93cd-4503-a676-efa2967e82a7</fpm:StatusLevelID>
        <fpm:UploadID>141D6A1F-8FFD-4CA4-8073-009338F22B13</fpm:UploadID>
     </tem:qr>
  </tem:CommitOne>
</soapenv:Body>
</soapenv:Envelope>

The request generated by my Java code is:

<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>
    <CommitOne xmlns="http://tempuri.org/" id="o0" c:root="1">
        <qr>
            <ClientID>8aa2f6a4-4d15-4b4c-9cac-fb2478d0d27a</ClientID>
            <LoanOperationNumber>6-2011-72978</LoanOperationNumber>
            <CreatedBy i:null="true" />
            <CreatedDate>2012-03-01T19:50:37</CreatedDate>
            <DimensionID>8a02a339-b5a7-4c76-b95f-5891ef57736d</DimensionID>
            <ImageID>b76c7bcc-a8f8-49ff-94c6-08cd2e05b1a8</ImageID>
            <IndicatorID>4637b333-701d-4d03-a708-4de48569be84</IndicatorID>
            <ModifiedBy i:null="true" />
            <ModifiedDate i:null="true" />
            <QuestionnaireCompletedDate>2012-03-01T19:50:54</QuestionnaireCompletedDate>
            <QuestionnaireID>99967f70-8161-4922-929f-03136a389ba6</QuestionnaireID>
            <ResultID i:type="d:string">95fa03b5-80af-479d-9dec-f2bf94baf3cc</ResultID>
            <ResultWeighting>0</ResultWeighting>
            <StatusLevelID>03a91cd6-93cd-4503-a676-efa2967e82a7</StatusLevelID>
            <UploadID i:type="d:string">8ffa3665-b691-486f-91a0-ebbe8575896c</UploadID>
        </qr>
    </CommitOne>
</v:Body>

The main difference between the two seems to be the prefixes/namespaces. For some reason when the "qr" object arrives in my .NET code, all its properties are null/zero.

I have tried 2 different approaches in my java code, trying to set my "qr" object as a PropertyInfo:

    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); 

    // build request object 
    PropertyInfo qrPi = new PropertyInfo();
    qrPi.setName("qr");
    qrPi.setType(qr.getClass());
    qrPi.setValue(qr);

    request.addProperty(qrPi); 

And also setting my "qr" as a SoapObject and then using .addProperty:

    SoapObject result = new SoapObject(NAMESPACE, "qr");
    result.addProperty("ClientID", (String) qr.getClientID());
    result.addProperty("CreatedBy", (String) qr.getCreatedBy());
    result.addProperty("CreatedDate", (String) qr.getCreatedDate());
    result.addProperty("DimensionID", (String) qr.getDimensionID());
    result.addProperty("ImageID", (String) qr.getImageID());
    result.addProperty("IndicatorID", (String) qr.getIndicatorID());
    result.addProperty("LoanOperationNumber", (String) qr.getLoanOperationNumber());
    result.addProperty("ModifiedBy", (String) qr.getModifiedBy());
    result.addProperty("ModifiedDate", (String) qr.getModifiedDate());
    result.addProperty("QuestionnaireCompletedDate", (String) qr.getQuestionnaireCompletedDate());
    result.addProperty("QuestionnaireID", (String) qr.getQuestionnaireID());
    result.addProperty("ResultID", (String) qr.getResultID());
    result.addProperty("ResultWeighting", qr.getResultWeighting());
    result.addProperty("StatusLevelID", (String) qr.getStatusLevelID());
    result.addProperty("UploadID", (String) qr.getUploadID());

    request.addSoapObject(result); 

But both of these approaches get the same result - all my "qr" object's fields are null when it gets into my webservice. I have been looking for similar questions on StackOverflow and found this but I can't figure out how to apply it to my own case.

Can anyone help shed any light on the situation?

Aboutface answered 6/3, 2012 at 16:16 Comment(0)
A
11

Not sure if I'm supposed to answer my own question, but I've figured out a solution and will leave it here for anyone who has a similar issue.

The key is different namespaces. In the SoapUI generated example we can see that the child elements (ClientID etc) use the fpm namespace, while the elements above them use the tem namespace. To explicitly specify the namespace for these child elements, I altered the 2nd approach discussed above - I created PropertyInfo objects for each child element and added them to the SoapObject.

Instead of using:

result.addProperty(String "ClientID", Object qr.getClientID());

I used:

PropertyInfo pi = new PropertyInfo();
pi.setNamespace(QR_NAMESPACE);
pi.setType(PropertyInfo.STRING_CLASS);
pi.setName("ClientID");
pi.setValue(qr.getClientID()); 
result.addProperty(pi);

When I did this with all the properties, it worked fine.

Hope this helps someone else some day!

Aboutface answered 7/3, 2012 at 15:46 Comment(2)
Hi breadbin, in your example namespace has prefix like "tem" and "fpm" . How can we add these prefixes in our PropertyInfo? or it will be taken care by library iteself?Proliferous
@silwar, see the "pi.setNameSpace(QR_NAMESPACE)" line in the code above - this is setting a string as the namespace for the PropertyInfo object.Aboutface
L
1

I've had a similar problem, but my objects implement KvmSerializable and KSoap serializes them automatically (they were generated from WSDL by wsdl2code). In this case the simplest solution was to set PropertyInfo.namespace in parent's getPropertyInfo method, like this:

@Override
public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
    switch(index){
        case 0:
            info.type = Person.class;
            info.name = "Person";
            info.namespace = "http://schemas.example.com/crm";
            break;
    }
}
Longicorn answered 26/4, 2018 at 14:39 Comment(4)
Hi..can you elaborate what you did and had you get the solution.i use above link to generate files but don't know how to use that..Easterly
@VishwaPratap Generated files should include one "main" file with a name of the target service (e.g. SampleService.java). It contains methods for accessing every "operation" defined in WSDL. If you have a problem with missing namespaces in nested objects, you can use solution in my answer. For example, if objects relations are Project->Task->Person, you can define Person's namespace in Task's getPropertyInfo method.Longicorn
I got my solution for the problem please see my complete answer belowEasterly
Hi, it seems that you have the same problem as described here by me #63376712 I have try to add namespace to fields of the object and also to the object. Can you explain your solution a little bit more please?Danyelledanyette

© 2022 - 2024 — McMap. All rights reserved.