Webservices mit Java EE 6: JAX-WS und RESTful Services
Seite 3: Fazit
Webservices der höchsten Stufe
Wie nicht anders zu erwarten sind JAX-WS und JAX-RS direkt in Java EE integriert, sodass innerhalb einer "Java EE"-Laufzeitumgebung SOAP-Endpoints und RESTful Resources am Lebenszyklus-Management einer Enterprise-Java-Anwendung teilhaben und via Dependency Injection auf "Java EE"-Ressourcen zugreifen können. Dabei schreiben die beiden Standards vor, dass die Annotationen @PostConstruct und @PreDestroy sowie @ManagedBean, @EJB, @Resource und @Inject zu unterstützen sind. Der Integration in eine klassische Enterprise-Java-Anwendung steht damit nichts im Wege.
JAX-WS-Webservices lassen sich dabei als normale Dienste im Web- oder aber als Dienste im EJB-Container installieren. Aus einem Dienst der Web- wird einer der EJB-Schicht durch das Markieren des Webservices als (Stateless) Session Bean. Seit Java EE 6 können JAX-WS-Webservices auch Stateful Session Beans sein, sodass man in Verbindung mit WS-Addressing statusbehaftete JAX-WS-Webservices realisieren kann. Der oben vorgestellte Warenkorb lässt sich somit leicht zu einem statusbehafteten Webservice umstellen:
@Stateful @WebService @Addressing
public class StatefulShoppingCart implements ShoppingCart {
private String identifier;
private List<CartItem> items = new ArrayList<CartItem>();
public static StatefulWebServiceManager<ShoppingCart> manager;
public StatefulShoppingCart(String identifier) {
this.identifier = identifier;
}
@WebMethod
public void addItem(Item item, int quantity) {...}
}
Für das Ressourcen-Management muss ein statusbehafteter JAX-WS-Webservice eine Referenz zu einem StatefulWebServiceManager aufnehmen können, was entweder über ein öffentliches statisches Feld oder aber über eine öffentliche statische Setter-Methode erfolgen kann.
Die Zugriff auf eine konkrete Warenkorb-Instanz erfolgt dann über einen weiteren JAX-WS-Webservice, der Warenkörbe als W3CEndpointReference unter Nutzung des StatefulWebServiceManager bereitstellt. Der gleiche lässt sich auch nutzen, einen nicht mehr benötigten Stateful-Service wieder freizugeben.
@WebService
public class MyShop implements Shop {
@WebMethod
public W3CEndpointReference createCart(String identifier) {
StatefulShoppingCart cart = new StatefulShoppingCart(identifier);
return cart.manager.export(cart);
}
}
Analog zu JAX-WS-Diensten können Entwickler JAX-RS-Ressourcen als Dienst der Web- oder als Dienst der EJB-Schicht veröffentlichen, wobei hier nur @Stateless Session Beans zum Einsatz kommen können. Zusätzlich ermöglicht JAX-RS über die @Context Annotation den Zugriff auf Ressourcen des Web-Containers, insbesondere auf den ServletContext sowie den aktuellen HttpServletRequest und die aktuelle HttpServletResponse.
Da normale Web-Container wie Tomcat oder Jetty keine direkte Unterstützung von JAX-WS oder JAX-RS bieten, ist zur Installation derartiger Dienste noch eine JAX-WS- oder JAX-RS-Laufzeitumgebung einzurichten. Hierzu lassen sich die oben genannten einschlägigen Webservice-Frameworks verwenden.
Fazit
Von vielen unbemerkt hat JAX-WS 2.0 die "Java EE 5"-Plattform um einen SOAP-Webservice-Standard ergänzt, der die Übersetzung formaler WSDL-Schnittstellenbeschreibungen nach Java und umgekehrt standardisiert. Dadurch ist mit dem seit Java EE 5 verbreiteten Architekturansatz der einfachen Klassen, Interfaces und Metadaten (Annotationen) eine leistungsfähige Basis für SOAP-Webservices entstanden, die bei korrekter Implementierung der JAX-WS API zu Webservices führt, die zwischen Applikationsservern und Webservice-Frameworks portabel sind. Als Anbieter von Java-Webservices sind nur die für den Service relevanten Klassen auszuliefern, damit eine mit JAX-WS 2.0+ oder Java EE 5+ kompatible Laufzeitumgebung die Dienste bereitstellen oder konsumieren kann. Java EE 6 konnte nicht mehr viel ergänzen, sodass der Nachfolger JAX-WS 2.1 mit Ausnahme von WS-Addressing im Wesentlichen nur kleine Lücken schloss beziehungsweise Unschärfen in der Spezifikation ausräumte.
Leider definiert der Standard auch mit Java EE 6 nicht, mit welchem konkreten Aufruf eine JAX-WS-Implementierung aus einer WSDL den serverseitigen JAX-WS-Rahmen oder aber einen JAX-WS-Client generiert. Weiterhin ist man auf eine ausreichend gute Dokumentation der JAX-WS-Implementierung angewiesen, was sich in der Praxis leider immer noch als große Hürde herausstellt.
Auch wenn sich mit JAX-WS relativ einfach Webservices nach dem Code-first-Prinzip realisieren lassen, die formal und inhaltlich einen interoperablen SOAP-Webservice darstellen, sei an der Stelle darauf hingewiesen, dass Contract-first-Webservices in der Regel deutlich schneller und nachhaltiger das gleiche Ziel erreichen. Einzige Voraussetzung hierzu sind Erfahrungen im Umgang mit XML Schema.
Es bleibt zu hoffen, dass mit JAX-RS nicht der Fehler, der mit SOAP-Webservices passiert ist, erneut wiederholt wurde. Denn deutlich überfällig hielten erst mit Java EE 6 RESTful-Services Einzug in Java EE. Zugegebenermaßen ist die JAX-RS API wirklich gelungen, sodass praktisch alle Java-Webservice-Frameworks zur Unterstützung von RESTful-Services auf JAX-RS setzen. Nicht die schlechteste Voraussetzung für eine breite Akzeptanz der API.
Dadurch befindet sich Java EE auf Augenhöhe mit allen relevanten Entwicklungen am Markt, auch wenn der Weg dahin erneut etwas steinig war.
Jens Schumann
ist CTO des IT-Beratungs- und Entwicklungsunternehmens open knowledge GmbH und beschäftigt sich seit der Java Servlet API mit dem Entwurf und der Realisierung von Enterprise-Java-Anwendungen – mit und ohne Java EE.
Literatur
- Andreas Holubek, Oliver Heuser; Zusammenspiel; Webservices-Interoperabilität - WS-Policies in der Praxis, Artikel auf heise Developer
(ane)