Web Services mit Spring-WS – Teil 3

Spring-WS und Spring Security

Thorsten Kamann

Ihr Client ist fast vollständig implementiert. Es fehlt nur noch eine Main-Methode, damit der Client ausgeführt werden kann:

public static void main(String[] args){
 ProductServiceClientJAXB client = new ProductServiceClientJAXB ();
 client.getProducts();
}

Der Client lässt sich nun kompilieren und ausführen. Allerdings kommt es sehr schnell zu einer NullPointerException. Das WebServiceTemplate ist noch nicht initialisiert worden. Wir müssen den Client noch etwas erweitern, damit Spring das Template injizieren kann. Zusätzlich müssen wir dem Client noch mitteilen, welchen Marshaller er verwenden soll (Listing 6).

Listing 6

Dieses kleine Stück Konfiguration enthält viele Finessen. Der Component Scan (<context:component-scan/>) scannt alle Klassen in dem angegebenen Package nach von Spring-unterstützten Annotations. Findet er welche, werden diese Annotations analysiert und der Spring-Kontext aufgebaut. Die Spring Bean mit der ID productWSTemplate konfiguriert das Web Service Template. Der URI des Web Service wird konfiguriert und der Marshaller und Unmarshaller werden injiziert. Um diese Konfiguration in verschiedenen Umgebungen verwenden zu können, sind die serverspezifischen Angaben, wie Host, Port und Kontextpfad in eine separate Properties-Datei ausgelagert. Schlussendlich wird noch der Marshaller konfiguriert. Der angegebene Jaxb2Marshaller enthält sowohl die Methoden für das Marshalling als auch für das Unmarshalling.

Damit die automatische Verdrahtung der Spring-Komponenten funktioniert, müssen wir den Client mit zwei Annotations erweitern:

@Component
public class ProductServiceClientJAXB {

 @Autowired
 private WebServiceTemplate wsTemplate;

 .
}

Die @Component-Annotation markiert die Klasse als Spring Bean. Damit das WebServiceTemplate injiziert wird, verwenden wir hier die @Autowired-Annotation. Spring sucht sich dadurch selbstständig die passende Bean, um sie zu injizieren. Beim Start des Clients in der Main-Methode muss Spring initialisiert werden. Das ist allerdings auch schnell erledigt (Listing 7).

Listing 7
public static void main(String[] args{
 ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
    "META-INF/spring/spring-ws-client-jaxb-context.xml");

 ProductServiceClientJAXB client = (ProductServiceClientJAXB)   
   applicationContext.getBean("productServiceClientJAXB");
 client.getProducts();
}

Die Spring-Konfiguration wird mit ClassPathXMLApplicationContext eingelesen und erzeugt einen ApplicationContext. Aus diesem Kontext bekommen wir eine Instanz unseres eigenen Clients, den wir mit der @Component-Annotation zu einer Spring Bean gemacht haben. Der Client wird den Request wie geplant ausführen und die Response zurückliefern. Damit Sie kontrollieren können, ob die Daten korrekt zurückgeliefert werden, können Sie wieder das generierte Java-API verwenden:

for (Product product : client.getProducts()) {
 System.out.println(product.getId() + "::" + product.getName()
   + "::" + product.getCategory().getName()+"::"
   +product.getSupplier().getName());
}

Jetzt haben Sie den Client vollständig implementiert. Der meiste Aufwand ist die Konfiguration des Requests, der allerdings einfach von der Hand geht, da ein Java-API verwendet wird.

Testen von Web Services

Spring ist ein Framework, das sich das Testen von Anwendungen mit auf die Fahne geschrieben hat. Das ist bei Spring-WS auch nicht anders. Allerdings sind Web Services sehr schwer zu testen, da sie auf einem Server deployt werden müssen. Um dieses Problem zu umgehen, gibt es das Projekt SpringWS Test [5]. Mit diesem Testframework können Sie Ihren Web Service testen, ohne ihn auf einen Server deployen zu müssen. Dies wird mit einem Mock-Objekt realisiert, das vorgibt, der auf einen Server deployte Server zu sein. Der Mock übernimmt die Verarbeitung des Requests, gibt die Daten allerdings an die reale Web-Service-Implementierung weiter. Spring-WS Test unterstützt sowohl Unit-, als auch funktionale Tests.

Im Bereich Integrationstests können Sie die Kombination Maven [6], Cargo [7] und WebServiceTemplate für Ihre Tests verwenden. Das Cargo-Plug-in für Maven erlaubt es, das WAR-Archiv mit dem Web Service auf einen Tomcat (oder anderen Container) zu deployen und dann Tests laufen zu lassen. Nach Beendigung der Tests wird die Webanwendung mit dem Web Service wieder undeployt und der Container optional heruntergefahren. Die Implementierung des Tests kann mit jUnit oder TestNG [8] realisiert werden. Mit dem WebServiceTemplate kann mit wenig Code ein Request erzeugt und die Response auf Korrektheit überprüft werden.

Absicherung von Web Services

SpringWS unterstützt natürlich auch die verschiedenen Aspekte der WS-Security [9]:

  • Authentifizierung
  • Digitale Signaturen
  • Verschlüsselung

Die Authentifizierung ist mittels EndpointInterceptor realisiert. Spring-WS bietet 2 davon an:

  • XwsSecurityInterceptor
  • Wss4jSecurityInterceptor

Der XwsSecurityInterceptor basiert auf Suns XML and Web Services Security Package (XWSS [10]). Dieser Interceptor benötigt mindestens Java 5 und Suns SAAJ [12] Referenzimplementierung. Der Wss4jSecurityInterceptor hingegen basiert auf Apaches WSS4J [11].

Konfiguration des Wss4jSecurityInterceptor

Dieser Interceptor kommt im Gegensatz zu dem XwsSecurityInterceptor ohne externe Konfiguration aus. Eine Spring-Konfiguration reicht aus:

Die beiden Actions (validateActions und securementActions) können verschiedene Einstellungen haben. Für die validateActions können Sie wählen unter:

  • UsernameToken validiert das Username-Token
  • Timestamp validiert den Timestamp
  • Encrypt verschlüsst
  • Signature validiert die Signatur
  • NoSecurity bewirkt, dass keine Aktion durchgeführt wird
Geschrieben von
Thorsten Kamann
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.