SOAP Web サービスの使用

このガイドでは、Spring で SOAP ベースの Web サービスを利用するプロセスを順を追って説明します。

構築するもの

SOAP [Wikipedia] を使用して、WSDL ベースの Web サービスである リモートから国データをフェッチするクライアントを構築します。このガイドに従って、国別サービスの詳細を確認し、自分でサービスを実行できます。

このサービスは国データを提供します。名前に基づいて国に関するデータを照会できます。

必要なもの

本ガイドの完成までの流れ

ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。

最初から始めるには、Spring Initializr から開始に進みます。

基本スキップするには、次の手順を実行します。

完了したときは、gs-consuming-web-service/complete のコードに対して結果を確認できます。

ターゲット Web サービスをローカルで実行する

関連ガイドの手順に従うか、リポジトリ [GitHub] (英語) のクローンを作成し、その complete ディレクトリからサービスを (たとえば、./gradlew bootRun を使用して) 実行します。ブラウザーで http://localhost:8080/services/countries.wsdl にアクセスすると、機能することを確認できます。そうしないと、後で JAXB ツールからビルドに紛らわしい例外が表示されることになります。

Spring Initializr から開始

すべての Spring アプリケーションは、Spring Initializr (Eclipse の場合は Spring スタータープロジェクト) から始める必要があります。Initializr は、アプリケーションに必要なすべての依存関係をすばやく取り込む方法を提供し、多くの設定を行います。この例では、Spring Web Services 依存関係のみが必要です。

IDE を使用する場合はプロジェクト作成ウィザードを使用します。IDE を使用せずにコマンドラインなどで開発する場合は、この事前に初期化されたプロジェクトからプロジェクトを ZIP ファイルとしてダウンロードできます。このプロジェクトは、このチュートリアルの例に合うように構成されています。

プロジェクトを初期化するには:

  1. IDE のメニューまたはブラウザーから Spring Initializr を開きます。アプリケーションに必要なすべての依存関係を取り込み、ほとんどのセットアップを行います。

  2. Gradle または Maven のいずれかと、使用する言語を選択します。このガイドは、Java を選択したことを前提としています。

  3. 依存関係をクリックして、Spring Web Services を選択します。

  4. 生成をクリックします。

  5. 結果の ZIP ファイルをダウンロードします。これは、選択して構成された Web アプリケーションのアーカイブです。

EclipseIntelliJ のような IDE は新規プロジェクト作成ウィザードから Spring Initializr の機能が使用できるため、手動での ZIP ファイルのダウンロードやインポートは不要です。

サーバー側のサポートを除外する

Spring Web Services スターターはサーバーとクライアントの両方のサポートを導入します。ここではクライアントのサポートのみが関係するため、ビルドファイルを更新してサーバーサポートを除外します。

アプリケーションではサーバー側のサポートは必要ないため、"spring-boot-starter-webmvc" とその "-test" バリアントを除外しましょう。

Gradle の場合:

dependencies {
	implementation ('org.springframework.boot:spring-boot-starter-webservices') {
		exclude group: 'org.springframework.boot', module: 'spring-boot-starter-webmvc'
	}

	testImplementation('org.springframework.boot:spring-boot-starter-test')
}

Maven の場合:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-webservices</artifactId>
	<exclusions>
		<exclusion>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-webmvc</artifactId>
		</exclusion>
	</exclusions>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>

WSDL に基づいてドメインオブジェクトを生成する

SOAP Web サービスへのインターフェースは、WSDL [Wikipedia] (英語) でキャプチャーされます。JAXB は、WSDL(または、WSDL の <Types/> セクションに含まれる XSD)から Java クラスを生成する方法を提供します。http://localhost:8080/ws/countries.wsdl で、国別サービスの WSDL を見つけることができます。

指定された URL にある WSDL のクラスを生成し、それらのクラスを com.example.consumingwebservice.wsdl パッケージに配置するようにビルドプラグインを構成しましょう。

Gradle の WSDL から Java クラスを生成するには、次のプラグインのセットアップが必要です。

plugins {
	id 'java'
	id 'org.springframework.boot' version '4.0.0'
	id 'io.spring.dependency-management' version '1.1.7'
	id 'uk.co.boothen.gradle.wsimport' version '0.25' // add the wsimport plugin
}
wsimport {
	wsdlSourceRoot = "http://localhost:8080/services/"

	wsdl ("countries.wsdl") {
		packageName("com.example.consumingwebservice.wsdl")
		xjcarg("-XautoNameResolution")
	}
}

生成されたクラスを ./gradlew assemble で確認してから、build/generated/src/wsdl/main で確認することができます。

Maven には次のプラグイン構成を使用します。

<plugin>
	<groupId>com.sun.xml.ws</groupId>
	<artifactId>jaxws-maven-plugin</artifactId>
	<version>4.0.3</version>
	<executions>
		<execution>
			<goals>
				<goal>wsimport</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<packageName>com.example.consumingwebservice.wsdl</packageName>
		<wsdlUrls>
			<wsdlUrl>http://localhost:8080/services/countries.wsdl</wsdlUrl>
		</wsdlUrls>
		<sourceDestDir>${sourcesDir}</sourceDestDir>
		<destDir>${classesDir}</destDir>
		<extension>true</extension>
	</configuration>
</plugin>

そのコードを生成するには、./mvnw compile を実行し、それが機能しているかどうかを確認する場合は target/generated-sources/wsimport を調べます。

Maven と Gradle の両方で、JAXB ドメインオブジェクト生成プロセスがビルドツールのライフサイクルに組み込まれているため、ビルドが成功したら追加の手順を実行する必要はありません。

カントリーサービスクライアントを作成する

Web サービスクライアントを作成するには、次の例 (src/main/java/com/example/consumingwebservice/CountryClient.java から) に示すように、WebServiceGatewaySupport クラスを継承して操作をコーディングする必要があります。

package com.example.consumingwebservice;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.core.SoapActionCallback;

import com.example.consumingwebservice.wsdl.GetCountryRequest;
import com.example.consumingwebservice.wsdl.GetCountryResponse;

public class CountryClient extends WebServiceGatewaySupport {

  private static final Logger log = LoggerFactory.getLogger(CountryClient.class);

  public GetCountryResponse getCountry(String country) {

    GetCountryRequest request = new GetCountryRequest();
    request.setName(country);

    log.info("Requesting location for " + country);

    GetCountryResponse response = (GetCountryResponse) getWebServiceTemplate()
        .marshalSendAndReceive("http://localhost:8080/services/countries", request,
            new SoapActionCallback(
                "https://spring.io/guides/gs-producing-web-service/GetCountryRequest"));

    return response;
  }

}

クライアントには、実際の SOAP 交換を行う 1 つのメソッド(getCountry)が含まれています。

このメソッドでは、GetCountryRequest クラスと GetCountryResponse クラスの両方が WSDL から派生し、JAXB 生成プロセス(WSDL に基づいてドメインオブジェクトを生成するで説明)で生成されています。GetCountryRequest リクエストオブジェクトを作成し、country パラメーター(国名)を設定します。国名を出力した後、WebServiceGatewaySupport 基本クラスによって提供される WebServiceTemplate を使用して、実際の SOAP 交換を行います。WSDL で <soap:operation/> 要素にこのヘッダーが必要であると記述されているため、GetCountryRequest リクエストオブジェクト(およびリクエストに SOAPAction [W3C] (英語) ヘッダーを渡すための SoapActionCallback)を渡します。レスポンスは GetCountryResponse オブジェクトにキャストされ、返されます。

Web サービスコンポーネントの構成

Spring WS は Spring Framework の OXM モジュールを使用します。このモジュールには、次の例(src/main/java/com/example/consumingwebservice/CountryConfiguration.java から)が示すように、XML リクエストをシリアライズおよびデシリアライズする Jaxb2Marshaller があります

package com.example.consumingwebservice;

import org.springframework.boot.webservices.client.WebServiceTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;

@Configuration
public class CountryConfiguration {

  @Bean
  public Jaxb2Marshaller marshaller() {
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    // this package must match the package configured in the build.gradle/pom.xml
    marshaller.setContextPath("com.example.consumingwebservice.wsdl");
    return marshaller;
  }

  @Bean
  public CountryClient countryClient(WebServiceTemplateBuilder builder, Jaxb2Marshaller marshaller) {
    builder = builder.setMarshaller(marshaller).setUnmarshaller(marshaller);

    CountryClient client = new CountryClient();
    client.setWebServiceTemplate(builder.build());
    client.setDefaultUri("http://localhost:8080/services");
    return client;
  }

}

marshaller は、生成されたドメインオブジェクトのコレクションを指しており、使用して XML と POJO の間で直列化と非直列化の両方を行います。

countryClient は、前に示した国別サービスの URI を使用して作成および構成されます。また、JAXB マーシャラーを使用するように構成されています。

アプリケーションの実行

このアプリケーションは、次のリスト(src/main/java/com/example/consumingwebservice/ConsumingWebServiceApplication.java から)に示すように、コンソールから実行して特定の国名のデータを取得するようにパッケージ化されています。

package com.example.consumingwebservice;

import java.util.List;

import com.example.consumingwebservice.wsdl.GetCountryResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class ConsumingWebServiceApplication {

  Logger logger = LoggerFactory.getLogger(ConsumingWebServiceApplication.class);

  public static void main(String[] args) {
    SpringApplication.run(ConsumingWebServiceApplication.class, args);
  }

  @Bean
  ApplicationRunner lookup(CountryClient countryClient) {
    return args -> {
      List<String> countryOption = args.getOptionValues("country");
      String country = (countryOption == null || countryOption.isEmpty()) ? "Spain" : countryOption.get(0);
      GetCountryResponse response = countryClient.getCountry(country);
      logger.info("Country [%s] has currency [%s].".formatted(country, response.getCountry().getCurrency()));
    };
  }

}

main() メソッドは SpringApplication ヘルパークラスに従い、run() メソッドの引数として CountryConfiguration.class を渡します。これにより、Spring は CountryConfiguration からアノテーションメタデータを読み取り、Spring アプリケーションコンテキスト内のコンポーネントとして管理するようになります。

このアプリケーションは、「スペイン」を検索するためにハードコードされています。このガイドの後半では、コードを編集せずに別のシンボルを入力する方法について説明します。

実行可能 JAR を構築する

コマンドラインから Gradle または Maven を使用してアプリケーションを実行できます。必要なすべての依存関係、クラス、リソースを含む単一の実行可能 JAR ファイルを構築して実行することもできます。実行可能な jar を構築すると、開発ライフサイクル全体、さまざまな環境などで、アプリケーションとしてサービスを簡単に提供、バージョン管理、デプロイできます。

Gradle を使用する場合、./gradlew bootRun を使用してアプリケーションを実行できます。または、次のように、./gradlew build を使用して JAR ファイルをビルドしてから、JAR ファイルを実行できます。

java -jar build/libs/gs-consuming-web-service-0.1.0.jar

Maven を使用する場合、./mvnw spring-boot:run を使用してアプリケーションを実行できます。または、次のように、./mvnw clean package で JAR ファイルをビルドしてから、JAR ファイルを実行できます。

java -jar target/gs-consuming-web-service-0.1.0.jar
ここで説明する手順は、実行可能な JAR を作成します。クラシック WAR ファイルを作成することもできます。

ロギング出力が表示されます。サービスは数秒以内に起動して実行されるはずです。

次のリストは、初期レスポンスを示しています。

Country [Spain] has currency [EUR].

<getCountryRequest><name>Spain</name>...</getCountryRequest>

次のコマンドを実行して、別の国に接続できます。

java -jar build/libs/consuming-web-service-0.0.1-SNAPSHOT.jar --country=Poland

その後、レスポンスは次のように変わります。

Country [Poland] has currency [PLN].

<getCountryRequest><name>Poland</name>...</getCountryRequest>

要約

おめでとう! Spring で SOAP ベースの Web サービスを使用するクライアントを開発しました。

関連事項

次のガイドも役立つかもしれません:

新しいガイドを作成したり、既存のガイドに貢献したいですか? 投稿ガイドラインを参照してください [GitHub] (英語)

すべてのガイドは、コード用の ASLv2 ライセンス、およびドキュメント用の帰属、NoDerivatives クリエイティブコモンズライセンス (英語) でリリースされています。

コードを入手する