Mittwoch, 23. Mai 2012


Artikel

Juni 2005 | Artikel

Kits und Packs

(Link zum Artikel: http://www.entwickler.de/jaxenter//000241)

Die Web Services Toolkits von Sun und IBM im Vergleich

Text: von Daniel S. Haischt
  • Teilen
  • kommentieren
  • empfehlen
  • Bookmark and Share
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.

JWSDP WSTK
JAXP kompatibel (Xerces) (Xerces)
SOAP Version 1.1 1.1
SOAP Implementierung JAXM/JAX-RPC Apache Axis
WSDL Version 1.0 1.0
WSDL Implementierung nicht bekannt WSDL4J
UDDI Client Version 2.0 2.0
UDDI Client Implementierung JAXR UDDI4J
UDDI Server Implementierung (basierend auf Apache Xindice) (im WebSphere SDK for Web Services enthalten)
Laufzeitumgebung Tomcat 4.x Tomcat 4.x, IBM WebSphere SDK for Web Services Application Server oder WebSphere
Web Service-Aufruf mittels Web Services Invocation Framework (WSIF) - ja
Deployment-Tool (grafisch/textbasiert) (textbasiert)
Hot Deployment ja ja
Remote Deployment ja nicht bekannt
UDDI Registry Browser ja -
Zielplattformen Windows/Linux Windows/Linux
Dokumentation sehr umfangreich sehr umfangreich
 
 
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 Abpictureungen 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.
JWSDP WSTK
Web Service-Implementierung Aufteilung in Interface und implementierende Klasse Normale Java Klasse
Erstellen der WSDL-Beschreibung Von Hand oder automatisch mit dem enthaltenen grafischen Deployment-Tool Automatisch mittels beigefügtem Java2WSDL Tool
Deployment-Deskriptor In Form eines jaxrpc-ri.xml-Files, welches von Hand erstellt werden muss bzw. vom grafischen Deployment-Tool generiert wird. In Form eines service-config.wsdd-Files, das von Hand erstellt werden muss.
Deployment Erfolgt durch ein grafisches Deployment-Tool Erfolgt durch ein grafisches Deployment-Tool
 
 
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) abgepictureet. 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
  1. import java.util.Hashtable;
  2. public class Magazines
  3. {
  4. private Hashtable magazines = new Hashtable();
  5. public Magazines()
  6. {
  7. this.magazines.put("ENT", "29.50");
  8. this.magazines.put("DOT", "41.00");
  9. this.magazines.put("JAV", "52.50");
  10. this.magazines.put("LIN", "37.50");
  11. this.magazines.put("PHP", "52.00");
  12. this.magazines.put("XML", "52.00");
  13. }
  14. public String getPrice(String shortName)
  15. {
  16. return (String) this.magazines.get(shortName);
  17. }
  18. public static void main(String[] args)
  19. {
  20. String shortName = null;
  21. if (args.length == 0)
  22. {
  23. shortName = "ENT";
  24. }
  25. else
  26. {
  27. shortName = args[0];
  28. }
  29. System.out.println("Short name is: " + shortName);
  30. String result = (new Magazines()).getPrice(shortName);
  31. System.out.println("Result was: \n" + result);
  32. }
  33. }
Listing 2
  1. package catalogue;
  2. import java.rmi.Remote;
  3. import java.rmi.RemoteException;
  4. public interface MagazinesIF extends Remote
  5. {
  6. public String getPrice(String shortName) throws RemoteException;
  7. }
  8. package catalogue;
  9. import java.util.Hashtable;
  10. public class MagazinesImpl implements MagazinesIF
  11. {
  12. private Hashtable magazines = new Hashtable();
  13. public MagazinesImpl()
  14. {
  15. this.magazines.put("ENT", "29.50");
  16. this.magazines.put("DOT", "41.00");
  17. this.magazines.put("JAV", "52.50");
  18. this.magazines.put("LIN", "37.50");
  19. this.magazines.put("PHP", "52.00");
  20. this.magazines.put("XML", "52.00");
  21. }
  22. public String getPrice(String shortName)
  23. {
  24. return (String) this.magazines.get(shortName);
  25. }
  26. }
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
  1. import java.util.Vector;
  2. import java.net.URL;
  3. import javax.xml.namespace.QName;
  4. import com.ibm.wstk.WSTKConstants;
  5. import com.ibm.uddi4j.wsdl.client.UDDIWSDLProxy;
  6. import com.ibm.uddi4j.wsdl.definition.ServiceDefinition;
  7. import com.ibm.uddi4j.wsdl.provider.ServiceProvider;
  8. import org.apache.wsil.WSILDocument;
  9. import org.apache.wsil.client.WSILProxy;
  10. import org.apache.axis.encoding.ser.BeanDeserializerFactory;
  11. import org.apache.axis.encoding.ser.BeanSerializerFactory;
  12. import org.apache.axis.client.Service ;
  13. import org.apache.axis.client.Call;
  14. import org.uddi4j.datatype.Name;
  15. public class Client
  16. {
  17. private static final String M = "Magazines";
  18. private static final QName MqName =
  19. new QName("urn:Magazines-types", "String");
  20. public static void main(String[] args) throws Exception
  21. {
  22. if (args.length == 0)
  23. {
  24. System.out.println("Usage: java Client [short name of a magazine]");
  25. System.exit(0);
  26. }
  27. try
  28. {
  29. String shortName = args[0];
  30. String wsdlURL = null;
  31. wsdlURL = findUDDI(M + "Service");
  32. if (wsdlURL != null)
  33. {
  34. System.out.println(getPrice(wsdlURL, shortName));
  35. }
  36. else
  37. {
  38. System.out.println(
  39. "The Magazines Service could not be found");
  40. }
  41. }
  42. catch (Exception e)
  43. {
  44. e.printStackTrace();
  45. }
  46. }
  47. private static Object getPrice(String wsdlURL, String shortName) throws Exception
  48. {
  49. QName serviceM = new QName("http://" + M, M + "Service" );
  50. QName portM = new QName("http://" + M, "magazine");
  51. Service service = new Service(new URL(wsdlURL), serviceM );
  52. Call call = (Call)service.createCall(portM, "getPrice");
  53. call.registerTypeMapping(String.class,
  54. MqName,
  55. new BeanSerializerFactory(String.class, MqName),
  56. new BeanDeserializerFactory(String.class,MqName));
  57. return (String)call.invoke( new Object[] { shortName } );
  58. }
  59. public static String findUDDI(
  60. String service)
  61. throws Exception {
  62. try {
  63. UDDIWSDLProxy uwp =
  64. new UDDIWSDLProxy(WSTKConstants.UDDI_INQUIRY_URL,
  65. WSTKConstants.UDDI_PUBLISH_URL,
  66. WSTKConstants.UDDI_USERID,
  67. WSTKConstants.UDDI_CRED,
  68. WSTKConstants.TRANSPORT_CLASS);
  69. Vector providerNameVector = new Vector();
  70. providerNameVector.add(new Name("WSTK 3.2 Tutorial"));
  71. ServiceProvider[] sps =
  72. uwp.findAllServiceProviders(null, providerNameVector,
  73. null,null,null,null,true);
  74. if (sps.length > 0) {
  75. ServiceDefinition sd = sps[0].getServiceDefinition(service);
  76. return sd.getServiceImplementation().getWSDLFilename();
  77. } else {
  78. return null;
  79. }
  80. } catch (Exception e) {
  81. System.out.println(e.getMessage());
  82. System.exit(0);
  83. return null;
  84. }
  85. }
  86. }
Listing 4
  1. package catalogue;
  2. import javax.xml.rpc.Stub;
  3. public class Client
  4. {
  5. public static void main(String[] args)
  6. {
  7. try
  8. {
  9. Stub stub = createProxy();
  10. MagazinesIF magazines = (MagazinesIF)stub;
  11. System.out.println(magazines.getPrice(args[0]));
  12. }
  13. catch (Exception ex)
  14. {
  15. ex.printStackTrace();
  16. }
  17. }
  18. private static Stub createProxy()
  19. {
  20. // Note: MyMagazines_Impl is implementation-specific.
  21. return (Stub)(new MyMagazines_Impl().getMagazinesIFPort());
  22. }
  23. }
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
  1. <deployment
  2. xmlns="http://xml.apache.org/axis/wsdd/"
  3. xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
  4. name="test">
  5. <service name="magazin" provider="java:RPC">
  6. <parameter name="className" value="Magazines" />
  7. <parameter name="allowedMethods" value="getPrice" />
  8. </service>
  9. </deployment>
Listing 6
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <webServices
  3. xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd"
  4. version="1.0"
  5. targetNamespaceBase="http://com.test/wsdl"
  6. typeNamespaceBase="http://com.test/types"
  7. urlPatternBase="/ws">
  8. <endpoint
  9. name="MyMagazines"
  10. displayName="Magazines Service"
  11. description="A simple web service"
  12. interface="catalogue.MagazinesIF"
  13. implementation="catalogue.MagazinesImpl"/>
  14. <endpointMapping
  15. endpointName="MyMagazines"
  16. urlPattern="/magazines"/>
  17. </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 Abpictureung 3 dargestellt. In diesem Beispiel werden die Preise für Magazine wie zum Beispiel das Java Magazin (Kürzel JAV) abgerufen.
Fazit
Beiden Toolkits kann attestiert werden, dass sie den für einen Web Service notwendigen Entwicklungsprozess ausreichend abpictureen. 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 Abpictureung 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.

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

Kommentare