Spring Integration WebFlux supports traditional XML-based configuration through the int-webflux namespace. This provides an alternative to the Java DSL for teams that prefer XML configuration.
The XML configuration namespace provides elements for all WebFlux integration components:
<int-webflux:inbound-gateway> - Receive HTTP requests with reply<int-webflux:inbound-channel-adapter> - Receive HTTP requests without reply<int-webflux:outbound-gateway> - Make HTTP requests with response handling<int-webflux:outbound-channel-adapter> - Make HTTP requests fire-and-forgetAdd the namespace declaration to your Spring XML configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-webflux="http://www.springframework.org/schema/integration/webflux"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/webflux
https://www.springframework.org/schema/integration/webflux/spring-integration-webflux.xsd">
<!-- Configuration here -->
</beans>Receive HTTP requests and send replies through the integration flow.
<int-webflux:inbound-gateway
id="gateway"
request-channel="requestChannel"
reply-channel="replyChannel"
error-channel="errorChannel"
path="/api/endpoint"
supported-methods="GET,POST"
request-payload-type="com.example.Request"
reply-payload-type="com.example.Response"
codec-configurer="codecConfigurer"
requested-content-type-resolver="contentTypeResolver"
reactive-adapter-registry="adapterRegistry"
header-mapper="headerMapper"
mapped-request-headers="X-*,Authorization"
mapped-response-headers="X-Response-*"
payload-expression="#requestParams"
validator="validator"
status-code-expression="T(org.springframework.http.HttpStatus).OK"
extract-reply-payload="true"
auto-startup="true"
phase="0">
<int-webflux:request-mapping>
<int-webflux:headers>
<entry key="X-API-Key" value="*"/>
</int-webflux:headers>
<int-webflux:params>
<entry key="active" value="true"/>
</int-webflux:params>
</int-webflux:request-mapping>
<int-webflux:cross-origin
origin="https://example.com"
allowed-headers="*"
exposed-headers="X-Total-Count"
method="GET,POST"
allow-credentials="true"
max-age="3600"/>
</int-webflux:inbound-gateway>Attributes:
id - Bean identifierrequest-channel - Channel to send inbound messages (required)reply-channel - Channel to receive reply messages (optional)error-channel - Channel for error messages (optional)path - URL path pattern(s) to match (required)supported-methods - Comma-separated HTTP methods (optional)request-payload-type - Java class for request deserialization (optional)reply-payload-type - Java class for reply type hint (optional)codec-configurer - Reference to ServerCodecConfigurer bean (optional)requested-content-type-resolver - Reference to RequestedContentTypeResolver bean (optional)reactive-adapter-registry - Reference to ReactiveAdapterRegistry bean (optional)header-mapper - Reference to HeaderMapper bean (optional)mapped-request-headers - Patterns for request headers to map (optional)mapped-response-headers - Patterns for response headers to map (optional)payload-expression - SpEL expression for payload extraction (optional)validator - Reference to Validator bean (optional)status-code-expression - SpEL expression for HTTP status code (optional)extract-reply-payload - Extract payload from reply message (default: true)auto-startup - Start automatically (default: true)phase - Startup phase (optional)Example:
<int-webflux:inbound-gateway
request-channel="orderChannel"
path="/api/orders"
supported-methods="POST"
request-payload-type="com.example.Order">
<int-webflux:request-mapping>
<int-webflux:consumes>application/json</int-webflux:consumes>
<int-webflux:produces>application/json</int-webflux:produces>
</int-webflux:request-mapping>
</int-webflux:inbound-gateway>Receive HTTP requests without sending replies (fire-and-forget).
<int-webflux:inbound-channel-adapter
id="adapter"
channel="channel"
error-channel="errorChannel"
path="/webhooks/event"
supported-methods="POST"
request-payload-type="com.example.Event"
codec-configurer="codecConfigurer"
header-mapper="headerMapper"
mapped-request-headers="X-*"
payload-expression="#requestParams"
auto-startup="true"
phase="0">
<int-webflux:request-mapping>
<!-- Same as inbound-gateway -->
</int-webflux:request-mapping>
<int-webflux:cross-origin>
<!-- Same as inbound-gateway -->
</int-webflux:cross-origin>
</int-webflux:inbound-channel-adapter>Attributes:
Same as inbound-gateway, except:
channel instead of request-channel (required)reply-channel attributereply-payload-type attributeextract-reply-payload attributestatus-code-expression attributeExample:
<int-webflux:inbound-channel-adapter
channel="webhookChannel"
path="/webhooks/notification"
supported-methods="POST"
request-payload-type="com.example.Notification"/>Configure detailed request matching criteria.
<int-webflux:request-mapping>
<!-- HTTP headers to match -->
<int-webflux:headers>
<entry key="X-API-Version" value="2"/>
<entry key="X-Client-ID" value="*"/>
</int-webflux:headers>
<!-- Request parameters to match -->
<int-webflux:params>
<entry key="active" value="true"/>
<entry key="filter" value="*"/>
</int-webflux:params>
<!-- Content types to consume -->
<int-webflux:consumes>application/json</int-webflux:consumes>
<int-webflux:consumes>application/xml</int-webflux:consumes>
<!-- Content types to produce -->
<int-webflux:produces>application/json</int-webflux:produces>
</int-webflux:request-mapping>Elements:
<int-webflux:headers> - Map of required request headers<int-webflux:params> - Map of required request parameters<int-webflux:consumes> - Consumable media types (can have multiple)<int-webflux:produces> - Producible media types (can have multiple)Configure CORS for inbound endpoints.
<int-webflux:cross-origin
origin="https://example.com,https://app.example.com"
allowed-headers="Content-Type,Authorization,X-Custom-Header"
exposed-headers="X-Total-Count,X-Page-Number"
method="GET,POST,PUT,DELETE"
allow-credentials="true"
max-age="3600"/>Attributes:
origin - Comma-separated allowed origins, or "*" for all (required)allowed-headers - Comma-separated allowed request headers (optional)exposed-headers - Comma-separated exposed response headers (optional)method - Comma-separated allowed HTTP methods (optional)allow-credentials - Allow credentials (default: false)max-age - Preflight cache duration in seconds (optional)Make HTTP requests and handle responses in the integration flow.
<int-webflux:outbound-gateway
id="gateway"
request-channel="requestChannel"
reply-channel="replyChannel"
url="https://api.example.com/users/{id}"
http-method="GET"
http-method-expression="headers.httpMethod"
expected-response-type="com.example.User"
expected-response-type-expression="headers.responseType"
web-client="customWebClient"
encoding-mode="VALUES_ONLY"
reply-payload-to-flux="false"
body-extractor="bodyExtractor"
publisher-element-type="com.example.DataItem"
publisher-element-type-expression="headers.elementType"
charset="UTF-8"
extract-payload="true"
extract-request-payload="true"
header-mapper="headerMapper"
mapped-request-headers="X-*,Authorization"
mapped-response-headers="X-Response-*"
transfer-cookies="false"
reply-timeout="30000"
requires-reply="true"
order="1">
<int-webflux:uri-variable name="id" expression="payload.userId"/>
<int-webflux:uri-variable name="type" value="premium"/>
<int-webflux:header name="Authorization" value="Bearer token"/>
<int-webflux:header name="X-Request-ID" expression="T(java.util.UUID).randomUUID()"/>
</int-webflux:outbound-gateway>Attributes:
id - Bean identifierrequest-channel - Input channel (required)reply-channel - Output channel for responses (optional)url - Target URL with optional placeholders (required)http-method - HTTP method (GET, POST, etc.) (optional, default: POST)http-method-expression - SpEL expression for HTTP method (optional)expected-response-type - Java class for response deserialization (optional)expected-response-type-expression - SpEL expression for response type (optional)web-client - Reference to WebClient bean (optional, mutually exclusive with encoding-mode)encoding-mode - URI encoding mode (TEMPLATE_AND_VALUES, VALUES_ONLY, URI_COMPONENT, NONE) (optional)reply-payload-to-flux - Return Flux instead of resolved value (default: false)body-extractor - Reference to custom BodyExtractor bean (optional)publisher-element-type - Element type for Publisher payloads (optional)publisher-element-type-expression - SpEL expression for element type (optional)charset - Character encoding (optional)extract-payload - Extract response payload vs ResponseEntity (default: true)extract-request-payload - Extract request payload vs Message (default: true)header-mapper - Reference to HeaderMapper bean (optional)mapped-request-headers - Patterns for request headers to map (optional)mapped-response-headers - Patterns for response headers to map (optional)transfer-cookies - Transfer cookies between requests (default: false)reply-timeout - Reply timeout in milliseconds (optional)requires-reply - Require a reply message (default: true)order - Handler order (optional)Example:
<int-webflux:outbound-gateway
request-channel="userRequestChannel"
reply-channel="userResponseChannel"
url="https://api.example.com/users/{userId}"
http-method="GET"
expected-response-type="com.example.User">
<int-webflux:uri-variable name="userId" expression="payload.id"/>
<int-webflux:header name="Authorization" value="Bearer ${api.token}"/>
</int-webflux:outbound-gateway>Make HTTP requests without handling responses (fire-and-forget).
<int-webflux:outbound-channel-adapter
id="adapter"
channel="channel"
url="https://webhook.example.com/notify"
http-method="POST"
expected-response-type="java.lang.Void"
web-client="customWebClient"
encoding-mode="VALUES_ONLY"
publisher-element-type="com.example.Event"
charset="UTF-8"
extract-request-payload="true"
header-mapper="headerMapper"
mapped-request-headers="X-*"
transfer-cookies="false"
order="1">
<int-webflux:uri-variable name="key" expression="payload.apiKey"/>
<int-webflux:header name="Content-Type" value="application/json"/>
</int-webflux:outbound-channel-adapter>Attributes:
Same as outbound-gateway, except:
channel instead of request-channel (required)reply-channel attributereply-payload-to-flux attributebody-extractor attributeextract-payload attributemapped-response-headers attributereply-timeout attributerequires-reply attributeExample:
<int-webflux:outbound-channel-adapter
channel="notificationChannel"
url="https://webhook.site/notify"
http-method="POST"
web-client="webhookClient"/>Define URI path variables for outbound endpoints.
<int-webflux:uri-variable name="variableName" expression="SpEL expression"/>
<int-webflux:uri-variable name="variableName" value="static value"/>Attributes:
name - Variable name matching placeholder in URL (required)expression - SpEL expression to evaluate (mutually exclusive with value)value - Static value (mutually exclusive with expression)Example:
<int-webflux:outbound-gateway
url="https://api.example.com/users/{userId}/orders/{orderId}">
<int-webflux:uri-variable name="userId" expression="payload.userId"/>
<int-webflux:uri-variable name="orderId" expression="headers.orderId"/>
</int-webflux:outbound-gateway>Add HTTP request headers for outbound endpoints.
<int-webflux:header name="headerName" expression="SpEL expression"/>
<int-webflux:header name="headerName" value="static value"/>Attributes:
name - Header name (required)expression - SpEL expression to evaluate (mutually exclusive with value)value - Static value (mutually exclusive with expression)Example:
<int-webflux:outbound-gateway url="https://api.example.com/data">
<int-webflux:header name="Authorization" value="Bearer ${api.token}"/>
<int-webflux:header name="X-Request-ID"
expression="T(java.util.UUID).randomUUID().toString()"/>
<int-webflux:header name="X-User-ID" expression="headers.userId"/>
</int-webflux:outbound-gateway><!-- Inbound gateway receiving orders -->
<int-webflux:inbound-gateway
request-channel="orderChannel"
path="/api/orders"
supported-methods="POST,PUT"
request-payload-type="com.example.Order"
validator="orderValidator">
<int-webflux:request-mapping>
<int-webflux:consumes>application/json</int-webflux:consumes>
<int-webflux:produces>application/json</int-webflux:produces>
<int-webflux:headers>
<entry key="X-API-Key" value="*"/>
</int-webflux:headers>
</int-webflux:request-mapping>
<int-webflux:cross-origin
origin="https://example.com"
method="POST,PUT"
allow-credentials="true"/>
</int-webflux:inbound-gateway>
<!-- Service activator processing orders -->
<int:service-activator
input-channel="orderChannel"
output-channel="orderResponseChannel"
ref="orderService"
method="processOrder"/>
<!-- Order service bean -->
<bean id="orderService" class="com.example.OrderService"/>
<!-- Validator bean -->
<bean id="orderValidator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/><!-- Outbound gateway calling external user API -->
<int-webflux:outbound-gateway
id="userApiGateway"
request-channel="userLookupChannel"
reply-channel="userDataChannel"
url="https://api.example.com/users/{userId}"
http-method="GET"
expected-response-type="com.example.User"
web-client="customWebClient">
<int-webflux:uri-variable name="userId" expression="payload.id"/>
<int-webflux:header name="Authorization" value="Bearer ${external.api.token}"/>
<int-webflux:header name="Accept" value="application/json"/>
</int-webflux:outbound-gateway>
<!-- Custom WebClient with timeout configuration -->
<bean id="customWebClient" class="com.example.WebClientFactory"
factory-method="createWebClient">
<constructor-arg value="${external.api.baseUrl}"/>
<constructor-arg value="${external.api.timeout}"/>
</bean><!-- Webhook inbound adapter -->
<int-webflux:inbound-channel-adapter
channel="webhookChannel"
path="/webhooks/github"
supported-methods="POST"
request-payload-type="com.example.GitHubEvent"
mapped-request-headers="X-GitHub-*">
<int-webflux:request-mapping>
<int-webflux:headers>
<entry key="X-GitHub-Event" value="*"/>
</int-webflux:headers>
</int-webflux:request-mapping>
</int-webflux:inbound-channel-adapter>
<!-- Async channel for webhook processing -->
<int:channel id="webhookChannel">
<int:dispatcher task-executor="webhookExecutor"/>
</int:channel>
<task:executor id="webhookExecutor" pool-size="10"/>
<!-- Service activator processing webhooks -->
<int:service-activator
input-channel="webhookChannel"
ref="githubService"
method="handleEvent"/><!-- Receive HTTP request -->
<int-webflux:inbound-gateway
request-channel="processRequestChannel"
path="/api/process"
supported-methods="POST"
request-payload-type="com.example.ProcessRequest"/>
<!-- Transform request -->
<int:transformer
input-channel="processRequestChannel"
output-channel="validateChannel"
ref="requestTransformer"
method="transform"/>
<!-- Call validation API -->
<int-webflux:outbound-gateway
request-channel="validateChannel"
reply-channel="validatedChannel"
url="https://validator.api.com/validate"
http-method="POST"
expected-response-type="com.example.ValidationResult"
web-client="validatorClient"/>
<!-- Process validated data -->
<int:service-activator
input-channel="validatedChannel"
ref="dataProcessor"
method="process"/>
<!-- Beans -->
<bean id="requestTransformer" class="com.example.RequestTransformer"/>
<bean id="dataProcessor" class="com.example.DataProcessor"/>
<bean id="validatorClient" class="com.example.ValidatorClientFactory"
factory-method="createClient"/><!-- Outbound gateway with Flux response -->
<int-webflux:outbound-gateway
request-channel="streamRequestChannel"
reply-channel="streamResponseChannel"
url="https://api.example.com/events"
http-method="GET"
reply-payload-to-flux="true"
expected-response-type-expression="headers.responseType"/>
<!-- Split Flux into individual messages -->
<int:splitter input-channel="streamResponseChannel"
output-channel="eventProcessingChannel"/>
<!-- Process individual events -->
<int:service-activator
input-channel="eventProcessingChannel"
ref="eventProcessor"
method="process"/>Use Spring property placeholders for externalized configuration:
<!-- Property placeholder configurer -->
<context:property-placeholder location="classpath:application.properties"/>
<!-- Inbound gateway with properties -->
<int-webflux:inbound-gateway
request-channel="apiChannel"
path="${api.endpoint.path}"
supported-methods="${api.endpoint.methods}"/>
<!-- Outbound gateway with properties -->
<int-webflux:outbound-gateway
request-channel="requestChannel"
url="${external.api.url}"
http-method="${external.api.method}"
web-client="webClient">
<int-webflux:header name="Authorization" value="Bearer ${external.api.token}"/>
</int-webflux:outbound-gateway>application.properties:
api.endpoint.path=/api/data
api.endpoint.methods=GET,POST
external.api.url=https://api.example.com/resource
external.api.method=GET
external.api.token=your-token-hereYou can mix XML configuration with Java beans:
<!-- XML configuration -->
<int-webflux:outbound-gateway
request-channel="requestChannel"
url="https://api.example.com/data"
web-client="customWebClient"/>
<!-- Reference to Java-configured bean -->
<bean id="customWebClient" class="com.example.config.WebClientConfig"
factory-method="customWebClient"/>@Configuration
public class WebClientConfig {
@Bean
public WebClient customWebClient() {
return WebClient.builder()
.baseUrl("https://api.example.com")
.defaultHeader("User-Agent", "Integration App")
.build();
}
}The XML namespace is handled by WebFluxNamespaceHandler.
package org.springframework.integration.webflux.config;
/**
* Namespace handler for int-webflux XML configuration.
* Registers parsers for all WebFlux elements.
*/
public class WebFluxNamespaceHandler extends AbstractIntegrationNamespaceHandler {
// Automatically registered via spring.handlers
}XML Namespace URI:
http://www.springframework.org/schema/integration/webfluxSchema Location:
https://www.springframework.org/schema/integration/webflux/spring-integration-webflux.xsdFor teams migrating from Java DSL to XML or vice versa:
Java DSL:
@Bean
public IntegrationFlow flow() {
return IntegrationFlow
.from(WebFlux.inboundGateway("/api/orders")
.requestMapping(m -> m.methods(HttpMethod.POST))
.requestPayloadType(Order.class))
.handle("orderService", "process")
.get();
}Equivalent XML:
<int-webflux:inbound-gateway
request-channel="orderChannel"
path="/api/orders"
supported-methods="POST"
request-payload-type="com.example.Order"/>
<int:service-activator
input-channel="orderChannel"
ref="orderService"
method="process"/>
<bean id="orderService" class="com.example.OrderService"/>