Een SOAP-webservice maken met Spring

1. Overzicht

In deze zelfstudie zullen we zien hoe u een SOAP-gebaseerde webservice met Spring Boot Starter Web Services.

2. SOAP-webservices

Een webservice is, kort gezegd, een machine-to-machine, platformonafhankelijke service die communicatie via een netwerk mogelijk maakt.

SOAP is een berichtenprotocol. Berichten (verzoeken en reacties) zijn XML-documenten via HTTP. Het XML-contract wordt bepaald door de WSDL (Web Services Description Language). Het biedt een set regels om de berichten, bindingen, bewerkingen en locatie van de service te definiëren.

De XML die in SOAP wordt gebruikt, kan extreem complex worden. Om deze reden is het het beste om SOAP te gebruiken met een framework zoals JAX-WS of Spring, zoals we in deze tutorial zullen zien.

3. Contract-eerste ontwikkelstijl

Er zijn twee mogelijke benaderingen bij het maken van een webservice: Contract-Last en Contract-First. Wanneer we een contract-last-benadering gebruiken, beginnen we met de Java-code en genereren we het webservicecontract (WSDL) vanuit de klassen. Bij gebruik van contract-first, we beginnen met het WSDL-contract, waaruit we de Java-klassen genereren.

Spring-WS ondersteunt alleen de contract-first ontwikkelstijl.

4. Opzetten van het Spring Boot Project

We gaan een Spring Boot-project maken waarin we onze SOAP WS-server definiëren.

4.1. Afhankelijkheden van Maven

Laten we beginnen met het toevoegen van de spring-boot-starter-parent naar ons project:

 org.springframework.boot spring-boot-starter-parent 2.2.6.RELEASE 

Laten we vervolgens het spring-boot-starter-web-services en wsdl4j afhankelijkheden:

 org.springframework.boot spring-boot-starter-web-services wsdl4j wsdl4j 

4.2. Het XSD-bestand

De contract-first-benadering vereist dat we eerst het domein (methoden en parameters) voor onze service creëren. We gaan een XML-schemabestand (XSD) gebruiken dat Spring-WS automatisch exporteert als een WSDL:

In dit bestand zien we het formaat van het getCountryRequest webserviceverzoek. We definiëren het om één parameter van het type te accepteren draad.

Vervolgens definiëren we het formaat van het antwoord, dat een object van het type bevat land.

Eindelijk zien we de valuta object, gebruikt binnen het land voorwerp.

4.3. Genereer de domein Java-klassen

We gaan nu de Java-klassen genereren uit het XSD-bestand dat in de vorige sectie is gedefinieerd. De jaxb2-maven-plugin zal dit automatisch doen tijdens de bouwtijd. De plug-in gebruikt de XJC-tool als engine voor het genereren van codes. XJC compileert het XSD-schemabestand in volledig geannoteerde Java-klassen.

Laten we de plug-in toevoegen en configureren in onze pom.xml:

 org.codehaus.mojo jaxb2-maven-plugin 1.6 xjc xjc $ {project.basedir} / src / main / resources / $ {project.basedir} / src / main / java false 

Hier merken we twee belangrijke configuraties op:

  • $ {project.basedir} / src / main / resources - De locatie van het XSD-bestand
  • $ {project.basedir} / src / main / java - Waar we willen dat onze Java-code wordt gegenereerd

Om de Java-klassen te genereren, kunnen we eenvoudig de xjc-tool uit onze Java-installatie gebruiken. Hoewel in ons Maven-project de dingen zelfs nog eenvoudiger zijn, zoals de lessen worden automatisch gegenereerd tijdens de gebruikelijke Maven-build:

mvn compileren

4.4. Voeg het SOAP-webservice-eindpunt toe

De SOAP-webservice-eindpuntklasse zal alle inkomende verzoeken voor de service afhandelen. Het start de verwerking en stuurt het antwoord terug.

Voordat we dit definiëren, maken we een Land repository om gegevens aan de webservice te verstrekken.

@Component openbare klasse CountryRepository {privé statische definitieve kaartlanden = nieuwe HashMap (); @PostConstruct public void initData () {// initialiseer de kaart van landen} public Country findCountry (String naam) {return landen.get (naam); }} 

Laten we vervolgens het eindpunt configureren:

@Endpoint openbare klasse CountryEndpoint {privé statische laatste String NAMESPACE_URI = "//www.baeldung.com/springsoap/gen"; privé CountryRepository countryRepository; @Autowired openbaar CountryEndpoint (CountryRepository countryRepository) {this.countryRepository = countryRepository; } @PayloadRoot (namespace = NAMESPACE_URI, localPart = "getCountryRequest") @ResponsePayload openbaar GetCountryResponse getCountry (@RequestPayload GetCountryRequest-verzoek) {GetCountryResponse response = nieuwe GetCountryResponse (); response.setCountry (countryRepository.findCountry (request.getName ())); antwoord teruggeven; }} 

Hier zijn een paar details om op te merken:

  • @Eindpunt - registreert de klasse bij Spring WS als een webservice-eindpunt
  • @PayloadRootdefinieert de handlermethode volgens de naamruimte en localPart attributen
  • @ResponsePayload - geeft aan dat deze methode een waarde retourneert die moet worden toegewezen aan de responspayload
  • @RequestPayload - geeft aan dat deze methode een parameter accepteert die moet worden toegewezen vanuit het inkomende verzoek

4.5. De SOAP-webservice Configuratiebonen

Laten we nu een klasse maken voor het configureren van de Spring Message Dispatcher-servlet om het verzoek te ontvangen:

@EnableWs @Configuration openbare klasse WebServiceConfig breidt WsConfigurerAdapter {// bean-definities} uit

@EnableWs schakelt SOAP-webservicefuncties in deze Spring Boot-applicatie in. De WebServiceConfig klasse breidt de WsConfigurerAdapter basisklasse, die het annotatiegestuurde Spring-WS-programmeermodel configureert.

Laten we een MessageDispatcherServlet die wordt gebruikt voor het afhandelen van SOAP-verzoeken:

@Bean openbare ServletRegistrationBean messageDispatcherServlet (ApplicationContext applicationContext) {MessageDispatcherServlet-servlet = nieuwe MessageDispatcherServlet (); servlet.setApplicationContext (applicationContext); servlet.setTransformWsdlLocations (true); retourneer nieuwe ServletRegistrationBean (servlet, "/ ws / *"); } 

We zetten de geïnjecteerde ApplicationContext object van de servlet zodat Spring-WS andere Spring-bonen kan vinden.

We maken ook de transformatie van de WSDL-locatieservlet mogelijk. Dit transformeert het locatiekenmerk van zeep: adres in de WSDL zodat het de URL van het inkomende verzoek weerspiegelt.

Laten we tot slot een DefaultWsdl11Definition voorwerp. Dit toont een standaard WSDL 1.1 met behulp van een XsdSchema. De WSDL-naam is hetzelfde als de bean-naam.

@Bean (naam = "landen") openbaar DefaultWsdl11Definition defaultWsdl11Definition (XsdSchema-landenchema) {DefaultWsdl11Definition wsdl11Definition = nieuwe DefaultWsdl11Definition (); wsdl11Definition.setPortTypeName ("Landenpoort"); wsdl11Definition.setLocationUri ("/ ws"); wsdl11Definition.setTargetNamespace ("// www.baeldung.com/springsoap/gen"); wsdl11Definition.setSchema (landenSchema); retourneer wsdl11Definition; } @Bean openbare XsdSchema landenSchema () {retourneer nieuwe SimpleXsdSchema (nieuwe ClassPathResource ("landen.xsd")); } 

5. Testen van het SOAP-project

Zodra de projectconfiguratie is voltooid, zijn we klaar om deze te testen.

5.1. Bouw en voer het project uit

Het zou mogelijk zijn om een ​​WAR-bestand te maken en dit op een externe applicatieserver te implementeren. We zullen in plaats daarvan Spring Boot gebruiken, wat een snellere en gemakkelijkere manier is om de applicatie aan de praat te krijgen.

Eerst voegen we de volgende klasse toe om de applicatie uitvoerbaar te maken:

@SpringBootApplication openbare klasse Toepassing {openbare statische leegte hoofd (String [] args) {SpringApplication.run (Application.class, args); }} 

Merk op dat we geen XML-bestanden (zoals web.xml) gebruiken om deze applicatie te maken. Het is allemaal pure Java.

Nu zijn we klaar om de applicatie te bouwen en uit te voeren:

mvn spring-boot: run

Om te controleren of de applicatie correct werkt, kunnen we de WSDL openen via de URL: //localhost:8080/ws/countries.wsdl

5.2. Test een SOAP-verzoek

Om een ​​verzoek te testen, maken we het volgende bestand en noemen het request.xml:

    Spanje 

Om het verzoek naar onze testserver te sturen, kunnen we externe tools gebruiken zoals SoapUI of de Google Chrome-extensie Wizdler. Een andere manier is om het volgende commando in onze shell uit te voeren:

curl --header "content-type: text / xml" -d @ request.xml // localhost: 8080 / ws

Het resulterende antwoord is misschien niet gemakkelijk te lezen zonder inspringing of regeleinden.

Om het opgemaakt te zien, kunnen we het kopiëren en plakken naar onze IDE of een andere tool. Als we xmllib2 hebben geïnstalleerd, kunnen we de uitvoer van onze curl-opdracht naar xmllint:

curl [opdrachtregelopties] | xmllint --format -

Het antwoord moet informatie over Spanje bevatten:

     Spanje 46704314 Madrid EUR 

6. Conclusie

In dit artikel hebben we geleerd hoe u een SOAP-webservice kunt maken met Spring Boot. We hebben ook geleerd hoe we Java-code kunnen genereren uit een XSD-bestand en we hebben gezien hoe we de Spring Beans moeten configureren die nodig zijn om de SOAP-verzoeken te verwerken.

De volledige broncode is beschikbaar op GitHub.