Plus CD! Stellenmarkt 64 3.09 Liferay Enterprise Edition gives you all the benefits of open source with the stability, security, and reliability of an enterprise subscription. And with version 5.1, get the latest in SOA, Social Networking, and Collaboration technology, all at a fraction of the cost of Oracle ® or IBM ®. Liferay 5.1 Enterprise Edition Maintenance Subscription 2.950 EUR / server / year Platinum Support (24x7) 19.950 EUR / server / year Compare Oracle ® WebCenter Suite: 125.000 EUR / processor, support 27.500 EUR / yr, as of 6 / 2008 For more information, email us at [email protected]. EUROPEAN HEADQUARTERS - LANGEN, GERMANY LIFERAY GMBH — ROBERT - BOSCH - STRASSE 11, 63225 LANGEN, GERMANY TEL: +49 - (0) 6103 - 3018570 Ý FAX: +49 - (0) 6103 - 3018571 Initialisation-Safety-Garantie • IntelliJ IDEA 8 • Services auf deklarative Weise • Überwachung von JEE-Applikationen bei 1&1 • Batch Proocessing 2.0 • Querfeld Seam Now get the best of both worlds. Deutschland € 7,50 Java Magazin Java Magazin 3.2009 You spoke. We listened. Introducing Liferay Enterprise Edition. Batch Processing 2.0 Java • Architekturen • SOA • Agile 67 Österreich € 8,60 Schweiz sFr 15,80 www.javamagazin.de CD-Inhalt Java-Frameworks • JBoss Seam 2.1.1 GA • Meta Programming Systems PERFORMANCE Tools • Trang • XDoclet Web • Apache Maven 2.0.9 • Maven License Plug-in • Dozer 4.4 • SoapUI 2.5 • JAX-WS 2.1.5 FIRST Jonas Jacobi: Re-architecting the Web with HTML 5 Communication Außerdem eine Auswahl der Apache-MyFaces-Projekte Alle CD-Infos 3 Core Java-Memory-Modell Initialisation-Safety-Garantie 42 Dynamische Services OSGi in kleinen Dosen – Teil 4 16 Web Querfeld Seam Sicherheit und Testbarkeit 50 Enterprise Überwachung von JEE-Applikationen bei 1&1 Mit MonSched D 45 86 7 78 Handeln bevor es zu spät ist: Performance in verteilten Systemen Tools 101 72 Das Tutorial Neu: IntelliJ IDEA 8 Web Services Welche Neuerungen bietet die Hauptversion in Bezug auf Maven, Subversion und Groovy/Grails? Außerdem: Ein Überblick zur erweiterten Produktstrategie mit RubyMine. Das neue Tutorial zeigt Schritt für Schritt den Weg zu einer Web-ServiceImplementierung – mittels Maven und Jax-WS. 107 Web Services Das Tutorial Web Services: Auf die Plätze, fertig, los! Der Weg zu einer Web-Service-Implementierung ist häufig mit vielen Hindernissen gespickt. Wie können diese Probleme gemeistert werden? Das folgende Tutorial zeigt Schritt für Schritt ein pragmatisches Vorgehen mittels Maven und JAX-WS. von Ralf Ebert und Gunnar Morling teht man vor der Aufgabe, einen Web Service bereitzustellen, sind zunächst einige Grundsatzentscheidungen zu treffen. So muss festgelegt werden, auf welche Weise der Schnittstellenkontrakt für den Service beschrieben werden soll. Ein möglicher Ansatz hierzu ist das so genannte Code-First-Vorgehen, bei dem der Kontrakt aus einem bestehenden Interface abgeleitet wird. Für unser Beispielprojekt möchten wir jedoch den Kontrakt explizit ausformulieren. Ei- Vorteile von Contract-First Bei der Entwicklung von Web Services nach dem ContractFirst-Ansatz wird zunächst der Schnittstellenkontrakt in der plattformneutralen Sprache WSDL beschrieben. Die in der Schnittstelle genutzten Typen werden dazu mit einer XMLSchema-Sprache wie XSD definiert. Daraus kann im zweiten Schritt ein Codegerüst generiert werden, das mit Leben gefüllt wird, indem etwa die Geschäftslogik aufgerufen wird. Diese Herangehensweise bietet einige Vorteile: Der Schnittstellenkontrakt ist explizit und unabhängig von der Implementierungssprache formuliert. Ein Wechsel oder Upgrade des Web Service Stacks kann keine ungewollten Änderungen an der Schnittstelle auslösen. Denn abweichend von Code-First wird die Schnittstelle definiert und nicht von einem Generator erzeugt. Es ist möglich, Schnittstellen vor- und rückwärtskompatibel weiter zu entwickeln. So können Nachrichtentypen um optionale Elemente ergänzt werden, wobei die Kompatibilität zu bestehenden Clients gewahrt bleibt. www.JAXenter.de nige Vorteile dieser als „Contract First“ bezeichneten Herangehensweise finden Sie im Kasten „Vorteile von Contract-First“. Weiterhin muss man sich für ein Web-Service-Framework entscheiden, das Service Requests entgegennimmt, an die Implementierung weiterleitet und schließlich entsprechende Response-Nachrichten an den Aufrufer übermittelt. Hierzu gibt es viele konkurrierende Technologien. Wir werden im Folgenden mit JAX-WS (Java API for XML Web Services [1]) arbeiten. Dies ist das API der Java-EE-Plattform für die Implementierung von Web Services. Es kann aber auch separat eingesetzt werden und ist seit Java 6 Teil des Standard-JDK. Wir werden die Referenzimplementierung (RI) verwenden, die aktuell in Version 2.1.5 vorliegt. Schließlich benötigen wir für unser Projekt ein BuildWerkzeug. Hierfür eignet sich hervorragend Apache Maven. Maven definiert eine Standardstruktur für Java-Projekte, lädt automatisch alle benötigten Bibliotheken herunter und erlaubt eine individuelle Anpassung des Build-Prozesses mittels Plug-ins. So werden wir bestehende und ein eigenes Plug-in zur Codegenerierung für Web Services nutzen und uns so viel manuelle Schreibarbeit ersparen. Design der Schnittstelle Der erste Schritt bei der Erstellung eines Web Service ist das Design des Schnittstellenkontrakts. Idealerweise kommen dazu Vertreter aller beteiligten Systeme zusammen. Zunächst sollten gemeinsam die Operationen, die der Web Service anbieten soll, herausgearbeitet werden. Als Beispiel wird im Folgenden ein javamagazin 3|2009 107 Tool auf CD Das Tutorial Web Services einfacher Service für Produktabfragen realisiert. Es soll möglich sein, Produktinformationen anhand einer Artikelnummer abzurufen (getProductById) sowie anhand vorgegebener Kriterien nach Produkten zu suchen (findProducts). Im XML Schema definieren wir für jede Operation einen Ein- und Ausgabetypen. Hat man über diese noch keine Klarheit, empfiehlt es sich, mit Beispielnachrichten in XML zu beginnen, z. B.: <GetProductByIdRequest> <Id>123</Id> </GetProductByIdRequest> <GetProductByIdResponse> <Product> Anlegen eines neuen Maven-Projekts <Id>123</Id> <Name>Jeans-Hose</Name> <Price>89.99</Price> <Size>L</Size> </Product> </GetProductByIdResponse> Ausgehend von diesem Beispiel ist es nun recht einfach, ein entsprechendes Schema abzuleiten. Dabei kann man sich von Tools wie Trang [2] unterstützen lassen, die aus einem vorhandenen Listing 1: Das XML Schema products.xsd <?xml version=“1.0“ encoding=“UTF-8“?> <schema targetNamespace=“http://www.javamagazin.de/ mvnjaxws/products/types“ xmlns=“http://www.w3.org/2001/XMLSchema“ xmlns:products=“http://www.javamagazin.de/mvnjaxws/ products/types“> <!-- GetProductById --> <element name=“GetProductByIdRequest“> <complexType> <sequence> <element name=“Id“ type=“int“ /> </sequence> </complexType> </element> <element name=“GetProductByIdResponse“> <complexType> <sequence> <element type=“products:Product“ name=“Product“ minOccurs=“0“ /> </sequence> </complexType> </element> <!-- FindProducts --> <element name=“FindProductsRequest“> <complexType> <sequence> <element name=“MaxResults“ type=“int“ /> <element name=“SearchText“ type=“string“ /> </sequence> </complexType> </element> <element name=“FindProductsResponse“> 108 javamagazin 3|2009 XML-Dokument ein Schema erzeugen, das meist nur noch etwas nachbearbeitet werden muss. In unserem Beispiel wurde das Schema gemäß Listing 1 verabschiedet. Die komplexen Einund Ausgabetypen sind jeweils in ein Element verpackt und haben nur Unterelemente, aber keine Attribute. Schemaseitig sind damit die Voraussetzungen für den so genannten Document/ Literal-Stil für Web-Service-Schnittstellen gegeben, der eine hohe Interoperabilität derselben gewährleistet sowie eine Schemavalidierung der Request- und Response-Nachrichten erlaubt. Aus dem deklarierten Target Namespace wird beim Generieren der Package-Name für die Java-Binding-Klassen abgeleitet – im Beispiel de.javamagazin.mvnjaxws.products.types. Auf Grundlage des Schemas kann es nun an die Umsetzung des Web Service gehen. Hierzu legen wir zunächst ein neues Maven-Projekt an. Sofern Sie Maven noch nicht installiert haben, finden Sie unter [3] oder auf der beigefügten Heft-CD die Installationsdatei und -anleitung. Maven erleichtert die Erstellung neuer Projekte durch Projektvorlagen (Archetypen). Zur Erstellung eines Web-Service-Projekts können wir mit folgendem Maven-Aufruf den von den Autoren bereitgestellten Archetypen instantws-archetype nutzen: <complexType> <sequence> <element minOccurs=“0“ maxOccurs=“unbounded“ type=“products:Product“ name=“Products“ /> </sequence> </complexType> </element> <!-- Common types --> <complexType name=“Product“> <sequence> <element name=“Id“ type=“int“ /> <element name=“Name“ type=“string“ /> <element name=“Price“ type=“decimal“ /> <element name=“Size“ type=“string“ minOccurs=“0“ /> </sequence> </complexType> </schema> Listing 2: Web-ServiceImplementierung ProductsPort.java @WebService(endpointInterface = “de.javamagazin. mvnjaxws.products.ProductsPortType“) public class ProductsPort implements ProductsPortType { private Map<Integer, Product> sampleProducts = new TreeMap< Integer, Product>(); public ProductsPort() { Product product = new Product(); product.setId(1); product.setName(“Jeans-Hose“); product.setPrice(new BigDecimal(“89.99“)); product.setSize(“L“); sampleProducts.put(product.getId(), product); // ... } public GetProductByIdResponse getProductById (GetProductByIdRequest request) { GetProductByIdResponse response = new GetProductByIdResponse(); response.setProduct(sampleProducts.get (request.getId())); return response; } public FindProductsResponse findProducts (FindProductsRequest request) { // ... } } Listing 3: Deployment-Deskriptor sun-jaxws.xml <?xml version=“1.0“ encoding=“UTF-8“?> <endpoints xmlns=“http://java.sun.com/xml/ns/jax-ws/ ri/runtime“ version=“2.0“> <endpoint implementation=“de.javamagazin.mvnjaxws. products.ProductsPort“ name=“Products“ url-pattern=“/Products“ wsdl=“WEB-INF/wsdl/products.wsdl“ service=“{http://www.javamagazin.de/mvnjaxws/ products}ProductsService“ port=“{http://www.javamagazin.de/mvnjaxws/ products}ProductsPort“ /> </endpoints> www.JAXenter.de mvn archetype:generate -DarchetypeCatalog= http://maven-instant-ws.googlecode.com/ svn/repo/archetype-catalog.xml Nach dem Download der von Maven benötigten Bibliotheken müssen wir noch einige zur Projektanlage erforderliche Angaben machen: Zu nutzender Archetyp: instantws-archetype groupId: Name der Firma oder Organisation artifactId: Bezeichner für das Projekt, z. B. jaxws-test version: Versionsnummer, standardmäßig 1.0-SNAPSHOT package: Top-Level-Package für die Klassen des Projekts In dem neu erstellten Projekt finden wir gemäß der vorgegebenen Maven-Projektstruktur folgende Pfade: pom.xml: Maven-Projektdefinition mit allen Einstellungen und Abhängigkeiten des Projekts src/main/java: Java-Klassen der Anwendung src/main/resources: Ressourcen, die von der Anwendung zur Laufzeit benötigt werden src/test/java: JUnit-Test-Klassen src/webapp: Deployment-Deskriptoren für den Webcontainer Das Projekt kann nun, wie im Kasten „Maven-Projekte in Eclipse und NetBeans“ beschrieben, in der IDE eingerichtet werden. Um den Web Service zu erstellen, legen wir das Schema mit den Typdefinitionen unter /src/main/resources/xsd/products.xsd ab. Zu einer vollständigen Web-Service-Definition gehört neben dem XML Schema noch ein WSDL-Dokument, das die Operationen des Service beschreibt. Dieses könnten wir von Hand erstellen, allerdings ist das WSDL-Format recht komplex und wenig intuitiv. Befolgt man bei der Benennung der Nachrichtentypen wie im Beispiel eine feste Konvention, ist es möglich, die WSDL-Datei aus dem XML Schema abzuleiten. Aus dem Vorhandensein der Elemente FindProductsRequest und FindProductsResponse etwa kann die Operation FindProducts abgeleitet und im WSDL-Dokument angelegt werden. Für die Verwendung im Beispielprojekt wurde durch die Autoren ein Maven-Plug-in entwickelt, das die WSDLGenerierung auf die beschriebene Weise nahtlos in den Build-Prozess integriert. Mittels des Befehls mvn clean generate-resources können wir nun den Maven-Build bis zum Build- Maven-Projekte in Eclipse und NetBeans Für Eclipse lässt sich mit mvn eclipse:eclipse eine Projektkonfiguration erzeugen. Optional können durch Angabe der Parameter -DdownloadSources=true -DdownloadJavadocs=true die Quellen und JavaDocs der referenzierten Bibliotheken heruntergeladen und eingebunden werden. Nachdem Sie unter Window | Preferences | Java | Build Path | Classpath Variables die Variable M2_REPO auf Ihr lokales Maven-Repository (z. B. /home/<nutzername>/.m2/repository) konfiguriert haben, können Sie das Projekt mit File | Import | General | Existing Projects into Workspace importieren. Alternativ besteht die Möglichkeit, mit dem Plug-in M2Eclipse [6] das Maven-Projekt direkt zu öffnen und Maven-Goals wie z. B. generate-resources aus der IDE heraus zu starten. Auch für NetBeans steht ein Plug-in zur Unterstützung von Maven-Projekten bereit. Dieses kann mittels des Plug-in-Managers unter Tools | Plugins installiert werden. Anschließend können Maven-Projekte wie normale NetBeans-Projekte geöffnet werden. IDEAktionen wie Build oder Test führen einen entsprechenden Maven-Build aus, während im Kontextmenü unter Custom | Goals... beliebige Maven-Goals aufgerufen werden können. Mit dem Repository-Browser können diverse Maven-Repositories nach Bibliotheken durchsucht und diese als Abhängigkeit zum Projekt hinzugefügt werden. Weitere Hinweise zum Umgang mit Maven-Projekten in NetBeans finden Sie unter [7]. www.JAXenter.de Anzeige Das Tutorial Web Services Schema-Typen, wobei JAXB als XML-Binding-Technologie zum Einsatz kommt. Damit haben wir das Grundgerüst für den Service erstellt. Wir implementieren diesen nun, indem wir die Klasse de.javamagazin.mvnjaxws.products.ProductsPort in src/main/ java erstellen. Zu Testzwecken geben wir in der Implementierung zunächst nur Beispieldaten zurück. Damit die Klasse als Web-Service-Endpunkt anerkannt wird, müssen wir sie mit der Annotation @WebService versehen (Listing 2). Über das Attribut endpointInterface stellt JAX-WS den Bezug zu dem generierten Endpunktinterface ProductsPortType her. Obwohl nicht erforderlich, implementieren wir das Interface zusätzlich, um z. B. fehlerhafte Methodensignaturen – etwa, weil wir eine Operation umbenannt haben – bereits zur Compile-Zeit zu erkennen. Publizieren des Service Abb. 1: Request und Response des Products-Services in soapUI Schritt generate-resources ausführen. Die im pom.xml des Projekts deklarierten Plug-ins erzeugen dabei die benötigten Artefakte: Das Maven WSDL Builder Plug-in [4] erzeugt auf oben beschriebene Weise aus dem XML Schema products.xsd die WSDL-Definition products.wsdl. Das JAX-WS Maven Plug-in [5] erzeugt anhand dieser WSDL ein Serviceinterface sowie Binding-Klassen für die Listing 4: Implementierung eines LogicalHandler Auf dem Weg zu unserem ersten Contract-First-Web-Service mit JAX-WS sind nun schon die größten Hürden genommen. Der Service muss nur noch dem JAX-WS-Framework bekannt gemacht werden. Das Vorgehen hierzu unterscheidet sich abhängig von der genutzten JAX-WS-Implementierung sowie dem Deployment-Szenario. Für das Beispiel nutzen wir die JAXWS-Referenzimplementierung in einem reinen Servlet-Container und müssen den Service daher in der Konfigurationsdatei /src/main/webapp/WEB-INF/sun-jaxws.xml bekanntmachen (Listing 3). Zusätzlich ist im Deployment-Deskriptor web.xml das Servlet com.sun.xml.ws.transport.http.servlet.WSServlet zu re- boolean isOutbound = (Boolean) public void close(MessageContext context) { lmc.get(MessageContext.MESSAGE_OUTBOUND_ // nothing to do here PROPERTY); public class RequestCountHandler implements } LogicalHandler< LogicalMessageContext> { // inbound handler invocation public boolean handleFault if (!isOutbound) { private static ConcurrentMap<String, AtomicInteger> requestCounts = new .ConcurrentHashMap<String, (LogicalMessageContext context) { // nothing to do here DOMResult requestDOM = new DOMResult(); AtomicInteger>(); return false; } Transformer transformer = TransformerFactory. private static void incrementCount(String requestName) { newInstance().newTransformer(); } transformer.transform(lmc.getMessage(). AtomicInteger count = requestCounts.putIfAbsent getPayload(), requestDOM); (requestName, new AtomicInteger()); String requestName = requestDOM.getNode(). if (count == null) getFirstChild().getNodeName(); count = requestCounts.get(requestName); Listing 5: WSDL-Customization zur Deklaration einer Handler-Chain <?xml version=“1.0“ encoding=“UTF-8“?> <jaxws:bindings xmlns:jaxws=“http://java.sun.com/xml/ns/jaxws“ RequestCountHandler. count.incrementAndGet(); xmlns:javaee=“http://java.sun.com/xml/ns/javaee“> incrementCount(requestName); <javaee:handler-chains> } <javaee:handler-chain> System.out.println(requestCounts); } <javaee:handler> } catch (Exception e) { public boolean handleMessage( e.printStackTrace(); LogicalMessageContext lmc) { } try { return true; } 110 javamagazin 3|2009 <javaee:handler-class>de.javamagazin.mvnjaxws. RequestCountHandler</javaee:handler-class> </javaee:handler> </javaee:handler-chain> </javaee:handler-chains> </jaxws:bindings> www.JAXenter.de Web Services Das Tutorial gistrieren. Im Beispielprojekt wurde dies bereits vom MavenArchetyp erledigt, alle Aufrufe werden automatisch an JAXWS RI delegiert. In einem Applikationsserver wie GlassFish, der JAX-WS RI bereits von Haus aus enthält, sind beide Deskriptoren nicht erforderlich; vielmehr sind die Informationen zu Servicename und WSDL-Pfad etc. direkt in der @WebService-Annotation anzugeben, woraufhin beim Deployment alle entsprechend annotierten Endpunkte publiziert werden. Zum Testen können wir nun per mvn clean jetty:run-war den Servlet-Container Jetty starten und anschließend den Web Service unter http://localhost:8080/<Projektname>/Products erreichen. Ein Aufruf dieses URL in einem Webbrowser zeigt eine Übersichtsseite aller deployten Web Services. Zum Testen des Service kann z. B. soapUI [8] verwendet werden, das eine grafische Oberfläche für Web-Service-Aufrufe bereitstellt (Abb. 1). Nachrichtenvalidierung Durch das XML Schema ist der Aufbau der Request- und Response-Nachrichten exakt festgelegt. So ist es etwa möglich, den Wertebereich von Attributen oder die Kardinalität von Kollektionen einzuschränken. Vor allem während der Entwicklung kann eine Schemavalidierung aller Nachrichten hilfreich sein, um fehlerhafte Client-Requests, aber auch nicht schemakonforme Antworten der Serviceimplementierung zu identifizieren. Unter JAX-WS RI wird die Nachrichtenvalidie- rung aktiviert, indem die Annotation @SchemaValidation an der Endpunktklasse angegeben wird: @WebService(...) @SchemaValidation public class ProductsPort implements ProductsPortType { //... } Senden Clients nun Aufrufe, die nicht dem zugrunde liegenden Schema genügen oder wird durch die Serviceimplementierung eine invalide Antwort zurückgegeben, erzeugt das Framework einen SOAP-Fault, der die Schemaverletzung beschreibt. Ist darüber hinaus eine spezifische Fehlerbehandlungslogik erforderlich, kann in der Annotation eine Ableitung der Klasse com.sun.xml.ws.developer.ValidationErrorHandler angegeben werden, die bei Schemaverletzungen aufgerufen wird: @SchemaValidation(handler=MyValidationHandler.class) Handler-Chains Häufig ist wiederkehrende Logik wie das Loggen der ein- und ausgehenden Nachrichten oder die Auswertung von HeaderElementen in mehreren oder allen Web-Service-Operationen einer Anwendung durchzuführen. Ähnlich zum Servlet- Anzeige www.JAXenter.de javamagazin 3|2009 111 Das Tutorial Web Services Filter-Konzept erlaubt JAX-WS die redundanzfreie Realisierung solcher Querschnittsaufgaben mittels so genannter Handler-Chains. Auf diese Weise ist es möglich, beim JAXWS-Framework Handler zu registrieren, die vor und nach der Ausführung einer Web-Service-Operation aufgerufen werden und dabei die übermittelten Nachrichten inspizieren oder auch verändern können. Listing 4 zeigt einen BeispielHandler, der die Aufrufe aller Web-Service-Operationen zählt: Hierzu wurde das Interface LogicalHandler implementiert. Die Methode handleMessage() wird vor und nach jeder Operation aufgerufen, für die der Handler registriert ist. Soll aus einem Handler heraus nicht nur auf die Nutzlast einer SOAP-Nachricht, sondern auch auf ihren Header zugegriffen werden, ist statt LogicalHandler das Interface SOAPHandler zu implementieren. Der Handler muss nun noch beim JAX-WS-Framework registriert werden. Dies kann durch Annotation der Endpunktklasse mit @HandlerChain, im oben beschriebenen Deskriptor sun-jaxws.xml oder über eine so genannte WSDLCustomization erfolgen. Letzteres erlaubt auch die Definition serviceübergreifender Handler. Listing 5 zeigt beispielhaft eine solche Customization-Datei, die wir unter src/main/webapp/ WEB-INF/jaxws/wsdl-customization.xml ablegen. Beim Generierungsprozess wird diese ausgewertet und die generierten Serviceinterfaces mit der darin spezifizierten Handler-Chain verknüpft. Schnittstellen belohnt. Der Einsatz von JAX-WS und Maven ermöglicht rasche Erfolgserlebnisse. Auch weitergehende Anforderungen wie Nachrichtenvalidierung und die Erstellung von Message-Handlern sind auf dieser Grundlage unkompliziert umzusetzen. Ralf Ebert ist freiberuflicher Softwareentwickler und Trainer. Er entwickelt seit 7 Jahren vor allem grafische Benutzeroberflächen für Enterprise-Systeme und berät seine Kunden bei der Umsetzung von Anwendungen in diesem Bereich. Seine Erfahrungen aus zahlreichen Projekten gibt er auch als Trainer und Coach für Eclipse-Technologien weiter. Kontakt: www.ralfebert.de. Gunnar Morling arbeitet als Softwareentwickler bei der Saxonia Systems AG in Dresden und verfügt über mehrjährige Erfahrungen bei der Realisierung von Java-Enterprise-Anwendungen. Zu seinen Interessensschwerpunkten zählen das Konfigurationsmanagement mittels Maven sowie die Automatisierung von Integrationstests. Links & Literatur [1] JAX-WS: https://jax-ws.dev.java.net [2] Trang: thaiopensource.com/relaxng/trang.html [3] Apache Maven Download und Installationsanleitung: maven.apache.org/download.html [4] Maven WSDL Builder Plug-in: code.google.com/p/maveninstant-ws/ [5] JAX-WS Maven Plug-in: https://jax-ws-commons.dev.java. net/jaxws-maven-plugin/ Fazit Die Erstellung Contract-First-basierter Web Services wirkt auf viele Entwickler noch immer abschreckend – vor allem aufgrund des recht sperrigen Formats WSDL. Dass dem nicht so sein muss, hat der vorliegende Artikel gezeigt. Mit den richtigen Werkzeugen ist Contract-First nur geringfügig aufwändiger als der Code-First-Ansatz, der Entwickler wird aber mit robusten und interoperablen Web-Service- [6] M2Eclipse: m2eclipse.codehaus.org [7] NetBeans Wiki: Maven Best Practices: wiki.netbeans.org/ MavenBestPractices [8] soapUI: www.soapui.org [9] JAX-WS API Version Mess with Maven: weblogs.java.net/ blog/ramapulavarthi/archive/2008/10/jaxws_api_versi. html Stolpersteine Verschiedene Versionen von JAX-WS RI im Repository: Sollten Sie beim Starten des Projekts die Fehlermeldung Caused by: java.lang.NoClassDefFoundError: javax/jws/WebService erhalten, liegt die Ursache vermutlich in einem Konflikt verschiedener Versionen von JAX-WS RI in Ihrem Maven-Repository [9]. Der einfachste Workaround ist, das lokale Maven-Repository zu löschen. Leider müssen dann alle abhängigen Bibliotheken Ihrer Maven-Projekte neu heruntergeladen werden. Unvollständige @WebServiceAnnotationen: JAX-WS RI hat die etwas eigenwillige Angewohnheit, bei unvollständigen oder fehlerhaften Angaben in @WebServiceAnnotationen in den Code-First-Modus 112 javamagazin 3|2009 zu wechseln und automatisch WSDL/ XSD-Dokumente anhand der JavaSchnittstellen zu generieren. Sie sollten die Konsolenausgaben beim Start Ihrer Anwendung beobachten. Sind dabei Ausschriften wie der Projektanlage angegebene Archetypkatalog nicht gefunden wird. Befindet sich eine solche fehlerhafte Version in Ihrem lokalen Repository, führt dies zu folgender Fehlermeldung: [WARNING] Error reading archetype catalog INFO: Dynamically creating request wrapper Class http://maven-instant-ws.googlecode.com/svn/ [...] 18.10.2008 15:48:52 repo/archetype-catalog.xml com.sun.xml.ws.model. WrapperBeanGenerator createBeanImage zu sehen, sollten Sie die Angaben Ihrer @WebService-Annotationen auf Korrektheit überprüfen. Veraltete Version des MavenArchetype-Plug-ins: Dem kann begegnet werden, indem im lokalen Repository der Ordner org/apache/maven/plugins/maven-archetypeplugin und damit das Archetype-Plug-in gelöscht wird. Daraufhin wird dieses neu heruntergeladen und auch der Archetypkatalog gefunden. Ein Bug im Maven-Archetype-Plug-in führt unter Umständen dazu, dass der bei www.JAXenter.de