Produzieren und Konsumieren von SOAP-Webdiensten mit Spring Boot – Teil V
In diesem Beitrag beschreiben wir, wie Sie einen SOAP-Webservice aus unserer vorhandenen Spring Boot-REST-API erstellen. In den letzten Beiträgen haben wir Folgendes behandelt
- Spring Boot REST CRUD API – Teil I
- Swagger-Dokumentation für die Spring Boot-REST-API – Teil II
- Fehlerbehandlung und -protokollierung in der Spring Boot-REST-API – Teil III
- Nutzung des RESTful-Webdienstes – Teil IV
Dieser SOAP-Webservice stellt uns Benutzerdaten aus der Datenbank zur Verfügung, die wir über Spring-data in Spring REST API verbunden haben.
1. Anforderungen
- Eclipse Mars2
- Maven 3.1 und höher
- Spring 1.4 und höher
- Java 7
- Tomcat 8
2. SOAP-Webdienst
Wir werden unsere vorhandene Spring Boot-REST-API verwenden, um eine Anwendung zu erstellen, die als SOAP-Webdienst fungiert, um Benutzerdaten bereitzustellen. Für eine bestimmte Benutzer-ID gibt der Webdienst Benutzerdaten zurück.
Lassen Sie uns eine Schemadatei in src/main/resources
erstellen Verzeichnis und Maven erstellt Java-Klassen basierend auf dieser Schemadatei.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="https://betterjavacode.com/benefits/soap" targetNamespace="https://betterjavacode.com/benefits/soap" elementFormDefault="qualified">
<xs:element name="getUserRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getUserResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="user" type="tns:user"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="user">
<xs:sequence>
<xs:element name="id" type="xs:int"/>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="middlename" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
<xs:element name="username" type="xs:string"/>
<xs:element name="createdate" type="xs:date"/>
<xs:element name="jobtitle" type="xs:string"/>
<xs:element name="email" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
3. Aktualisieren Sie die Maven-Abhängigkeiten
Um jetzt Klassen aus dem Schema zu generieren, müssen wir sicherstellen, dass wir alle richtigen Abhängigkeiten in unserem pom.xml
haben . Wir werden auch eine Spring-Boot-Dienstabhängigkeit hinzufügen, um einen SOAP-Webdienst zu erstellen.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.betterjavacode</groupId>
<artifactId>Benefits</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Benefits Maven Webapp</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>${project.basedir}/src/main/resources/</schemaDirectory>
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<clearOutputDir>false</clearOutputDir>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>com.betterjavacode.benefits.soap</generatePackage>
<forceRegenerate>true</forceRegenerate>
<scehmas>
<schema>
<url>http://localhost:8080/benefits/endpoints/users.wsdl</url>
</schema>
</scehmas>
</configuration>
</plugin>
</plugins>
<finalName>Benefits</finalName>
</build>
</project>
Wenn wir das Projekt jetzt mit Maven Build ausführen, generiert das Plugin jaxb2-maven-plugin Klassen unter com.betterjavacode.benefits.soap
Verzeichnis. Es wird auch unsere WSDL-SOAP-URL für Benutzer aktivieren. Dadurch werden folgende Java-Objekte generiert
GetUserRequest
GetUserResponse
ObjectFactory
package-info
User
4. Dienst definieren
Als Nächstes definieren wir eine Schnittstelle für unseren Dienst. Dies sieht wie folgt aus
package com.betterjavacode.benefits.services;
public interface UserAccountService
{
public com.betterjavacode.benefits.soap.user.getUserDetails(int id);
}
Die Implementierung dieses Dienstes wird die Entitätsklasse User auf die generierte Klasse für den Soap-Service User abbilden. Unter Verwendung der ID als Schlüssel zum Abrufen von Benutzerdaten aus dem Repository werden wir dem Soap-Service-Benutzer zugeordnet. Für Post-Zwecke zeigen wir die Implementierung dieser Schnittstelle nicht.
5. Dienstendpunkt erstellen
Was ist ein Dienstendpunkt? Wenn eine SOAP-Anforderung für eine definierte URL vom Spring-Servlet verarbeitet wird, leitet das Spring-Servlet diese Anforderung an den Dienstendpunkt weiter. Der Dienstendpunkt verarbeitet dann diese Anfrage, um eine Antwort zu erstellen. Unsere spring-boot-starter-web-services
Abhängigkeit bringt alle notwendigen Klassen für Annotationszwecke.
package com.betterjavacode.benefits.services.endpoints;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
import com.betterjavacode.benefits.services.UserAccountService;
import com.betterjavacode.benefits.soap.GetUserRequest;
import com.betterjavacode.benefits.soap.GetUserResponse;
import com.betterjavacode.benefits.soap.User;
@Endpoint
public class UserAccountServiceEndpoint
{
// private static final String TARGET_NAMESPACE ="http://com/betterjavacode/benefits/webservices/useraccountservice";
private static final String TARGET_NAMESPACE = "https://betterjavacode.com/benefits/soap";
@Autowired private UserAccountService userAccountService;
@PayloadRoot(localPart = "getUserRequest", namespace = TARGET_NAMESPACE)
public @ResponsePayload GetUserResponse getUserRequest(@RequestPayload GetUserRequest request)
{
GetUserResponse response = new GetUserResponse();
User user = userAccountService.getUserDetails(request.getId());
response.setUser(user);
return response;
}
}
@Endpoint
Annotation ermöglicht es, die Klasse als Dienstendpunkt zu definieren und in @Component
aufzunehmen Anmerkung zum Scannen. Stellen Sie sicher, dass der in dieser Klasse definierte Namespace mit der XSD-Schemadefinition übereinstimmt. Andernfalls kann ein Fehler für „Kein Endpunkt definiert für auftreten “.
6. Konfiguration
Als Nächstes konfigurieren wir unsere Konfigurationsklasse, um den WSDL-Endpunkt zu generieren. Diese Konfigurationsklasse wird mit @EnableWs kommentiert, um die Webdienstkonfiguration bereitzustellen.
package com.betterjavacode.benefits;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;
@Configuration
@EnableWs
@ComponentScan("com.betterjavacode")
public class AppConfig extends WsConfigurerAdapter
{
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext)
{
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
return new ServletRegistrationBean(servlet,"/benefits/endpoints/*");
}
@Bean(name="users")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema usersSchema)
{
DefaultWsdl11Definition wsdl11definition = new DefaultWsdl11Definition();
wsdl11definition.setPortTypeName("UserAccountService");
wsdl11definition.setLocationUri("/endpoints");
wsdl11definition.setTargetNamespace("http://com/betterjavacode/benefits/webservices/useraccountservice");
wsdl11definition.setSchema(usersSchema);
return wsdl11definition;
}
@Bean
public XsdSchema usersSchema()
{
return new SimpleXsdSchema(new ClassPathResource("employees.xsd"));
}
}
Einige wichtige Punkte zu dieser Konfigurationsklasse sind
- MessageDispatcherServlet ist ein erforderliches Servlet zum Versenden von Webdienstnachrichten. Wir setzen dieses Servlet mit einer Bean, um die URL zu verarbeiten, von der die Anfrage kommt.
- DefaultWsdl11Definition erstellt SOAP für das angegebene XSD-Schema
- XsdSchema bietet eine Abstraktion für das XSD-Schema unserer Benutzer
7. Ausführen des SOAP-Webservice
Bauen Sie jetzt unser Projekt mit maven. Führen Sie die Spring-Boot-Anwendung über Eclipse aus, um den eingebetteten Tomcat-Server zu starten. Sobald der Tomcat-Server startet, wenn wir auf die URL http://localhost:8080/benefits/endpoints/users.wsdl
zugreifen
Die Ausgabe im Browser erfolgt wie folgt
Hier haben wir gezeigt, wie man einen einfachen SOAP-Webdienst erstellt, den wir mit dem Spring Boot REST API-Dienst kombiniert haben. Wir können diesen SOAP-Webservice auch mit der Soap-Benutzeroberfläche testen, wie im folgenden Screenshot gezeigt
8. Nutzung des SOAP-Webdienstes
In den vorherigen Schritten haben wir gezeigt, wie ein SOAP-Webdienst erstellt wird. Jetzt zeigen wir, wie dieser SOAP-Webdienst programmgesteuert genutzt wird.
8.1 Erstellen Sie eine Client-Klasse
Unter Paket com.betterjavacode.benefits.views
, definieren Sie eine Klasse UserClient
wodurch ein WebServiceGatewaySupport
erweitert wird Klasse. WebServiceGatewaySupport
-Klasse stellt Webservice-Methoden bereit.
package com.betterjavacode.benefits.views;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.core.SoapActionCallback;
import com.betterjavacode.benefits.soap.GetUserRequest;
import com.betterjavacode.benefits.soap.GetUserResponse;
public class UserClient extends WebServiceGatewaySupport
{
public GetUserResponse getUserById(int userid)
{
GetUserRequest userrequest = new GetUserRequest(); userrequest.setId(userid);
GetUserResponse response = (GetUserResponse) getWebServiceTemplate().marshalSendAndReceive(userrequest, new SoapActionCallback("http://localhost:8080/benefits/endpoints/getUserResponse"));
return response;
}
}
8.2 Den Client für die Spring Bean-Unterstützung konfigurieren
Wir werden Jaxb2Marshaller so konfigurieren, dass JAXB unterstützt wird, um den Kontextpfad festzulegen. Dies wird uns helfen, unsere XML-Anfrage und -Antwort zu marshall und unmarshall.
package com.betterjavacode.benefits.views;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
@Configuration
public class ClientAppConfig
{
@Bean
public Jaxb2Marshaller marshaller()
{
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.betterjavacode.benefits.soap");
return marshaller;
}
@Bean
public UserClient userClient(Jaxb2Marshaller marshaller)
{
// WSDL URL - http://localhost:8080/benefits/endpoints/users.wsdl
UserClient uc = new UserClient();
uc.setDefaultUri("http://localhost:8080/benefits/endpoints/users.wsdl");
uc.setMarshaller(marshaller);
uc.setUnmarshaller(marshaller);
return uc;
}
}
8.3 Führen Sie den SOAP-Webservice-Client aus
Wir werden eine Klasse mit Hauptmethode definieren, um ein Argument der Benutzer-ID zu übergeben. Unser Client ruft den Webdienst mit übergebenem Argument auf, um uns die Daten zurückzugeben, wenn diese Benutzer-ID in der Datenbank vorhanden war.
9. Fazit
In diesem Artikel haben wir gezeigt, wie Sie einen SOAP-Webdienst erstellen und einen Client erstellen, der denselben SOAP-Webdienst mit Spring Boot nutzt. Der Code dafür ist auf github
verfügbar10. Referenzen
- Tutorial für Spring-Webdienste
- Erzeuger und Verbraucher von SOAP-Webdiensten
- Nutzung eines Webdienstes in Java und SOAP UI