Aufrufen eines SOAP-Webdienstes in Java

1. Übersicht

In diesem Tutorial erfahren Sie, wie Sie mit JAX-WS RI einen SOAP-Client in Java erstellen . Zuerst generieren wir den Client-Code mit dem Dienstprogramm wsimport und testen ihn dann mit einer JUnit.

Für Anfänger bietet unsere Einführung in JAX-WS großartige Hintergrundinformationen zu diesem Thema.

2. Der Webdienst

Bevor wir mit dem Erstellen eines Clients beginnen, benötigen wir einen Server. In diesem Fall stellt ein Server einen JAX-WS-Webdienst bereit.

Für dieses Tutorial verwenden wir einen Webdienst, der uns die Daten eines Landes unter seinem Namen abruft.

2.1. Zusammenfassung der Implementierung

Da wir uns auf den Aufbau des Kunden konzentrieren, werden wir nicht auf die Implementierungsdetails unseres Service eingehen.

Es genügt zu sagen, dass eine Schnittstelle CountryService verwendet wird, um den Webdienst der Außenwelt zugänglich zu machen. Zur Vereinfachung erstellen und implementieren wir den Webdienst mithilfe der API javax.xml.ws.Endpoint in unserer Klasse CountryServicePublisher .

Wir führen CountryServicePublisher als Java-Anwendung aus, um einen Endpunkt zu veröffentlichen, der die eingehenden Anforderungen akzeptiert. Mit anderen Worten, dies wird unser Server sein.

Wenn Sie nach dem Starten des Servers die URL // localhost: 8888 / ws / country? Wsdl eingeben , erhalten Sie die Webdienstbeschreibungsdatei. Die WSDL dient als Leitfaden, um die Angebote des Dienstes zu verstehen und Implementierungscode für den Client zu generieren.

2.2. Die Web Services-Beschreibungssprache

Schauen wir uns unsere Web - Service WSDL, Land :


    

Kurz gesagt, dies sind die nützlichen Informationen, die es bietet:

  • Wir können die Methode findByName mit einem String- Argument aufrufen
  • Als Antwort sendet uns der Service einen benutzerdefinierten Landestyp zurück
  • Typen werden in einem xsd- Schema definiert, das am Speicherort // localhost: 8888 / ws / country? xsd = 1 : generiert wird.

    

Das ist alles, was wir brauchen, um einen Client zu implementieren.

Mal sehen wie im nächsten Abschnitt.

3. Verwenden von wsimport zum Generieren von Clientcode

3.1. Maven Plugin

Fügen wir zunächst ein Plugin zu unserer pom.xml hinzu , um dieses Tool über Maven zu verwenden:

 org.codehaus.mojo jaxws-maven-plugin 2.6   wsimport-from-jdk  wsimport      //localhost:8888/ws/country?wsdl  true com.baeldung.soap.ws.client.generated src/main/java  

Zweitens lassen Sie uns dieses Plugin ausführen:

mvn clean jaxws:wsimport

Das ist alles! Der obige Befehl generiert Code im angegebenen Paket com.baeldung.soap.ws.client.generated in dem sourceDestDir, das wir in der Plugin-Konfiguration bereitgestellt haben.

Eine andere Möglichkeit, dies zu erreichen, wäre die Verwendung des Dienstprogramms wsimport . Es wird mit der Standard-JDK 8-Distribution ausgeliefert und befindet sich im Verzeichnis JAVA_HOME / bin .

Um Client-Code mit wsimport zu generieren , können wir zum Stammverzeichnis des Projekts navigieren und diesen Befehl ausführen:

JAVA_HOME/bin/wsimport -s src/main/java/ -keep -p com.baeldung.soap.ws.client.generated "//localhost:8888/ws/country?wsdl"

Es ist wichtig zu beachten, dass der Service-Endpunkt verfügbar sein sollte, um das Plugin oder den Befehl erfolgreich ausführen zu können.

Schauen wir uns als nächstes die generierten Artefakte an.

3.2. Generierte POJOs

Basierend auf dem zuvor gesehenen xsd generiert das Tool eine Datei mit dem Namen Country.java :

@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "country", propOrder = { "capital", "currency", "name", "population" }) public class Country { protected String capital; @XmlSchemaType(name = "string") protected Currency currency; protected String name; protected int population; // standard getters and setters }

Wie wir sehen können, ist die generierte Klasse mit JAXB-Annotationen zum Marshalling und Unmarshalling des Objekts zu und von XML dekoriert.

Außerdem wird eine Währungsaufzählung generiert :

@XmlType(name = "currency") @XmlEnum public enum Currency { EUR, INR, USD; public String value() { return name(); } public static Currency fromValue(String v) { return valueOf(v); } }

3.3. CountryService

Das zweite generierte Artefakt ist eine Schnittstelle, die als Proxy für den eigentlichen Webdienst fungiert.

Die Schnittstelle CountryService deklariert dieselbe Methode wie unser Server findByName :

@WebService(name = "CountryService", targetNamespace = "//server.ws.soap.baeldung.com/") @SOAPBinding(style = SOAPBinding.Style.RPC) @XmlSeeAlso({ ObjectFactory.class }) public interface CountryService { @WebMethod @WebResult(partName = "return") @Action(input = "//server.ws.soap.baeldung.com/CountryService/findByNameRequest", output = "//server.ws.soap.baeldung.com/CountryService/findByNameResponse") public Country findByName(@WebParam(name = "arg0", partName = "arg0") String arg0); }

Insbesondere ist die Schnittstelle als javax.jws.WebService markiert , mit einem SOAPBinding.Style als RPC, wie in der WSDL des Dienstes definiert.

Die Methode findByName wird mit Anmerkungen versehen, um zu deklarieren, dass es sich um eine javax.jws.WebMethod mit den erwarteten Eingabe- und Ausgabeparametertypen handelt.

3.4. CountryServiceImplService

Unsere nächste generierte Klasse, CountryServiceImplService , erweitert javax.xml.ws.Service. Die Anmerkung WebServiceClient gibt an, dass es sich um die Clientansicht eines Dienstes handelt:

@WebServiceClient(name = "CountryServiceImplService", targetNamespace = "//server.ws.soap.baeldung.com/", wsdlLocation = "//localhost:8888/ws/country?wsdl") public class CountryServiceImplService extends Service { private final static URL COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION; private final static WebServiceException COUNTRYSERVICEIMPLSERVICE_EXCEPTION; private final static QName COUNTRYSERVICEIMPLSERVICE_QNAME = new QName("//server.ws.soap.baeldung.com/", "CountryServiceImplService"); static { URL url = null; WebServiceException e = null; try { url = new URL("//localhost:8888/ws/country?wsdl"); } catch (MalformedURLException ex) { e = new WebServiceException(ex); } COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION = url; COUNTRYSERVICEIMPLSERVICE_EXCEPTION = e; } public CountryServiceImplService() { super(__getWsdlLocation(), COUNTRYSERVICEIMPLSERVICE_QNAME); } // other constructors @WebEndpoint(name = "CountryServiceImplPort") public CountryService getCountryServiceImplPort() { return super.getPort(new QName("//server.ws.soap.baeldung.com/", "CountryServiceImplPort"), CountryService.class); } private static URL __getWsdlLocation() { if (COUNTRYSERVICEIMPLSERVICE_EXCEPTION != null) { throw COUNTRYSERVICEIMPLSERVICE_EXCEPTION; } return COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION; } }

Die wichtige Methode, die hier zu beachten ist, ist getCountryServiceImplPort . Wenn ein qualifizierter Name des Service-Endpunkts oder QName und der Name der Service-Endpunkt-Schnittstelle des dynamischen Proxys angegeben werden, wird eine Proxy-Instanz zurückgegeben.

Um den Webdienst aufzurufen, müssen wir diesen Proxy verwenden, wie wir in Kürze sehen werden .

Using a proxy makes it seem as if we are calling a service locally, abstracting away the intricacies of remote invocation.

4. Testing the Client

Next, we'll write a JUnit test to connect to the web service using the generated client code.

Before we can do that, we need to get the service's proxy instance at the client end:

@BeforeClass public static void setup() { CountryServiceImplService service = new CountryServiceImplService(); CountryService countryService = service.getCountryServiceImplPort(); }

For more advanced scenarios such as enabling or disabling a WebServiceFeature, we can use other generated constructors for CountryServiceImplService.

Now let's look at some tests:

@Test public void givenCountryService_whenCountryIndia_thenCapitalIsNewDelhi() { assertEquals("New Delhi", countryService.findByName("India").getCapital()); } @Test public void givenCountryService_whenCountryFrance_thenPopulationCorrect() { assertEquals(66710000, countryService.findByName("France").getPopulation()); } @Test public void givenCountryService_whenCountryUSA_thenCurrencyUSD() { assertEquals(Currency.USD, countryService.findByName("USA").getCurrency()); } 

Wie wir sehen können, war das Aufrufen der Methoden des Remotedienstes so einfach wie das lokale Aufrufen von Methoden. Die findByName- Methode des Proxys hat eine Country- Instanz zurückgegeben, die dem von uns angegebenen Namen entspricht . Dann haben wir verschiedene Getter des POJO verwendet, um erwartete Werte zu bestätigen.

5. Schlussfolgerung

In diesem Tutorial haben wir gesehen, wie ein SOAP-Webdienst in Java mit JAX-WS RI und dem Dienstprogramm wsimport aufgerufen wird.

Alternativ können wir andere JAX-WS-Implementierungen wie Apache CXF, Apache Axis2 und Spring verwenden, um dasselbe zu tun.

Wie immer ist der Quellcode über GitHub verfügbar.