Donnerstag, 4. Dezember 2008





April 2006
aus XML & Web Services Magazin Ausgabe: 3.2002
Kits und Packs
Die Web Services Toolkits von Sun und IBM im Vergleich
von Daniel S. Haischt

Suns Java Web Services Developer Pack (JWSDP) hat seine Feuerprobe einige Monate nach dem Final Release inzwischen hinter sich gebracht, sodass es nun an der Zeit ist, dieses mit anderen Toolkits für Web Services zu vergleichen. In diesem Artikel soll sich das JWSDP dem direkten Vergleich mit IBMs Web Services Toolkit stellen. Dieses liegt inzwischen in Version 3.22 vor und hat zumindest zeitlich einen Vorsprung von mehr als einem Jahr vorzuweisen. Es soll dabei aufgezeigt werden, wie sich mit den beiden Lösungsansätzen eine einfache Anwendung in Form eines Web Services umsetzen lässt.


Das Augenmerk beim Herunterladen der beiden Development Kits fällt sicherlich zuerst auf den enormen Unterschied der Dateigrößen. Schlägt das Developer Pack von Sun gerade mal mit rund 35 Mbyte zu Buche, so summiert sich die Dateigröße beim IBM Toolkit auf rund 125 Mbyte. Dies rührt allerdings in erster Linie daher, dass versucht wurde, eine möglichst einheitliche Testumgebung für diesen Artikel zu schaffen. Da im IBM Toolkit ein UDDI Registry Server nicht enthalten ist, musste zusätzlich das IBM WebSphere SDK for Web Services heruntergeladen werden. Dies verschlang letztlich auch den Bärenanteil der gesamten Downloadgröße.

Sind die Development Kits erst einmal heruntergeladen, installiert und konfiguriert, findet man zwei Entwicklungslösungen für Web Services vor, die einander ebenbürtig sind. Um dies zu verdeutlichen, sei an dieser Stelle auf die Featurematrix in Tabelle 1 verwiesen.

Entwicklungsparadigmen
Grundsätzlich unterscheiden sich die Development Kits in den einzelnen Entwicklungsschritten nur marginal. Im Wesentlichen sind dies das Erstellen des eigentlichen Web Services, das Beschreiben des Web Services mittels WSDL, das Erstellen eines proprietären Deployment-Deskriptors, der je nach Produkt variiert, und abschließend das Deployment des erstellten Web Services. Dieser Entwicklungsprozess ist in den Abbildungen 1 und 2 nochmals für die jeweiligen Produkte dargestellt. Außerdem erläutert Tabelle 2 wesentliche Details, in denen sich die beiden Development Kits unterscheiden.


Abb. 1: Entwicklungsprozess Sun JWSDP


Abb. 2: Entwicklungsprozess IBM WSTK


Nachfolgend sei auf einige Details verwiesen, die während des Tests besonders aufgefallen sind:
  • Das Sun Developer Pack verwendet das RMI-Protokoll als Aufsatz auf die eigentlichen SOAP Calls.
  • IBMs Implementierung basiert hingegen auf dem Apache Axis-Projekt, welches beim Implementieren eines Web Services keine zusätzlichen APIs benötigt, wodurch sich die Klasse für den Web Service nicht von einer normalen Klasse unterscheidet. Dies spricht vor allem dafür, dass sich nahezu jede Java-Klasse mit nur geringen Aufwand in einen Web Service umwandeln lässt.
  • Sämtliche Schritte des Deployments lassen sich beim Sun Developer Pack mit einem grafischen Tool erledigen. Dies erspart vor allem das lästige Erstellen der einzelnen Deployment-Deskriptoren. Zudem läst sich der erstellte Web Service als WAR-Datei auf einen Tomcat-Server spielen, der auf einem Remote-Rechner läuft.

Die Beispielanwendung
Um den zuvor beschriebenen Entwicklungsprozess und die Toolkit-spezifischen Unterschiede zu veranschaulichen, soll im Folgenden ein einfacher Web Service implementiert werden, der es erlaubt, die Preise verschiedener Magazine abzufragen. Um den Preis eines bestimmten Magazins zu erhalten, muss dem Web Service das Kürzel des jeweiligen Magazins übergeben werden. Im Wesentlichen wird dieser Prozess durch die Methode getPrice(String shortName) abgebildet. In Listings 1 und 2 sind die Web Service-Implementierungen für das zuvor geschilderte Problem dargestellt. Der Quellcode für das Sun Developer Pack enthält dabei sowohl das Interface für den Web Service als auch die eigentliche Klasse.

Listing 1

import java.util.Hashtable;

public class Magazines
{
private Hashtable magazines = new Hashtable();

public Magazines()
{
this.magazines.put("ENT", "29.50");
this.magazines.put("DOT", "41.00");
this.magazines.put("JAV", "52.50");
this.magazines.put("LIN", "37.50");
this.magazines.put("PHP", "52.00");
this.magazines.put("XML", "52.00");
}

public String getPrice(String shortName)
{
return (String) this.magazines.get(shortName);
}

public static void main(String[] args)
{
String shortName = null;

if (args.length == 0)
{
shortName = "ENT";
}
else
{
shortName = args[0];
}

System.out.println("Short name is: " + shortName);
String result = (new Magazines()).getPrice(shortName);
System.out.println("Result was: \n" + result);
}
}

Listing 2

package catalogue;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface MagazinesIF extends Remote
{
public String getPrice(String shortName) throws RemoteException;
}

package catalogue;

import java.util.Hashtable;

public class MagazinesImpl implements MagazinesIF
{
private Hashtable magazines = new Hashtable();

public MagazinesImpl()
{
this.magazines.put("ENT", "29.50");
this.magazines.put("DOT", "41.00");
this.magazines.put("JAV", "52.50");
this.magazines.put("LIN", "37.50");
this.magazines.put("PHP", "52.00");
this.magazines.put("XML", "52.00");
}

public String getPrice(String shortName)
{
return (String) this.magazines.get(shortName);
}
}

Der Quelltext in Listing 3 veranschaulicht die Implementierung des Clients, der letztlich den Web Service aufruft, mit Hilfe des IBM Toolkits. Es fällt auf, dass der Programmieraufwand, der beim Entwickeln des Web Services gespart wurde, in diesem Fall verhältnismäßig groß ist. Dies bestätigt sich im Vergleich zur Client-Anwendung, die mittels Sun Developer Kit umgesetzt wurde (siehe Listing 4). Allerdings darf an dieser Stelle nicht unterschlagen werden, dass der größte Teil des Client-Codes beim Sun Developer Kit in Form so genannter Stubs dynamisch generiert wird. Das heißt, der größte Teil der SOAP-Aufrufe ist im Beispiel nicht sichtbar.

Listing 3

import java.util.Vector;
import java.net.URL;
import javax.xml.namespace.QName;
import com.ibm.wstk.WSTKConstants;
import com.ibm.uddi4j.wsdl.client.UDDIWSDLProxy;
import com.ibm.uddi4j.wsdl.definition.ServiceDefinition;
import com.ibm.uddi4j.wsdl.provider.ServiceProvider;
import org.apache.wsil.WSILDocument;
import org.apache.wsil.client.WSILProxy;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.client.Service ;
import org.apache.axis.client.Call;
import org.uddi4j.datatype.Name;

public class Client
{
private static final String M = "Magazines";

private static final QName MqName =
new QName("urn:Magazines-types", "String");

public static void main(String[] args) throws Exception
{
if (args.length == 0)
{
System.out.println("Usage: java Client [short name of a magazine]");
System.exit(0);
}

try
{
String shortName = args[0];
String wsdlURL = null;

wsdlURL = findUDDI(M + "Service");

if (wsdlURL != null)
{
System.out.println(getPrice(wsdlURL, shortName));
}
else
{
System.out.println(
"The Magazines Service could not be found");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}

private static Object getPrice(String wsdlURL, String shortName) throws Exception
{
QName serviceM = new QName("http://" + M, M + "Service" );
QName portM = new QName("http://" + M, "magazine");
Service service = new Service(new URL(wsdlURL), serviceM );
Call call = (Call)service.createCall(portM, "getPrice");
call.registerTypeMapping(String.class,
MqName,
new BeanSerializerFactory(String.class, MqName),
new BeanDeserializerFactory(String.class,MqName));
return (String)call.invoke( new Object[] { shortName } );
}

public static String findUDDI(
String service)
throws Exception {
try {
UDDIWSDLProxy uwp =
new UDDIWSDLProxy(WSTKConstants.UDDI_INQUIRY_URL,
WSTKConstants.UDDI_PUBLISH_URL,
WSTKConstants.UDDI_USERID,
WSTKConstants.UDDI_CRED,
WSTKConstants.TRANSPORT_CLASS);
Vector providerNameVector = new Vector();
providerNameVector.add(new Name("WSTK 3.2 Tutorial"));
ServiceProvider[] sps =
uwp.findAllServiceProviders(null, providerNameVector,
null,null,null,null,true);
if (sps.length > 0) {
ServiceDefinition sd = sps[0].getServiceDefinition(service);
return sd.getServiceImplementation().getWSDLFilename();
} else {
return null;
}
} catch (Exception e) {
System.out.println(e.getMessage());
System.exit(0);
return null;
}
}
}

Listing 4

package catalogue;

import javax.xml.rpc.Stub;

public class Client
{
public static void main(String[] args)
{
try
{
Stub stub = createProxy();
MagazinesIF magazines = (MagazinesIF)stub;
System.out.println(magazines.getPrice(args[0]));
}
catch (Exception ex)
{
ex.printStackTrace();
}
}

private static Stub createProxy()
{
// Note: MyMagazines_Impl is implementation-specific.
return (Stub)(new MyMagazines_Impl().getMagazinesIFPort());
}
}

Abschließend sollen noch Beispiele für die Deployment-Deskriptoren aufgeführt werden (siehe Listings 5 und 6). Diese werden benötigt, um den Web Service auf dem jeweiligen Server zu installieren. Es sei nochmals darauf verwiesen, dass zumindest beim Sun Developer Pack der Deployment-Deskriptor nicht von Hand erstellt werden muss, obwohl dies mit Sicherheit nur einen geringen Aufwand verursacht.

Listing 5

<deployment
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
name="test">

<service name="magazin" provider="java:RPC">
<parameter name="className" value="Magazines" />
<parameter name="allowedMethods" value="getPrice" />
</service>
</deployment>

Listing 6

<?xml version="1.0" encoding="UTF-8"?>
<webServices
xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd"
version="1.0"
targetNamespaceBase="http://com.test/wsdl"
typeNamespaceBase="http://com.test/types"
urlPatternBase="/ws">

<endpoint
name="MyMagazines"
displayName="Magazines Service"
description="A simple web service"
interface="catalogue.MagazinesIF"
implementation="catalogue.MagazinesImpl"/>

<endpointMapping
endpointName="MyMagazines"
urlPattern="/magazines"/>

</webServices>

Der fertige Web Service
Wurde der Web Service korrekt installiert, kann er von beinahe jeder Programmiersprache aufgerufen werden. Um dies zu veranschaulichen, ist der zugehörige Aufruf des Clients in Abbildung 3 dargestellt. In diesem Beispiel werden die Preise für Magazine wie zum Beispiel das Java Magazin (Kürzel JAV) abgerufen.


Abb. 3: Aufruf des Clients

Fazit
Beiden Toolkits kann attestiert werden, dass sie den für einen Web Service notwendigen Entwicklungsprozess ausreichend abbilden. Sun hat die meisten Tools in das Apache Ant Build Tool integriert, sodass man von den bereits vorhandenen build-Dateien abkupfern kann. Zudem automatisiert das in Abbildung 4 dargestellte Deployment-Tool von Sun den kompletten Deployment Prozess, was man beim IBM Toolkit zum Teil vermisst. Ursprünglich wollte ich in meiner Beispielanwendung auch das Deployment mittels einer UDDI Registry beschreiben. Allerdings produzierte das IBM Deployment-Tool beim Einlesen der WSDL-Files Fehler, die für mich in der Kürze der Zeit nicht nachvollziehbar waren.


Abb. 4: Sun Deployment Tool


Abgesehen von den zuvor geschilderten Problemen, stellen beide Toolkits eine hervorragende Lösung für das Entwickeln von Web Services dar. Dieser Eindruck wird durch eine sehr umfangreiche Dokumentation und durch verschiedene praktische Werkzeuge abgerundet. Einziger Wehrmutstropfen wird für manchen das Fehlen diverser APIs wie der JAXB API zur Datenanbindung sein. Diese Sun-API fehlt nach wie vor im Sun Developer Kit. Darüber hinaus sind die Entwicklungsparadigmen der beiden Toolkits in wesentlichen Punkten grundlegend verschieden, sodass Umsteigern das Einarbeiten in das jeweils andere Toolkit unnötig erschwert wird. Dies wird aber vielleicht dadurch ausgeglichen, dass Sun das für Web Services aufgebohrte J2EE Deployment-Tool mit seinem Developer Pack ausliefert. Mit diesem werden sich vor allem J2EE-Veteranen schnell zurecht finden.

Müsste ich an dieser Stelle bezüglich der beiden Toolkits ein ganz persönliches Statement abgeben, so würde ich sagen, dass IBM die größere Erfahrung in diesem Umfeld mitbringt. Dies zeigt sich im Umfang des Toolkits sowie den zusätzlichen APIs wie zum Beispiel dem Web Services Invocation Framework. Letztlich lassen sich aber mit beiden Toolkits ebenbürtige Ergebnisse erzielen.

Links und Literatur


    Hat Ihnen dieser Artikel gefallen? Dann abonnieren Sie das Entwickler Magazin direkt über unser Online-Formular.

zur vorherigen Seite
zurück
an den Anfang der Seite
nach oben
Diesen Artikel drucken
drucken
Diesen Artikel weiterempfehlen
empfehlen




Software & Support Verlag GmbH