Es wird heiß

Web Services leicht gemacht mit XFire
Kommentare

Viele Unternehmen sind gerade dabei, Kernfunktionen ihrer Systeme über Web-Service-Schnittstellen zur Verfügung zu stellen. Das Apache Axis-Projekt war eines der ersten erfolgreichen Frameworks in diesem Bereich. Axis ist vom Umfang und der Funktionalität her sehr mächtig, in manchen Bereichen jedoch zu umfangreich und umständlich. Mit XFire gibt es einen Weg, ohne viel Aufwand Services einer Anwendung als Web Services zur Verfügung zu stellen.

XFire ist ein relativ junges Open-Source-SOAP-Framework und steht derzeit in der Version 1.2.2 auf der Website zum Download zur Verfügung. Das Team von XFire hat sich zum Ziel gemacht, ein einfaches und schnelles SOAP-Framework für Entwickler anzubieten. Ich werde zu Beginn erklären, wie XFire in einer simplen Anwendung ohne Container (Spring) verwendet werden kann. Abschließend werde ich auf die Integration in das Spring Framework eingehen und demonstrieren, wie in Spring verwaltete Komponenten als Web Service exportiert werden können. (Wissenswertes zur Spring-Axis-Kombination finden Sie im Java Magazin 6.2006 [Thilo Frotscher: Frühlingsgefühle für Axis. Lose gekoppelte Anwendungen mit Axis und Spring].) Als begleitendes Beispiel wird ein einfacher Kundenservice verwendet, welcher grundlegende Datenbank-Operationen für Kunden anbietet. Das Service wird als POJO implementiert (Listing 1) und bildet auch die Grundlage für den Web Service. Wichtig ist der Default-Konstruktor bei CustomerServiceImpl. Diesen benötigt XFire für die Instanziierung.

Listing 1: Einfacher Kundenservice
------------------------------------------------------------------------
package at.demolsky.customer.service;

//Interface
public interface ICustomerService {
  public void saveCustomer ( Customer customer );
  public String getState(String id);
  public void deleteCustomer ( Customer customer );
  public Customer loadCustomer ( String id );
  public List loadAllCustomers ();
}

//Implementierung
public CustomerServiceImpl implements ICustomerService {
  private CustomerDAO customerDAO;

  public CustomerServiceImpl(){
  }

  public void saveCustomer(Customer customer){
    //some work
    customerDAO.saveCustomer(customer);
  }

  public String getState(String id){
    return customerDAO.getState(id);
  }
  //other services
}
Einrichtung von XFire ohne Container

Wir betrachten zuerst einmal die grundlegende Einrichtung von XFire in einer Webanwendung. Bei XFire handelt es sich um eine Servlet-basierte Applikation, sie muss daher entsprechend im Webkontext (web.xml) eingerichtet werden (Listing 2).

Listing 2: XFire Servlet in der web.xml
------------------------------------------------------------------
XFireServletXFire Servlet
     org.codehaus.xfire.transport.http.XfireConfigurableServlet
  XFireServlet/services/*

Das XfireConfigurableServlet wird durch die Konfigurationsdatei services.xml, welche sich im Verzeichnis WEB-INF/META-INF/xfire befindet, konfiguriert. Diese Datei enthält alle Services, die XFire als Web Services zur Verfügung stellen soll (Listing 3). Die Definition unseres Web Service befindet sich innerhalb des -Konstruktes. Der muss ein gültiger XML-Name sein und definiert den Namen unseres Service. Dieser Name wird von den Client-Programmen und anderen Komponenten benötigt, um diesen Service zu lokalisieren. Der wird für die eindeutige Identifizierung von Parametern im Service benötigt. Schließlich definiert die das Interface, also die Methodensignatur, und die die entsprechende Implementierung des Interfaces.

Listing 3: services.xml
-----------------------------------------------------------------------
Customerdemolskyat.demolsky.customer.ICustomerService
      at.demolsky.customer.ICustomerServiceImpl
    

Gratulation! Der Web Service ist fertig. Und alles war eine Sache der Konfiguration. Es waren keine Ant-Skripts ausführen, um eine WSDL zu erzeugen, oder Ähnliches. Jetzt nur noch den Web-Container starten und die WSDL des Service wie folgt aufrufen: http://localhost:8080/einContext/services/Customer?wsdl. Dies ist auch gleich ein Test, ob der Service korrekt exportiert wurde. Customer entspricht dem Servicenamen, welcher in der service.xml als deklariert wurde. Die in Listing 3 angeführte service.xml-Datei stellt den einfachsten Fall einer Servicekonfiguration dar. In dieser Konfigurationsdatei können wesentlich mehr Einstellungen vorgenommen werden. So besteht unter anderem auch die Möglichkeit, benutzerdefinierte Handlers (Requests, Responses, Faults), Invokers oder Executors in das Service einzubringen. Für die Handlers, Invokers und Executors stellt der Benutzer passende Implementierungen zur Verfügung und registriert diese in der service.xml-Datei.

Wird nur das XFire Servlet angesprochen (http://localhost:8080/springRemote/services), so liefert das Servlet eine nette Übersicht über alle registrierten Services. Dies kann hilfreich sein, wenn mehr als ein Service von XFire verwaltet wird.

Binding

Das Binding ist eines der wesentlichsten Konzepte bei der Arbeit mit Web Services. Es definiert, wie sowohl eingehende als auch ausgehende XML-Daten auf Java-Objekte abgebildet werden. XFire bietet hierfür eine Art Plug-in an, um unterschiedliche Bindings verwenden zu können. Dazu zählen unter anderem XMLBeans, JAXB oder Castor. Für das Binding von POJOs stellt XFire das Aegis Binding (Default XFire Binding) zur Verfügung, auf das wir uns im Rahmen dieses Artikels beschränken. Diese Art von Binding ist ein einfaches und flexibles Mapping-System und unterstützt alle gängigen Typen, wie int, double, java.util.Date und einige andere mehr. In vielen Fällen ist es notwendig, das Mapping zwischen Java-Objekten und XML zu kontrollieren. Da noch immer viele Systeme nicht auf Java 5 umgestellt sind, müssen zum Beispiel Collections manuell gemappt werden. Java 5 verwendet hierfür bereits Generics, welche eine Typsicherung in der Collection garantieren.

Betrachten wir als Beispiel unsere Methoden loadCustomer und loadAllCustomers aus Listing 1. Die erste Methode liefert ein Domänenobjekt Customer. Dieser Typ wird von Aegis in einen komplexen Typ (XSD) umgewandelt. Dieser Typ enthält alle Attribute des Domänenobjektes, wie id, name etc. Angenommen, wir verwenden nicht Generics, dann muss – wie bereits erwähnt – definiert werden, welche Art von Objekten sich in der Collection befindet:

Diese Mapping-Definitionen müssen in MeinService.aegis.xml-Dateien abgelegt werden, wobei MeinService durch das Interface ersetzt werden muss: ICustomerService.aegis.xml. Es ist wichtig, dass der Name der Mapping-Datei mit dem des Interface übereinstimmt und nicht mit deren Implementierung. Sonst könnte es sein, dass XFire beim Start einen Fehler liefert. Für jeden Service existiert eine eigene Datei, welche sich auch im gleichen Package wie das Service befindet. XFire stellt auch passende Aegis Annotations zur Verfügung, mit denen die Mappings direkt im Code definiert werden können. Somit erspart man sich die Datei. Ein Aufruf der WSDL zeigt, ob das Binding korrekt definiert wurde, andernfalls kommt eine passende Fehlermeldung von XFire.

Neben dem Collection Mapping ist es oft notwendig, die Rückgabewerte von Methoden, Attributnamen oder Parametern zu mappen. Auch für diese Sachverhalte stellt das Aegis Binding Ansätze zur Verfügung.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -