Outbound endpoints execute HTTP requests reactively using Spring WebFlux's WebClient. They act as the client-side component, making HTTP calls to external services from within integration flows.
Required Dependencies:
spring-webflux must be on classpath (provides WebClient)spring-integration-core is requiredreactor-core is required (provided transitively)Default Behaviors:
extractPayload=true by default (extracts body from ResponseEntity)extractRequestPayload=true by default (extracts payload from Message)replyPayloadToFlux=false by default (resolves Mono to single value)Threading Model:
Lifecycle:
autoStartup=true by defaultExceptions:
WebClientException - WebClient request failuresWebClientResponseException - HTTP response errors (4xx, 5xx)HttpServerErrorException - 5xx server errorsHttpClientErrorException - 4xx client errorsHttpMessageNotReadableException - response body conversion failuresTimeoutException - request timeout errorsEdge Cases:
publisherElementType configurationextractPayload=false, full ResponseEntity is available in message payloadreplyPayloadToFlux=true, response is always Flux even for single valuesSpring Integration WebFlux provides two types of outbound endpoints:
Both types use WebClient for fully reactive, non-blocking HTTP communication.
Create outbound gateways that make HTTP requests and route responses back into the flow.
/**
* Create an outbound gateway with a fixed URI.
* @param uri - Target URI as String
* @return WebFluxMessageHandlerSpec for fluent configuration
*/
public static WebFluxMessageHandlerSpec outboundGateway(String uri)
/**
* Create an outbound gateway with a fixed URI and custom WebClient.
* @param uri - Target URI as String
* @param webClient - Custom configured WebClient instance
* @return WebFluxMessageHandlerSpec for fluent configuration
*/
public static WebFluxMessageHandlerSpec outboundGateway(
String uri,
WebClient webClient)
/**
* Create an outbound gateway with dynamic URI evaluation.
* @param uriFunction - Function to compute URI from message
* @return WebFluxMessageHandlerSpec for fluent configuration
*/
public static <P> WebFluxMessageHandlerSpec outboundGateway(
Function<Message<P>, ?> uriFunction)
/**
* Create an outbound gateway with dynamic URI evaluation via SpEL.
* @param uriExpression - SpEL expression to evaluate URI
* @return WebFluxMessageHandlerSpec for fluent configuration
*/
public static WebFluxMessageHandlerSpec outboundGateway(Expression uriExpression)Usage Examples:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.webflux.dsl.WebFlux;
import org.springframework.http.HttpMethod;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class OutboundGatewayConfig {
// Fixed URI
@Bean
public IntegrationFlow simpleOutboundFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/users")
.httpMethod(HttpMethod.GET)
.expectedResponseType(User[].class))
.channel("responseChannel")
.get();
}
// Dynamic URI with function
@Bean
public IntegrationFlow dynamicUriFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway(
message -> "https://api.example.com/users/" + message.getPayload()))
.get();
}
// Custom WebClient
@Bean
public IntegrationFlow customClientFlow(WebClient customWebClient) {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/data", customWebClient)
.httpMethod(HttpMethod.GET))
.get();
}
}Create outbound channel adapters for one-way HTTP requests.
/**
* Create an outbound channel adapter with a fixed URI.
* Fire-and-forget pattern - doesn't route HTTP response back to flow.
* @param uri - Target URI as String
* @return WebFluxMessageHandlerSpec for fluent configuration
*/
public static WebFluxMessageHandlerSpec outboundChannelAdapter(String uri)
/**
* Create an outbound channel adapter with custom WebClient.
* @param uri - Target URI as String
* @param webClient - Custom configured WebClient instance
* @return WebFluxMessageHandlerSpec for fluent configuration
*/
public static WebFluxMessageHandlerSpec outboundChannelAdapter(
String uri,
WebClient webClient)
/**
* Create an outbound channel adapter with dynamic URI.
* @param uriFunction - Function to compute URI from message
* @return WebFluxMessageHandlerSpec for fluent configuration
*/
public static <P> WebFluxMessageHandlerSpec outboundChannelAdapter(
Function<Message<P>, ?> uriFunction)
/**
* Create an outbound channel adapter with dynamic URI via SpEL.
* @param uriExpression - SpEL expression to evaluate URI
* @return WebFluxMessageHandlerSpec for fluent configuration
*/
public static WebFluxMessageHandlerSpec outboundChannelAdapter(Expression uriExpression)Usage Example:
@Bean
public IntegrationFlow notificationFlow() {
return IntegrationFlow
.from("notificationChannel")
.handle(WebFlux.outboundChannelAdapter("https://webhook.site/notify")
.httpMethod(HttpMethod.POST)
.expectedResponseType(Void.class))
.get();
}Specify the HTTP method for the request.
/**
* Set the HTTP method for the request.
* @param httpMethod - HttpMethod (GET, POST, PUT, DELETE, PATCH, etc.)
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec httpMethod(HttpMethod httpMethod)
/**
* Set the HTTP method using a SpEL expression.
* @param httpMethodExpression - Expression object evaluating to HttpMethod
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec httpMethodExpression(Expression httpMethodExpression)
/**
* Set the HTTP method using a function.
* @param httpMethodFunction - Function returning HttpMethod
* @return Spec for method chaining
*/
public <P> WebFluxMessageHandlerSpec httpMethodFunction(
Function<Message<P>, HttpMethod> httpMethodFunction)Usage Example:
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
@Bean
public IntegrationFlow dynamicMethodFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/resource")
.httpMethod(HttpMethod.POST))
.get();
}
@Bean
public IntegrationFlow dynamicMethodExpressionFlow() {
SpelExpressionParser parser = new SpelExpressionParser();
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/resource")
.httpMethodExpression(parser.parseExpression("headers.httpMethod")))
.get();
}
@Bean
public IntegrationFlow dynamicMethodFunctionFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/resource")
.httpMethodFunction(message ->
message.getHeaders().get("httpMethod", HttpMethod.class)))
.get();
}Specify the expected response type for deserialization.
/**
* Set the expected response type.
* @param expectedResponseType - Java class for response deserialization
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec expectedResponseType(Class<?> expectedResponseType)
/**
* Set the expected response type using ParameterizedTypeReference for generics.
* @param expectedResponseType - ParameterizedTypeReference for generic types
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec expectedResponseType(
ParameterizedTypeReference<?> expectedResponseType)
/**
* Set the expected response type using a SpEL expression.
* @param expectedResponseTypeExpression - Expression object evaluating to Class or ParameterizedTypeReference
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec expectedResponseTypeExpression(
Expression expectedResponseTypeExpression)
/**
* Set the expected response type using a function.
* @param expectedResponseTypeFunction - Function returning Class or ParameterizedTypeReference
* @return Spec for method chaining
*/
public <P> WebFluxMessageHandlerSpec expectedResponseTypeFunction(
Function<Message<P>, ?> typeFunction)Usage Examples:
import org.springframework.core.ParameterizedTypeReference;
import java.util.List;
// Simple type
@Bean
public IntegrationFlow simpleTypeFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/user")
.expectedResponseType(User.class))
.get();
}
// Generic type
@Bean
public IntegrationFlow genericTypeFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/users")
.expectedResponseType(new ParameterizedTypeReference<List<User>>() {}))
.get();
}
// Dynamic type using Expression
@Bean
public IntegrationFlow dynamicTypeFlow() {
SpelExpressionParser parser = new SpelExpressionParser();
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/data")
.expectedResponseTypeExpression(
parser.parseExpression("headers.responseType")))
.get();
}
// Dynamic type using Function
@Bean
public IntegrationFlow dynamicTypeFunctionFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/data")
.expectedResponseTypeFunction(message ->
message.getHeaders().get("responseType", Class.class)))
.get();
}Define URI path variables for dynamic URI construction.
/**
* Add a URI variable with a static value.
* @param variable - Variable name in URI template
* @param value - Static value for the variable
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec uriVariable(String variable, Object value)
/**
* Add a URI variable with a SpEL expression.
* @param variable - Variable name in URI template
* @param expression - SpEL expression to evaluate for the variable
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec uriVariable(String variable, String expression)
/**
* Add a URI variable with an Expression object.
* @param variable - Variable name in URI template
* @param expression - Expression to evaluate for the variable
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec uriVariable(String variable, Expression expression)
/**
* Set all URI variables using a SpEL expression that evaluates to a Map.
* @param uriVariablesExpression - SpEL expression evaluating to Map<String, ?>
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec uriVariablesExpression(String uriVariablesExpression)
/**
* Set all URI variables using an Expression that evaluates to a Map.
* @param uriVariablesExpression - Expression evaluating to Map<String, ?>
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec uriVariablesExpression(Expression uriVariablesExpression)Usage Examples:
@Bean
public IntegrationFlow uriVariableFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/users/{id}/orders/{orderId}")
.uriVariable("id", "headers.userId")
.uriVariable("orderId", "payload.orderId")
.httpMethod(HttpMethod.GET))
.get();
}
@Bean
public IntegrationFlow uriVariablesMapFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/users/{id}")
.uriVariablesExpression("headers.uriVariables"))
.get();
}Configure HTTP request header mapping.
/**
* Set a custom HeaderMapper for complete control over header mapping.
* @param headerMapper - Custom HeaderMapper implementation
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec headerMapper(HeaderMapper<HttpHeaders> headerMapper)
/**
* Specify which message headers to map to HTTP request headers.
* Supports patterns like "X-*" (all X- headers), "!X-Secret-*" (exclude X-Secret-* headers).
* @param patterns - Header name patterns
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec mappedRequestHeaders(String... patterns)
/**
* Specify which HTTP response headers to map to message headers.
* @param patterns - Header name patterns
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec mappedResponseHeaders(String... patterns)Usage Examples:
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
// Filter which message headers map to HTTP headers
@Bean
public IntegrationFlow headerMappingFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/data")
.mappedRequestHeaders("X-*", "!X-Secret-*") // Map X-* headers except X-Secret-*
.mappedResponseHeaders("X-Response-*")) // Map X-Response-* from response
.get();
}
// Set custom headers using enrichHeaders before the outbound endpoint
@Bean
public IntegrationFlow customHeadersFlow() {
return IntegrationFlow
.from("requestChannel")
.enrichHeaders(h -> h
.header("Authorization", "Bearer token123")
.headerExpression("X-Request-ID",
"T(java.util.UUID).randomUUID().toString()"))
.handle(WebFlux.outboundGateway("https://api.example.com/data")
.mappedRequestHeaders("Authorization", "X-Request-ID"))
.get();
}
// Custom HeaderMapper for advanced control
@Bean
public IntegrationFlow customHeaderMapperFlow() {
DefaultHttpHeaderMapper headerMapper = new DefaultHttpHeaderMapper();
headerMapper.setOutboundHeaderNames("X-*", "Authorization");
headerMapper.setInboundHeaderNames("X-Response-*");
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/data")
.headerMapper(headerMapper))
.get();
}Important Note: Unlike some other Spring Integration endpoints, WebFlux outbound endpoints do not provide direct header() or headerExpression() methods. To set custom HTTP headers, use the .enrichHeaders() DSL method before the outbound endpoint, then use .mappedRequestHeaders() to control which message headers are mapped to HTTP headers.
Control whether to extract the response payload or keep the full ResponseEntity.
/**
* Set whether to extract the payload from the ResponseEntity.
* Default is true.
* @param extractPayload - true to extract payload, false to keep ResponseEntity
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec extractPayload(boolean extractPayload)Usage Example:
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.HttpHeaders;
@Bean
public IntegrationFlow fullResponseFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/data")
.extractPayload(false)) // Get full ResponseEntity with headers, status
.handle((payload, headers) -> {
ResponseEntity<?> response = (ResponseEntity<?>) payload;
HttpStatusCode status = response.getStatusCode();
HttpHeaders responseHeaders = response.getHeaders();
Object body = response.getBody();
return processFullResponse(status, responseHeaders, body);
})
.get();
}Specify the element type when sending reactive Publishers (Flux/Mono) as request body.
/**
* Set the element type for Publisher request bodies.
* Used when payload is Flux or Mono.
* @param publisherElementType - Java class of Publisher elements
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec publisherElementType(Class<?> publisherElementType)
/**
* Set the element type using ParameterizedTypeReference for generic types.
* @param publisherElementType - ParameterizedTypeReference for Publisher elements
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec publisherElementType(
ParameterizedTypeReference<?> publisherElementType)
/**
* Set the element type dynamically using a function.
* @param typeFunction - Function to determine element type from message
* @return Spec for method chaining
*/
public <P> WebFluxMessageHandlerSpec publisherElementTypeFunction(
Function<Message<P>, ?> typeFunction)
/**
* Set the element type using a SpEL expression.
* @param publisherElementTypeExpression - SpEL expression evaluating to Class
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec publisherElementTypeExpression(
Expression publisherElementTypeExpression)Usage Example:
import reactor.core.publisher.Flux;
@Bean
public IntegrationFlow publisherFlow() {
return IntegrationFlow
.from("streamChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/stream")
.httpMethod(HttpMethod.POST)
.publisherElementType(DataEvent.class)) // Payload is Flux<DataEvent>
.get();
}Control whether to return the response as a Flux or resolve it to a single value.
/**
* Set whether to return the reply payload as a Flux.
* If true, returns Flux even for single-element responses.
* If false (default), resolves Mono to single value.
* @param replyPayloadToFlux - true to return Flux, false to resolve value
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec replyPayloadToFlux(boolean replyPayloadToFlux)Usage Example:
import org.springframework.integration.dsl.IntegrationFlowDefinition;
@Bean
public IntegrationFlow fluxReplyFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/stream")
.replyPayloadToFlux(true)) // Always return Flux
.split() // Split Flux elements into individual messages
.channel("processChannel")
.get();
}Provide a custom BodyExtractor for low-level response processing.
/**
* Set a custom BodyExtractor for extracting the response body.
* Allows low-level access to ClientHttpResponse.
* @param bodyExtractor - BodyExtractor instance
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec bodyExtractor(
BodyExtractor<?, ? super ClientHttpResponse> bodyExtractor)Usage Example:
import org.springframework.integration.webflux.support.ClientHttpResponseBodyExtractor;
import org.springframework.web.reactive.function.client.ClientHttpResponse;
@Bean
public IntegrationFlow customExtractorFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/data")
.bodyExtractor(new ClientHttpResponseBodyExtractor()))
.handle((payload, headers) -> {
ClientHttpResponse response = (ClientHttpResponse) payload;
// Access raw response
HttpStatusCode status = response.getStatusCode();
HttpHeaders responseHeaders = response.getHeaders();
return processRawResponse(response);
})
.get();
}Configure URI encoding mode (only when WebClient is not provided externally).
/**
* Set the URI encoding mode.
* Only applies when WebClient is created internally.
* @param encodingMode - EncodingMode (TEMPLATE_AND_VALUES, VALUES_ONLY, URI_COMPONENT, NONE)
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec encodingMode(
DefaultUriBuilderFactory.EncodingMode encodingMode)Usage Example:
import org.springframework.web.util.DefaultUriBuilderFactory;
@Bean
public IntegrationFlow encodingFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/search?q={query}")
.encodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY)
.uriVariable("query", "payload.searchTerm"))
.get();
}Enable automatic cookie transfer between requests.
/**
* Enable or disable cookie transfer between requests.
* @param transferCookies - true to transfer cookies, false otherwise
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec transferCookies(boolean transferCookies)Usage Example:
@Bean
public IntegrationFlow cookieFlow() {
return IntegrationFlow
.from("loginChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/login")
.httpMethod(HttpMethod.POST)
.transferCookies(true))
.handle(WebFlux.outboundGateway("https://api.example.com/protected")
.transferCookies(true)) // Cookies from login are sent
.get();
}Configure WebClient with custom settings for advanced use cases.
import io.netty.channel.ChannelOption;
import reactor.netty.http.client.HttpClient;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import java.time.Duration;
@Bean
public WebClient customWebClient() {
return WebClient.builder()
.baseUrl("https://api.example.com")
.defaultHeader("User-Agent", "My Integration App")
.defaultHeader("Accept", "application/json")
.defaultCookie("session", "xyz123")
.filter(ExchangeFilterFunction.ofRequestProcessor(
clientRequest -> {
// Custom request processing
return Mono.just(clientRequest);
}))
.filter(ExchangeFilterFunction.ofResponseProcessor(
clientResponse -> {
// Custom response processing
return Mono.just(clientResponse);
}))
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create()
.responseTimeout(Duration.ofSeconds(10))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
))
.codecs(configurer -> {
// Custom codecs
configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024);
})
.build();
}
@Bean
public IntegrationFlow customWebClientFlow(WebClient customWebClient) {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("/resource/{id}", customWebClient)
.uriVariable("id", "payload.id"))
.get();
}import reactor.core.publisher.Flux;
import org.springframework.messaging.MessageChannel;
import org.springframework.integration.channel.MessageChannels;
@Bean
public IntegrationFlow sendFluxFlow() {
return IntegrationFlow
.from("dataStreamChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/batch")
.httpMethod(HttpMethod.POST)
.publisherElementType(DataItem.class))
.get();
}
@Bean
public MessageChannel dataStreamChannel() {
return MessageChannels.flux().get();
}
// Send Flux as message payload
@Autowired
private MessageChannel dataStreamChannel;
public void streamData() {
Flux<DataItem> dataStream = Flux.interval(Duration.ofSeconds(1))
.map(i -> new DataItem(i))
.take(100);
dataStreamChannel.send(MessageBuilder.withPayload(dataStream).build());
}import org.springframework.core.ParameterizedTypeReference;
@Bean
public IntegrationFlow receiveFluxFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/events")
.httpMethod(HttpMethod.GET)
.replyPayloadToFlux(true)
.expectedResponseType(new ParameterizedTypeReference<Flux<Event>>() {}))
.split()
.handle("eventProcessor", "process")
.get();
}import org.springframework.http.ResponseEntity;
import org.springframework.web.reactive.function.client.WebClientResponseException;
@Bean
public IntegrationFlow errorHandlingFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/risky")
.extractPayload(false))
.handle((payload, headers) -> {
ResponseEntity<?> response = (ResponseEntity<?>) payload;
if (response.getStatusCode().is2xxSuccessful()) {
return response.getBody();
} else if (response.getStatusCode().is4xxClientError()) {
throw new BadRequestException("Client error: " + response.getStatusCode());
} else {
throw new ServiceException("Server error: " + response.getStatusCode());
}
})
.get();
}import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
@Bean
public WebClient errorHandlingWebClient() {
return WebClient.builder()
.baseUrl("https://api.example.com")
.filter(ExchangeFilterFunction.ofResponseProcessor(
clientResponse -> {
if (clientResponse.statusCode().is5xxServerError()) {
return clientResponse.bodyToMono(String.class)
.flatMap(body -> Mono.error(new ServerException("Server error: " + body)));
}
return Mono.just(clientResponse);
}))
.build();
}import reactor.core.publisher.Mono;
@Bean
public IntegrationFlow reactiveErrorHandlingFlow() {
return IntegrationFlow
.from("requestChannel")
.handle(WebFlux.outboundGateway("https://api.example.com/data")
.expectedResponseType(Data.class))
.handle((payload, headers) -> {
if (payload instanceof WebClientResponseException) {
WebClientResponseException ex = (WebClientResponseException) payload;
return Mono.error(new CustomException(ex));
}
return Mono.just(payload);
})
.onErrorContinue((ex, data) -> {
// Handle errors gracefully
log.error("Error processing: {}", ex.getMessage());
})
.get();
}Set WebClient request attributes for advanced configuration.
/**
* Set a SpEL expression that evaluates to a Map of request attributes.
* @param attributeVariablesExpression - SpEL expression evaluating to Map
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec attributeVariablesExpression(
Expression attributeVariablesExpression)
/**
* Set a SpEL expression string that evaluates to a Map of request attributes.
* @param attributeVariablesExpression - SpEL expression string evaluating to Map
* @return Spec for method chaining
*/
public WebFluxMessageHandlerSpec attributeVariablesExpression(
String attributeVariablesExpression)Usage Example:
import org.springframework.expression.spel.standard.SpelExpressionParser;
import java.util.Map;
import java.time.Duration;
@Bean
public IntegrationFlow requestAttributesFlow() {
SpelExpressionParser parser = new SpelExpressionParser();
return IntegrationFlow
.from("requestChannel")
.enrichHeaders(h -> h.header("attributes", Map.of(
"timeout", Duration.ofSeconds(30),
"retries", 3
)))
.handle(WebFlux.outboundGateway("https://api.example.com/data")
.attributeVariablesExpression(
parser.parseExpression("headers.attributes")))
.get();
}For advanced use cases, configure WebFluxRequestExecutingMessageHandler directly.
package org.springframework.integration.webflux.outbound;
/**
* Direct bean configuration for WebFluxRequestExecutingMessageHandler.
*/
public class WebFluxRequestExecutingMessageHandler
extends AbstractHttpRequestExecutingMessageHandler {
/**
* Create handler with fixed URI.
*/
public WebFluxRequestExecutingMessageHandler(String uri);
/**
* Create handler with dynamic URI expression.
*/
public WebFluxRequestExecutingMessageHandler(Expression uriExpression);
/**
* Create handler with custom WebClient.
*/
public WebFluxRequestExecutingMessageHandler(String uri, WebClient webClient);
// Configuration methods
public void setReplyPayloadToFlux(boolean replyPayloadToFlux);
public void setBodyExtractor(BodyExtractor<?, ?> bodyExtractor);
public void setPublisherElementType(Class<?> publisherElementType);
public void setPublisherElementTypeExpression(Expression expression);
public void setAttributeVariablesExpression(Expression expression);
public void setEncodingMode(DefaultUriBuilderFactory.EncodingMode encodingMode);
}Usage Example:
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.MessageChannel;
@Bean
@ServiceActivator(inputChannel = "outboundChannel")
public WebFluxRequestExecutingMessageHandler customOutboundHandler(
WebClient customWebClient) {
WebFluxRequestExecutingMessageHandler handler =
new WebFluxRequestExecutingMessageHandler(
"https://api.example.com/data",
customWebClient);
handler.setHttpMethod(HttpMethod.POST);
handler.setExpectedResponseType(ResponseData.class);
handler.setReplyPayloadToFlux(false);
return handler;
}package org.springframework.integration.webflux.dsl;
/**
* Spec builder for configuring WebFlux outbound message handlers.
*/
public class WebFluxMessageHandlerSpec
extends BaseHttpMessageHandlerSpec<WebFluxMessageHandlerSpec,
WebFluxRequestExecutingMessageHandler> {
// All configuration methods as documented above
}package org.springframework.integration.webflux.support;
/**
* BodyExtractor that returns raw ClientHttpResponse without extraction.
*/
public class ClientHttpResponseBodyExtractor
implements BodyExtractor<ClientHttpResponse, ClientHttpResponse> {
public ClientHttpResponse extract(ClientHttpResponse response, Context context);
}