0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

springのWebClientでXMLレスポンスを受信

Posted at

サンプルコード

build.gradle
plugins {
	id 'java'
	id 'org.springframework.boot' version '3.3.4'
	id 'io.spring.dependency-management' version '1.1.6'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(17)
	}
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-webflux'
	implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml'
	implementation("org.glassfish.jaxb:jaxb-runtime")

	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'io.projectreactor:reactor-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
	useJUnitPlatform()
}

以下はXMLレスポンスを格納するクラス。注意点として、@XmlRootElementの指定が必要。

import jakarta.xml.bind.annotation.XmlRootElement;
import lombok.Data;

@Data

@XmlRootElement(name = "note")
public class WebClientSampleDto {
  String to;
  String from;
}

public class SampleMain {

  public static void main(String[] args) {
    ExchangeStrategies strategies = ExchangeStrategies.builder()
        .codecs(conf -> conf.defaultCodecs().jaxb2Decoder(new Jaxb2XmlDecoder()))
        .build();

    WebClient client = WebClient.builder()
        .exchangeStrategies(strategies)
        .build();

    WebClientSampleDto body = client.get()
        .uri("http://localhost:3002/xml")
        .retrieve()
        .bodyToMono(WebClientSampleDto.class)
        .block();

    System.out.println(body);
  }
}

ほぼ見た目通り。デフォルトコーデックにXML処理用のJaxb2XmlDecoderを指定する。今回はレスポンスだけなのでdecoderの指定だけだが、リクエストはjaxb2Encoderを指定すれば良いと思われる。

詳細

動作確認

適当なモックサーバ、今回は https://mockoon.com/ を使用し、URLhttp://localhost:3002/xmlContent-Typeapplication/xmlで以下を返すように設定する。

<note>
  <to>to-hoge</to>
  <from>from-kagami</from>
</note>

これを実行すると以下の結果が得られる。

WebClientSampleDto(to=to-hoge, from=from-kagami)

対応Content-Typeの変更

Jaxb2XmlDecoderのデフォルト対応Content-Typeは、application/xml, text/xml, application/*+xml、となっている。なのでこれ以外に対応したい場合は別途以下のように設定の必要がある。具体的にはJaxb2XmlDecoderのコンストラクタに指定する。以下はapplication/octet-streamに対応させている。

import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;

    ExchangeStrategies strategies = ExchangeStrategies.builder()
        .codecs(conf -> conf.defaultCodecs().jaxb2Decoder(
            new Jaxb2XmlDecoder(MimeTypeUtils.APPLICATION_OCTET_STREAM)))
        .build();

はまった点

UnsupportedMediaTypeException

この例外はクラス名が示す通り、レスポンスに対応するデコーダーがWebClientに未設定なことを示す。ただ、その原因は様々なケースがありうる。

Caused by: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/octet-stream;charset=utf-8' not supported for bodyType=org.example.app.WebClientSampleDto
	at org.springframework.web.reactive.function.BodyExtractors.readWithMessageReaders(BodyExtractors.java:205)

まず、jaxb2Decoderが未指定だと当然ながらこの例外をスローする。

また、Content-Typeが未対応のものだとこれも例外をスローする。

デコーダはJAXBであってjacksonではない。よって、XML用アノテーションは@XmlRootElementを使用する必要がある。@JacksonXmlRootElementではない。これも例外をスローする。

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?