Experiencing with kSoap 2 and complex objects

As usual, I stumbled upon a problem, but this time during application development for Android.(Jump right into the problem explanation)

Imagine having to develop the application so that it can communicate with a webservice that you have already built some sort of programming language, such as in Java by using Axis2 (maybe in version 1.5.1) and a tomcat server (maybe in version 6).

kSoap 2 is an API designed to enable communication between mobile applications programmed in Java and web services.

I’m not very experienced in the use of this API, but it seemed a common problem of many people who use it, the impossibility of working with a list of objects, or rather with arrays of objects coming back as a result of a method of ur webservice.

Since my problem was a ClassCastException, due to the impossibility of casting the type ‘anyType‘ into something useful, like an object of my creation, or maybe an array of my objects, the solution was found using a method similar to Russian dolls.

Now let me explain better.

In the side of the web service application, you use data types that you created through the classes, but maybe you should call them by their name objects.

These objects are Java Beans suitably designed to be serialized into SOAP messages through the use of Axis2.

Axis2 supports the return lists of objects, so that through the use of SoapUI you can read the SOAP message response from the webservice and note the list of returned items. Even more, in the WSDL file that describes the web service, the return value of this method is marked as ‘sequence‘ object of our type.

The problem is kSoap that fails to convert and manage complex data type as the array of our objects, declaring it as ‘anyType‘.

Fortunately it is possible to decompose the object ‘anyType‘ for extracting fields(actually is a SoapObject, and we can use his methods like .getProperty(index) and .getPropertyCount() ).

The problem is that it does not handle arrays, it only returns the first object instead of the whole list. At this point I had to create an additional class that enclose my array of objects and then I edited the method of the webservice to return this new ‘wrapper‘ object.

kSoap doing so receives a single object that contains within it a sequence of objects that make up the array correctly serialized by Axis2. Here is an explanation of the Russian dolls.A big complex and custom object that include small complex objects.

Is our task in the client side of android, provide to the unwrapping of the object, that is remapped into the corresponding complex-object instances.
This is not a solution but a patch to the problem, a patch that I decided to take as we have upcoming deadlines on the development/deployment of the application.

Here is a picture to express a thousand words I wrote and made you read so far.

Drawing done with Balsamiq Mockups (for Desktop [demo]).

Here is a sample of code that unwraps soapObjects using .getProperty(index) and .getPropertyCount().

http://pastebin.com/JMpeYFK5

 

 

Recap:

webservice-side:

first I create my array of AccessoBean objects, then I give it to  the

.setListaAccesso(AccessoBean[] list)

method of my ArrayOfAccessoBean wrapper object.

My object  ‘AccessoBean’

http://pastebin.com/85dhXXsf

My wrapper object for an array of  ‘AccessoBean’ (how to do a simple wrapper class)

http://pastebin.com/eTBzap3x

So, instead of returning an array( ‘list’ of objects ), I’m returning a single object that contains my array of objects.

Please let me know if you solved this problem in another and/or more elegant way!

Binary Search Tree on Array : pseudo-C++/Qt-code (not really so ‘pseudo’)

Codice su pastebin: http://pastebin.com/wq65fpZv
Download
del codice: http://pastebin.com/download.php?i=wq65fpZv

QVector<myStruct> buildBSTOnArray(QVector<myStruct> vettoreInput){
    //fase di costruzione dell'albero binario di ricerca bilanciato su vettore
    //prelevo il numero di endpoint memorizzati
    int dimensione=vettoreInput.size();
    //calcolo il livello dell'albero che incomincia a contenere le foglie dell'albero bilanciato
    int livello_i=(int)floor(log2((double)dimensione));

    //calcolo poi quanti elementi usualmente stanno in un albero pieno di quel livello
    int elementiLivello_i=(int)pow(2.0,livello_i);
    //scopro quanti nodi del livello i 'passano' da foglie a padri per delle foglie del livello i+1

    int nodiLivello_i= dimensione-elementiLivello_i;
    //Calcolo quanti elementi devo spostare in coda al vettore per ottenere la rappresentazione corretta dell'albero
    int foglieLivello_ip1= nodiLivello_i*2;

    //...e quindi effettuo, se necessario, gli spostamenti
    int i;

    //vettore risultato contenente il BST
    QVector<myStruct> vettoreBST;
    myStruct nodo;

    //////////fase di valorizzazione delle foglie
    if(foglieLivello_ip1>0){
        //se il numero di foglie non è una potenza di 2, allora devo spostare i primi 'foglieLivello_ip1' elementi in fondo al vettore
        //oppure portare in testa gli elementi dopo i primi  'foglieLivello_ip1' elementi
        for(i= foglieLivello_ip1;i<=dimensione-1;i++){
            nodo.key=vettoreInput[i].getKey();
            nodo.isLeaf=true;
            //Aggiungo il nodo
            vettoreBST.push_back(nodo);
        }
        //ora aggiungo i primi elementi
        for(i=0;i<=foglieLivello_ip1-1;i++){
	    nodo.key=vettoreInput[i].getKey();
	    nodo.isLeaf=true;
            //Aggiungo il nodo
            vettoreBST.push_back(nodo);
        }

    }else{
        //ho un numero di foglie pari ad una potenza di 2 e non devo spostare nulla, li copio semplicemente in fondo al vettore
        for(i=0;i<=dimensione-1;i++){
            nodo.key=vettoreInput[i].getKey();
	    nodo.isLeaf=true;
            //Aggiungo il nodo
            vettoreBST.push_back(nodo);
        }
    }
    //////////fase di valorizzazione dei nodi interni
    //Si effettua la costruzione 'bottom-up' dell'albero valorizzando tutti i nodi padre delle foglie precedentemente inserite
    //'Puntatori' a figli sinistro e destro per un particolare nodo genitore
    int leftC,rightC;
    //Inizializzazione dei puntatori ai figli sinistro e destro: inizialmente corrispondono agli ultimi due elementi del vettore finora riempito con delle 'foglie'
    leftC=dimensione-2;
    rightC=dimensione-1;
    //costruzione 'bottom-up'
    for(i=dimensione-1;i>0;i--){
        //indico che non è una foglia del bst	
	nodo.isLeaf=false;
        //aggiungo il nodo padre
        vettoreBST.push_front(nodo);
        //decremento i 'puntatori' ai figli per provedere con la costruzione 'bottom-up'
        leftC--;
        rightC--;
    }//fine for padri

    //valorizzazione dei campi key dei nodi padre(interni), che permettono la ricerca all'interno dell'albero binario bilanciato
    for(i=0;i<=dimensione-2;i++){
        //valorizzo per ogni nodo padre il valore key che mi permette di condurre la ricerca
        //la chiave per i nodi padre sarà il valore chiave dell'ultima foglia del suo sottoalbero sinistro
        int indice=i;
        indice=indice*2+1;//vado al figlio sinistro
        //mi sposto nei sotto alberi destri
        while(!(vettoreBST[indice].isLeaf)){
            indice=indice*2+2;
        }
        //ora ho la chiave da memorizzare nel nodo padre per condurre la ricerca
        vettoreBST[i].key=vettoreBST[indice].key;
    }
	//restituisco il vettore contenente il BST
	return vettoreBST;
}