Het aanroepen van een SOAP-webservice in Java

1. Overzicht

In deze tutorial we zullen leren hoe we een SOAP-client in Java kunnen bouwen met JAX-WS RI. Eerst genereren we de klantcode met behulp van de wsimport utility en test het vervolgens met een JUnit.

Voor degenen die beginnen, biedt onze inleiding tot JAX-WS geweldige achtergrondinformatie over het onderwerp.

2. De webservice

Voordat we beginnen met het bouwen van een client, hebben we een server nodig. In dit geval stelt een server een JAX-WS-webservice bloot.

Voor deze tutorial gebruiken we een webservice die ons de gegevens van een land ophaalt, gegeven de naam.

2.1. Samenvatting van de implementatie

Omdat we ons richten op het bouwen van de klant, gaan we niet in op de implementatiedetails van onze service.

Laten we volstaan ​​om te zeggen dat een interface CountryService wordt gebruikt om de webservice aan de buitenwereld bloot te stellen. Om het simpel te houden, we bouwen en implementeren de webservice met behulp van de javax.xml.ws.Endpoint API in onze klas CountryServicePublisher.

We rennen CountryServicePublisher als een Java-applicatie om een ​​eindpunt te publiceren dat de inkomende verzoeken accepteert. Met andere woorden, dit wordt onze server.

Na het starten van de server, drukt u op de URL // localhost: 8888 / ws / country? wsdl geeft ons het bestand met de webdienstbeschrijving. De WSDL fungeert als een gids om het aanbod van de service te begrijpen en implementatiecode voor de klant te genereren.

2.2. De taal van de beschrijving van webservices

Laten we eens kijken naar de WSDL van onze webservice, land:

Dit is in een notendop de nuttige informatie die het biedt:

  • we kunnen de methode aanroepen findByName met een draad argument
  • in reactie daarop stuurt de service ons een aangepast type land
  • typen worden gedefinieerd in een xsd schema gegenereerd op de locatie // localhost: 8888 / ws / country? xsd = 1:

Dat is alles wat we nodig hebben om een ​​klant te implementeren.

Laten we eens kijken hoe in de volgende sectie.

3. Met behulp van wsimport om klantcode te genereren

3.1. Maven-plug-in

Laten we eerst een plug-in toevoegen aan ons pom.xml om deze tool te gebruiken via Maven:

 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 

Ten tweede, laten we deze plug-in uitvoeren:

mvn schoon jaxws: wsimport

Dat is alles! De bovenstaande opdracht genereert code in het opgegeven pakket com.baeldung.soap.ws.client.generated binnen in de sourceDestDir we hebben gezorgd voor de configuratie van de plug-in.

Een andere manier om hetzelfde te bereiken, is door de wsimport nut. Het komt uit de doos met de standaard JDK 8-distributie en is te vinden onder JAVA_HOME / bin directory.

Om klantcode te genereren met wsimport, kunnen we naar de root van het project navigeren en deze opdracht uitvoeren:

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

Het is belangrijk om in gedachten te houden dat het service-eindpunt beschikbaar moet zijn om de plug-in of het commando met succes uit te voeren.

Laten we vervolgens kijken naar de gegenereerde artefacten.

3.2. Gegenereerde POJO's

Gebaseerd op de xsd we eerder zagen, genereert de tool een bestand met de naam Land.java:

@XmlAccessorType (XmlAccessType.FIELD) @XmlType (naam = "land", propOrder = {"kapitaal", "valuta", "naam", "bevolking"}) openbare klasse Land {beschermd tekenreekshoofdstad; @XmlSchemaType (name = "string") beschermd Valuta valuta; beschermde tekenreeksnaam; beschermde int populatie; // standaard getters en setters}

Zoals we kunnen zien, is de gegenereerde klasse versierd met JAXB-annotaties voor het rangschikken en unmarshallen van het object van en naar XML.

Het genereert ook een Valuta opsomming:

@XmlType (name = "currency") @XmlEnum openbare opsomming Valuta {EUR, INR, USD; openbare tekenreekswaarde () {retournaam (); } openbare statische valuta fromValue (String v) {return valueOf (v); }}

3.3. CountryService

Het tweede gegenereerde artefact is een interface die fungeert als een proxy voor de eigenlijke webservice.

De interface CountryService verklaart dezelfde methode als onze server, findByName:

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

De interface is met name gemarkeerd als een javax.jws.WebService, met een SOAPBinding.Style als RPC zoals gedefinieerd door de WSDL van de service.

De methode findByName is geannoteerd om aan te geven dat het een javax.jws.WebMethod, met de verwachte typen invoer- en uitvoerparameters.

3.4. CountryServiceImplService

Onze volgende gegenereerde klas, CountryServiceImplService, strekt zich uit javax.xml.ws.Service. Zijn annotatie WebServiceClient geeft aan dat het de klantweergave van een dienst is:

@WebServiceClient (name = "CountryServiceImplService", targetNamespace = "//server.ws.soap.baeldung.com/", wsdlLocation = "// localhost: 8888 / ws / country? Wsdl") openbare klasse CountryServiceImplService breidt service uit {privé finale statische URL COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION; privé definitieve statische WebServiceException COUNTRYSERVICEIMPLSERVICE_EXCEPTION; privé definitieve statische QName COUNTRYSERVICEIMPLSERVICE_QNAME = nieuwe QName ("// server.ws.soap.baeldung.com/", "CountryServiceImplService"); statische {URL url = null; WebServiceException e = null; probeer {url = nieuwe URL ("// localhost: 8888 / ws / country? wsdl"); } catch (MalformedURLException ex) {e = nieuwe WebServiceException (ex); } COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION = url; COUNTRYSERVICEIMPLSERVICE_EXCEPTION = e; } openbare CountryServiceImplService () {super (__ getWsdlLocation (), COUNTRYSERVICEIMPLSERVICE_QNAME); } // andere constructeurs @WebEndpoint (naam = "CountryServiceImplPort") openbare CountryService getCountryServiceImplPort () {retourneren super.getPort (nieuwe QName ("// server.ws.soap.baeldung.com/", "CountryServiceImplPort"), CountryService. klasse); } privé statische URL __getWsdlLocation () {if (COUNTRYSERVICEIMPLSERVICE_EXCEPTION! = null) {gooi COUNTRYSERVICEIMPLSERVICE_EXCEPTION; } retourneer COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION; }}

De belangrijke methode om hier op te merken is getCountryServiceImplPort. Gegeven een gekwalificeerde naam van het service-eindpunt, of QName, en de naam van de interface van het service-eindpunt van de dynamische proxy, retourneert het een proxy-instantie.

Om de webservice aan te roepen, hebben we deze proxy nodig, zoals we binnenkort zullen zien.

Door een proxy te gebruiken, lijkt het alsof we een service lokaal aanroepen, waardoor de fijne kneepjes van het aanroepen op afstand worden weggenomen.

4. Testen van de klant

Vervolgens zullen we een JUnit-test schrijven om verbinding te maken met de webservice met behulp van de gegenereerde clientcode.

Voordat we dat kunnen doen, moeten we de proxy-instantie van de service aan de clientzijde krijgen:

@BeforeClass openbare statische ongeldige setup () {CountryServiceImplService-service = nieuwe CountryServiceImplService (); CountryService countryService = service.getCountryServiceImplPort (); }

Voor meer geavanceerde scenario's zoals het in- of uitschakelen van een WebServiceFeature, kunnen we andere gegenereerde constructors gebruiken voor CountryServiceImplService.

Laten we nu eens kijken naar enkele tests:

@Test openbare ongeldig gegevenCountryService_whenCountryIndia_thenCapitalIsNewDelhi () {assertEquals ("New Delhi", countryService.findByName ("India"). GetCapital ()); } @Test openbare ongeldig gegevenCountryService_whenCountryFrance_thenPopulationCorrect () {assertEquals (66710000, countryService.findByName ("Frankrijk"). GetPopulation ()); } @Test openbare ongeldige gegevenCountryService_whenCountryUSA_thenCurrencyUSD () {assertEquals (Currency.USD, countryService.findByName ("VS"). GetCurrency ()); } 

Zoals we kunnen zien, werd het aanroepen van de methoden van de service op afstand net zo eenvoudig als het lokaal aanroepen van methoden. De proxy's findByName methode retourneerde een Land instantie die overeenkomt met de naam wij hebben voorzien. Vervolgens hebben we verschillende getters van de POJO gebruikt om verwachte waarden te bevestigen.

5. Conclusie

In deze zelfstudie hebben we gezien hoe u een SOAP-webservice in Java aanroept met JAX-WS RI en het wsimport nut.

Als alternatief kunnen we andere JAX-WS-implementaties gebruiken, zoals Apache CXF, Apache Axis2 en Spring om hetzelfde te doen.

Zoals altijd is de broncode beschikbaar op GitHub.