performance - Google Sites

Werbung
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
Herunterladen