Skip to content

Http Interface with Object class as RequestBody results in UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=java.lang.Object #36078

@KrishnaST

Description

@KrishnaST

** Bug Reports /Enhancements requests **

Java Version : 25
Spring Boot Version : 4.0.1

Spring WebClient with http interface throws UnsupportedMediaTypeException when Object class is used as RequestBody and when Content-Type is 'application/xml'

Image

The same works when used with Spring RestClient for any content type. This also works with Webclient with content type as 'application/json'.

The issue happening because the RequestBody type resolution is happening at the time of Interface proxy creation rather than when actual request is fired. The org.springframework.web.service.invoker.ReactiveHttpRequestValues.bodyValueType is getting populated as java.lang.Object rather than the actual request body class type.

Here are some test classes used to identify the issue.

public class WebClientTest {

	public interface NameInterfaceReactive {
		@PostExchange("test")
		public Mono<ResponseEntity<Response>> sendRequest(@RequestBody final Object request);
	}
	
	public static void main(String[] args) throws InterruptedException {
		NameInterfaceReactive nameInterfaceReactive = getNameInterfaceReactive();
		System.out.println("nameInterfaceReactive "+nameInterfaceReactive.getClass().getName());
		nameInterfaceReactive.sendRequest(new Request("John", "Rambo")).subscribe(res -> System.out.println(res));
		Thread.sleep(Duration.ofSeconds(50));
	}
	
	public static NameInterfaceReactive getNameInterfaceReactive() {
		final WebClient.Builder builder = WebClient.builder();
		builder.clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
		builder.baseUrl("http://127.0.0.1:8080/");
		builder.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE);
		final WebClient webClient = builder.build();
		final HttpServiceProxyFactory httpServiceProxyFactory = HttpServiceProxyFactory.builderFor(WebClientAdapter.create(webClient)).build();
		final NameInterfaceReactive nameInterfaceReactive =  httpServiceProxyFactory.createClient(NameInterfaceReactive.class);
		return nameInterfaceReactive;
	}
}




This works with RestClient

public class RestClientTest {

	public interface NameInterface {
		@PostExchange("test")
		public ResponseEntity<Response> sendRequest(@RequestBody final Object request);
	}
	
	public static void main(String[] args) {
		NameInterface nameInterface = getNameInterface();
		System.out.println(nameInterface.sendRequest(new Request("John", "Rambo")).getBody());
	}
	
	public static NameInterface getNameInterface() {
		final RestClient.Builder builder = RestClient.builder();
		builder.baseUrl("http://127.0.0.1:8080/");
		builder.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE);
		final RestClient restClient = builder.build();
		final HttpServiceProxyFactory httpServiceProxyFactory = HttpServiceProxyFactory.builderFor(RestClientAdapter.create(restClient)).build();
		NameInterface nameInterface =  httpServiceProxyFactory.createClient(NameInterface.class);
		return nameInterface;
	}
}

Here is full exception.

Caused by: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=java.lang.Object
	at org.springframework.web.reactive.function.BodyInserters.unsupportedError(BodyInserters.java:445)
	at org.springframework.web.reactive.function.BodyInserters.writeWithMessageWriters(BodyInserters.java:435)
	at org.springframework.web.reactive.function.BodyInserters.lambda$fromValue$1(BodyInserters.java:129)
	at org.springframework.web.reactive.function.client.DefaultClientRequestBuilder$BodyInserterRequest.writeTo(DefaultClientRequestBuilder.java:273)
	at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$exchange$0(ExchangeFunctions.java:103)
	at org.springframework.http.client.reactive.ReactorClientHttpConnector.lambda$connect$0(ReactorClientHttpConnector.java:166)
	at reactor.netty.http.client.HttpClientConnect$HttpClientHandler.requestWithBody(HttpClientConnect.java:657)
	at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.lambda$onStateChange$0(HttpClientConnect.java:469)
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:46)
	at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.onStateChange(HttpClientConnect.java:470)
	at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:730)
	at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onStateChange(DefaultPooledConnectionProvider.java:215)
	at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnection.onStateChange(DefaultPooledConnectionProvider.java:477)
	at reactor.netty.channel.ChannelOperationsHandler.channelActive(ChannelOperationsHandler.java:62)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:220)
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelActive(CombinedChannelDuplexHandler.java:410)
	at io.netty.channel.ChannelInboundHandlerAdapter.channelActive(ChannelInboundHandlerAdapter.java:69)
	at io.netty.channel.CombinedChannelDuplexHandler.channelActive(CombinedChannelDuplexHandler.java:209)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:220)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelActive(DefaultChannelPipeline.java:1417)
	at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:862)
	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:355)
	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:385)
	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.handle(AbstractNioChannel.java:432)
	at io.netty.channel.nio.NioIoHandler$DefaultNioRegistration.handle(NioIoHandler.java:388)
	at io.netty.channel.nio.NioIoHandler.processSelectedKey(NioIoHandler.java:596)
	at io.netty.channel.nio.NioIoHandler.processSelectedKeysPlain(NioIoHandler.java:541)
	at io.netty.channel.nio.NioIoHandler.processSelectedKeys(NioIoHandler.java:514)
	at io.netty.channel.nio.NioIoHandler.run(NioIoHandler.java:484)
	at io.netty.channel.SingleThreadIoEventLoop.runIo(SingleThreadIoEventLoop.java:225)
	at io.netty.channel.SingleThreadIoEventLoop.run(SingleThreadIoEventLoop.java:196)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:1193)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1474)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions