# AXIS2 Webservice: Umgang mit komplexen Datentypen



## sunnyheinz (6. Jan 2011)

Hallo zusammen,

ich erstelle gerade einige Webservices mit AXIS2 und dem ECLIPSE WTP Plugin (Axis2 V1.4 und ECLIPSE GANYMEDE). Das klappt soweit ganz gut, aber ich habe noch ein Verständisproblem bzgl. der Behandlung nichtprimitiver Datentypen, das ich über google nicht klären konnte (vermutlich in Ermangelung des passenden Suchwortes )

Meine Webservice Klasse sieht wie folgt aus:

```
package com.sh.test;

import java.util.UUID;

public class Webservice {
	public enum Meinenum {EINS, ZWEI, DREI}
	
	public Meinenum test(UUID uuid) {
		System.out.println("Aufruf mit UUID: " + uuid.toString());
		return(Meinenum.EINS);
	}
}
```

Ok, ist sinnfrei, soll aber auch nur ein Test sein. Ich kann aus dieser Klasse mittels WTP einen Webservice bauen und deployen und auch einen WebserviceStub für den Client generieren.

*Problem:* 
Der Stub definiert eine eigene UUID Klasse _WebserviceStub.UUID_, die dann für das Requestobjekt verwendet werden muss. Ein cast des UUID Objektes aus java.util wird nicht akzeptiert.
Zudem ist der Rückgabewert der _get_return()_ Methode des Responseobjektes auch nicht vom Typ _Meinenum_, sondern vom Typ _Webservice_Meinenum_ und lässt sich einer Variablen vom Typ _Meinenum _auch nicht zuweisen.

Wenn ich einen int als Rückgabewert und einen String als Übergabeparameter definiere, funktioniert freilich alles, aber ich würde gerne verstehen, wie man mit komplexeren Datentypen richtig umgeht.


----------



## mvitz (6. Jan 2011)

In Verbindung mit Metro (JAX-WS Implementierung) habe ich dafür eine Möglichkeit gefunden, dieses Problem zu lösen, zu Axis/Axis2 ist mir (außer den Client NICHT zu generieren und die Axis2 API zu nutzen) keine Möglichkeit bekannt.

Die wohl sinnvollste Lösung ist es, die Aufrufe deines WS-Clients in einer Methode zu kapseln, die Argumente und Rückgabewerte umwandelt.

Hilfreich für komplexere Objekte ist dabei: BeanUtils (Commons BeanUtils 1.8.3 API)


----------



## fastjack (7. Jan 2011)

Ich habe schon vor ca. zwei Jahren komplexe Datentypen mit Java-Webservices (Axis) verwendet. Java<->Java und Java<->.net kein Problem. Probleme gab es allerdings mit Listen von komplexen Datentypen, wenn es sich um einen .net <3.5 Client handelte. .net hatte den Code immer so generiert, das Rückgaben und Anfragen mit Listen immer null sendeten/empfingen. Dort mußte manuell der .net Code angepaßt werden, dann lief es.


----------



## fastjack (7. Jan 2011)

Zum Problem: Wenn in aus Deiner WSDL ein Webservice_MeinEnum generiert wird, mußt Du das auch in der Software in irgendeiner Form verwenden.


----------



## sunnyheinz (7. Jan 2011)

Danke für Eure Rückmeldungen!

Aktuell wandle ich die zu übertragenden Objekte mittels xstream in einen XML String, übertrage diesen und wandle auf der Clientseite mit xstream wieder zurück in das Ausgangsobjekt. Das funktioniert zwar, kommt mir aber umständlich vor, denn diese Konvertierung hätte ich eigentlich vom Axis2 Framework erwartet.

Ich schaue mir mal an, was Axis2 aus meinen Objekten bei der Übertragung macht. Vielleicht komme ich ja ohne xstream aus und kann auf der Clientseite das Ursprungsobjekt aus den Stub-Eigenen Klassen wieder entnehmen und ein Objekt der Originalklasse zuammenbauen.

Kann ich Axis2 nicht irgendwie sagen, wie ein custom-Typ serialisiert und deserialisiert werden soll, so dass auf der Clientseite gleich der richtige Objekttyp erzeugt wird?


----------



## sunnyheinz (13. Jan 2011)

Mal ein Zwischenstand zu meinem Problem: Habe jetzt zu allen Businessobjekten und den davon referenzierten Objekten, die als Parameter oder Rückgabewert verwendet werden, vereinfachte "Transportobjekte" erstellt. Diese Transportobjekte enthalten nur primitive Datentypen oder sie referenzieren weitere Transportobjekte. 

Für jedes Paar Businessobjekt/Transportobjekt habe ich Konverter erstellt, die vor und zurück konvertieren können.
Auf der Serverseite verwende ich nun diese Transportobjekte, wandele sie in Businessobjekte, arbeite mit den Businessobjekten und wandele anschließend den Rückgabewert wieder in ein Transportobjekt. Das funktioniert soweit, wenn es auch umständlich ist.

Mit diesen Transportobjekten als Schnittstellenparameter und Rückgabewerte habe ich dann den Webservice generiert.

Anschließend habe ich dann den Client generiert. Dabei wurde für jedes Transportobjekt ein zusätzliches Objekt mit gleichem Namen erzeugt, das im Client Stub definiert wird(!). Damit musste ich dann zusätzliche Konvertierungsroutinen schreiben, die dann von diesen Client-Transportobjekten in Businessobjekte und zurück wandeln.

Der gesamte Weg ist also jetzt wie folgt:

- Client will Businessobjekt übertragen
- Client wandelt Businessobjekt und alle referenzierten Objekte in Client-Transportobjekte
- Client überträgt Client-Transportobjekte an Server
- Beim Server kommen Transportobjekte an (nicht Client-Transportobjekte!)
- Server wandelt Transportobjekte in Businessobjekte
- Server arbeitet mit Businessobjekten
- Server wandelt Businessobjekte in Transportobjekte (nicht Client-Transportobjekte!)
- Server verschickt Transportobjekte als Response
- Beim Client kommen Client-Transportobjekte an
- Client wandelt Client-Transportobjekte in Businessobjekte

Also eine üble Konvertierungsorgie. Wenn ich jetzt ein Attribut im Businessobjekt ändere, muss ich alle Transportobjekte und mehrere Konvertierungsroutinen anpassen.

Scheint mir noch nicht ganz die optimale Lösung zu sein... ;(


----------

