HTTP message converters for content type handling and header mappers for bidirectional translation between Spring Integration MessageHeaders and HTTP headers. These components enable seamless conversion of HTTP requests/responses to Spring Integration messages and vice versa.
Default Converters:
MappingJackson2HttpMessageConverter (if Jackson on classpath)MappingJackson2XmlHttpMessageConverter or JAXB converter (if available)StringHttpMessageConverterFormHttpMessageConverterMultipartAwareFormHttpMessageConverter (must be explicitly configured)Converter Selection:
Content-Type header for readingAccept header for writingcanRead()/canWrite() is usedHeader Mapping:
http_ prefixX-*, Custom-*)HTTP_REQUEST_HEADERS, HTTP_RESPONSE_HEADERSDefault Header Mapper:
DefaultHttpHeaderMapper provides intelligent mappingHeader Mapping Rules:
Multipart Support:
MultipartAwareFormHttpMessageConverter required for file uploadsMultipartFileReader for file handling strategyapplication/x-www-form-urlencoded and multipart/form-dataSerialization Support:
SerializingHttpMessageConverter for Java serializationapplication/x-java-serialized-object media typeEdge Cases:
HttpMessageNotReadableException or HttpMessageNotWritableExceptionextractResponseBody=true)Performance Considerations:
Default HeaderMapper implementation for HTTP, mapping between Spring Integration MessageHeaders and HTTP HttpHeaders bidirectionally. Provides intelligent mapping with configurable patterns and prefixes.
public class DefaultHttpHeaderMapper
implements HeaderMapper<HttpHeaders>, BeanFactoryAware, InitializingBean {
public static final String CONTENT_MD5 = "Content-MD5";
public static final String REFRESH = "Refresh";
public static final String HTTP_REQUEST_HEADER_NAME_PATTERN = "HTTP_REQUEST_HEADERS";
public static final String HTTP_RESPONSE_HEADER_NAME_PATTERN = "HTTP_RESPONSE_HEADERS";
/**
* Creates a default header mapper instance.
*/
public DefaultHttpHeaderMapper();
/**
* Sets BeanFactory for dependency resolution.
*
* @param beanFactory the bean factory
* @throws BeansException if error occurs
*/
public void setBeanFactory(BeanFactory beanFactory) throws BeansException;
/**
* Sets header names or patterns to map to HTTP request/response headers.
* Supports wildcards (e.g., "X-Custom-*") and special patterns.
*
* @param outboundHeaderNames header name patterns
*/
public void setOutboundHeaderNames(String... outboundHeaderNames);
/**
* Sets header names or patterns to map from HTTP request/response headers.
* Supports wildcards (e.g., "X-Custom-*") and special patterns.
*
* @param inboundHeaderNames header name patterns
*/
public void setInboundHeaderNames(String... inboundHeaderNames);
/**
* Sets excluded outbound standard request header names.
* Headers matching these names will not be mapped to HTTP requests.
*
* @param excludedOutboundStandardRequestHeaderNames excluded header names
*/
public void setExcludedOutboundStandardRequestHeaderNames(
String... excludedOutboundStandardRequestHeaderNames);
/**
* Sets excluded inbound standard response header names.
* Headers matching these names will not be mapped from HTTP responses.
*
* @param excludedInboundStandardResponseHeaderNames excluded header names
*/
public void setExcludedInboundStandardResponseHeaderNames(
String... excludedInboundStandardResponseHeaderNames);
/**
* Sets prefix for user-defined headers.
* User headers without standard HTTP names will be prefixed.
* Default: empty string (no prefix).
*
* @param userDefinedHeaderPrefix the prefix
*/
public void setUserDefinedHeaderPrefix(String userDefinedHeaderPrefix);
/**
* Initializes ConversionService after properties set.
*
* @throws Exception if initialization fails
*/
public void afterPropertiesSet() throws Exception;
/**
* Maps from Spring Integration MessageHeaders to HTTP HttpHeaders.
* Converts message headers to HTTP request/response headers.
*
* @param headers source message headers
* @param target target HTTP headers
*/
public void fromHeaders(MessageHeaders headers, HttpHeaders target);
/**
* Maps from HTTP HttpHeaders to Spring Integration MessageHeaders.
* Converts HTTP request/response headers to message headers.
*
* @param source source HTTP headers
* @return map of message headers
*/
public Map<String, Object> toHeaders(HttpHeaders source);
/**
* Creates default outbound mapper instance.
* Pre-configured for mapping message headers to HTTP requests.
*
* @return outbound header mapper
*/
public static DefaultHttpHeaderMapper outboundMapper();
/**
* Creates default inbound mapper instance.
* Pre-configured for mapping HTTP responses to message headers.
*
* @return inbound header mapper
*/
public static DefaultHttpHeaderMapper inboundMapper();
}Usage Example - Basic Header Mapping:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
@Configuration
public class HeaderMappingConfig {
@Bean
public DefaultHttpHeaderMapper httpHeaderMapper() {
DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper();
// Map specific headers to HTTP requests
mapper.setOutboundHeaderNames(
"Content-Type",
"Accept",
"Authorization",
"X-Custom-*"); // Pattern for custom headers
// Map specific headers from HTTP responses
mapper.setInboundHeaderNames(
"Content-Type",
"X-Transaction-Id",
"X-Status-*");
return mapper;
}
@Bean
public HttpRequestExecutingMessageHandler handlerWithMapper() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler("https://api.example.com/data");
handler.setHeaderMapper(httpHeaderMapper());
handler.setHttpMethod(HttpMethod.POST);
return handler;
}
}Usage Example - Outbound Mapper with Exclusions:
@Bean
public DefaultHttpHeaderMapper outboundHeaderMapper() {
DefaultHttpHeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper();
// Set user-defined header prefix
mapper.setUserDefinedHeaderPrefix("X-App-");
// Exclude specific standard headers
mapper.setExcludedOutboundStandardRequestHeaderNames(
"Cookie",
"Set-Cookie");
return mapper;
}Usage Example - Inbound Mapper:
@Bean
public DefaultHttpHeaderMapper inboundHeaderMapper() {
DefaultHttpHeaderMapper mapper = DefaultHttpHeaderMapper.inboundMapper();
// Map all response headers
mapper.setInboundHeaderNames("*");
// Exclude specific headers from mapping
mapper.setExcludedInboundStandardResponseHeaderNames(
"Transfer-Encoding",
"Connection");
return mapper;
}Usage Example - Custom Pattern Matching:
@Bean
public DefaultHttpHeaderMapper customPatternMapper() {
DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper();
// Map standard headers and custom patterns
mapper.setOutboundHeaderNames(
"HTTP_REQUEST_HEADERS", // Standard request headers
"Authorization",
"X-*", // All headers starting with X-
"Custom-*"); // All headers starting with Custom-
mapper.setInboundHeaderNames(
"HTTP_RESPONSE_HEADERS", // Standard response headers
"X-*",
"Custom-*");
return mapper;
}Abstract class containing constant definitions for HTTP-related message header names used in Spring Integration HTTP components.
public abstract class HttpHeaders {
/**
* Prefix for HTTP header names in Spring Integration messages.
* Value: "http_"
*/
public static final String PREFIX = "http_";
/**
* Header name for request URL.
* Value: "http_requestUrl"
*/
public static final String REQUEST_URL = "http_requestUrl";
/**
* Header name for HTTP request method.
* Value: "http_requestMethod"
*/
public static final String REQUEST_METHOD = "http_requestMethod";
/**
* Header name for user principal.
* Value: "http_userPrincipal"
*/
public static final String USER_PRINCIPAL = "http_userPrincipal";
/**
* Header name for HTTP status code.
* Value: "http_statusCode"
*/
public static final String STATUS_CODE = "http_statusCode";
}Usage Example:
import org.springframework.integration.http.HttpHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
public class HttpHeaderExample {
public Message<String> createMessageWithHttpHeaders(String payload) {
return MessageBuilder
.withPayload(payload)
.setHeader(HttpHeaders.REQUEST_URL, "https://api.example.com/data")
.setHeader(HttpHeaders.REQUEST_METHOD, "POST")
.setHeader(HttpHeaders.STATUS_CODE, 200)
.build();
}
public void processMessage(Message<?> message) {
String requestUrl = (String) message.getHeaders().get(HttpHeaders.REQUEST_URL);
String method = (String) message.getHeaders().get(HttpHeaders.REQUEST_METHOD);
Integer statusCode = (Integer) message.getHeaders().get(HttpHeaders.STATUS_CODE);
System.out.println("URL: " + requestUrl);
System.out.println("Method: " + method);
System.out.println("Status: " + statusCode);
}
}HttpMessageConverter implementation that delegates to AllEncompassingFormHttpMessageConverter while adding capability to read multipart/form-data content in HTTP requests. Enables handling of file uploads and multipart form submissions.
public class MultipartAwareFormHttpMessageConverter
implements HttpMessageConverter<MultiValueMap<String, ?>> {
/**
* Creates converter with default configuration.
*/
public MultipartAwareFormHttpMessageConverter();
/**
* Sets the character set used for writing form data.
* Default: UTF-8.
*
* @param charset the charset
*/
public void setCharset(Charset charset);
/**
* Sets the MultipartFileReader to use when reading MultipartFile content.
* Determines how uploaded files are processed.
*
* @param multipartFileReader the multipart file reader
*/
public void setMultipartFileReader(
MultipartFileReader<?> multipartFileReader);
/**
* Returns list of supported media types.
* Includes application/x-www-form-urlencoded and multipart/form-data.
*
* @return list of supported media types
*/
public List<MediaType> getSupportedMediaTypes();
/**
* Checks if this converter can read the given class and media type.
*
* @param clazz the class to check
* @param mediaType the media type
* @return true if can read
*/
public boolean canRead(Class<?> clazz, MediaType mediaType);
/**
* Checks if this converter can write the given class and media type.
*
* @param clazz the class to check
* @param mediaType the media type
* @return true if can write
*/
public boolean canWrite(Class<?> clazz, MediaType mediaType);
/**
* Reads multipart form data from HTTP input message.
* Converts multipart request to MultiValueMap.
*
* @param clazz the target class
* @param inputMessage the HTTP input message
* @return the multipart form data as MultiValueMap
* @throws IOException if read error occurs
* @throws HttpMessageNotReadableException if conversion fails
*/
public MultiValueMap<String, ?> read(
Class<? extends MultiValueMap<String, ?>> clazz,
HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/**
* Writes form data to HTTP output message.
* Converts MultiValueMap to HTTP form data.
*
* @param map the form data
* @param contentType the content type
* @param outputMessage the HTTP output message
* @throws IOException if write error occurs
* @throws HttpMessageNotWritableException if conversion fails
*/
public void write(
MultiValueMap<String, ?> map,
MediaType contentType,
HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}Usage Example - File Upload Endpoint:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.http.converter.MultipartAwareFormHttpMessageConverter;
import org.springframework.integration.http.multipart.FileCopyingMultipartFileReader;
import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway;
import org.springframework.integration.http.inbound.RequestMapping;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.HttpMessageConverter;
@Configuration
public class MultipartConfig {
@Bean
public MultipartAwareFormHttpMessageConverter multipartConverter() {
MultipartAwareFormHttpMessageConverter converter =
new MultipartAwareFormHttpMessageConverter();
// Configure multipart file reader
FileCopyingMultipartFileReader reader =
new FileCopyingMultipartFileReader();
reader.setPrefix("upload_");
reader.setSuffix(".tmp");
converter.setMultipartFileReader(reader);
converter.setCharset(StandardCharsets.UTF_8);
return converter;
}
@Bean
public HttpRequestHandlingMessagingGateway uploadGateway() {
HttpRequestHandlingMessagingGateway gateway =
new HttpRequestHandlingMessagingGateway();
RequestMapping mapping = new RequestMapping();
mapping.setPathPatterns("/upload");
mapping.setMethods(HttpMethod.POST);
mapping.setConsumes("multipart/form-data");
gateway.setRequestMapping(mapping);
// Set message converters
List<HttpMessageConverter<?>> converters = new ArrayList<>();
converters.add(multipartConverter());
gateway.setMessageConverters(converters);
gateway.setRequestChannel(uploadChannel());
return gateway;
}
}Usage Example - Form Submission with Java DSL:
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.http.dsl.Http;
import org.springframework.util.MultiValueMap;
@Bean
public IntegrationFlow formSubmissionFlow() {
MultipartAwareFormHttpMessageConverter converter =
new MultipartAwareFormHttpMessageConverter();
return IntegrationFlow
.from(Http.inboundGateway("/forms/submit")
.requestMapping(m -> m
.methods(HttpMethod.POST)
.consumes("multipart/form-data"))
.messageConverters(converter)
.requestPayloadType(MultiValueMap.class))
.handle((payload, headers) -> {
MultiValueMap<String, ?> formData = (MultiValueMap<String, ?>) payload;
// Process form data
return processFormData(formData);
})
.get();
}HttpMessageConverter implementation for Serializable instances using Java serialization. Supports application/x-java-serialized-object media type for binary Java object serialization over HTTP.
public class SerializingHttpMessageConverter
extends AbstractHttpMessageConverter<Serializable> {
/**
* Creates new instance supporting application/x-java-serialized-object.
*/
public SerializingHttpMessageConverter();
/**
* Checks if class is Serializable.
* Only Serializable classes are supported.
*
* @param clazz the class to check
* @return true if class is Serializable
*/
protected boolean supports(Class<?> clazz);
/**
* Checks if can write Serializable to given media type.
*
* @param clazz the class
* @param mediaType the media type
* @return true if can write
*/
public boolean canWrite(Class<?> clazz, MediaType mediaType);
/**
* Reads serialized object from HTTP input message.
*
* @param clazz the target class
* @param inputMessage the HTTP input message
* @return the deserialized object
* @throws IOException if read error occurs
* @throws HttpMessageNotReadableException if deserialization fails
*/
protected Serializable readInternal(
Class<? extends Serializable> clazz,
HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/**
* Writes serialized object to HTTP output message.
*
* @param object the object to serialize
* @param outputMessage the HTTP output message
* @throws IOException if write error occurs
* @throws HttpMessageNotWritableException if serialization fails
*/
protected void writeInternal(
Serializable object,
HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}Usage Example - Serialized Object Transfer:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.http.converter.SerializingHttpMessageConverter;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.HttpMethod;
@Configuration
public class SerializationConfig {
@Bean
public SerializingHttpMessageConverter serializingConverter() {
return new SerializingHttpMessageConverter();
}
@Bean
public HttpRequestExecutingMessageHandler serializedObjectHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/serialized-data");
handler.setHttpMethod(HttpMethod.POST);
// Configure message converters
List<HttpMessageConverter<?>> converters = new ArrayList<>();
converters.add(serializingConverter());
handler.setMessageConverters(converters);
handler.setExpectedResponseType(SerializableResponse.class);
return handler;
}
}
// Serializable data class
class SerializableData implements Serializable {
private static final long serialVersionUID = 1L;
private String data;
private int value;
// Constructors, getters, setters
}Usage Example - Java DSL with Serialization:
@Bean
public IntegrationFlow serializationFlow() {
SerializingHttpMessageConverter converter =
new SerializingHttpMessageConverter();
return IntegrationFlow
.from("serializableChannel")
.handle(Http.outboundGateway("https://api.example.com/binary")
.httpMethod(HttpMethod.POST)
.messageConverters(converter)
.expectedResponseType(SerializableResult.class))
.get();
}Implement custom header mapping logic for specific requirements:
import org.springframework.integration.mapping.HeaderMapper;
import org.springframework.http.HttpHeaders;
import org.springframework.messaging.MessageHeaders;
@Bean
public HttpRequestExecutingMessageHandler customHeaderMappingHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler("https://api.example.com/data");
// Create custom header mapper
HeaderMapper<HttpHeaders> customMapper = new HeaderMapper<HttpHeaders>() {
@Override
public void fromHeaders(MessageHeaders headers, HttpHeaders target) {
// Map authorization
if (headers.containsKey("auth_token")) {
target.setBearerAuth((String) headers.get("auth_token"));
}
// Map custom headers with transformation
headers.keySet().stream()
.filter(key -> key.startsWith("custom_"))
.forEach(key -> {
String httpHeader = key.replace("custom_", "X-Custom-");
target.add(httpHeader, headers.get(key).toString());
});
// Map content type
if (headers.containsKey(MessageHeaders.CONTENT_TYPE)) {
target.setContentType(
MediaType.parseMediaType(
headers.get(MessageHeaders.CONTENT_TYPE).toString()));
}
}
@Override
public Map<String, Object> toHeaders(HttpHeaders source) {
Map<String, Object> headers = new HashMap<>();
// Map response headers
source.forEach((key, values) -> {
if (!values.isEmpty()) {
headers.put("http_" + key.toLowerCase(), values.get(0));
}
});
// Map status headers
if (source.containsKey("X-Status")) {
headers.put("response_status", source.getFirst("X-Status"));
}
return headers;
}
};
handler.setHeaderMapper(customMapper);
handler.setHttpMethod(HttpMethod.POST);
return handler;
}Map headers conditionally based on message content:
@Bean
public DefaultHttpHeaderMapper conditionalHeaderMapper() {
DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper();
// Configure base patterns
mapper.setOutboundHeaderNames(
"Content-Type",
"Accept");
// Custom mapping logic via BeanPostProcessor
return new DefaultHttpHeaderMapper() {
@Override
public void fromHeaders(MessageHeaders headers, HttpHeaders target) {
super.fromHeaders(headers, target);
// Conditional mapping
if (headers.containsKey("secure") &&
Boolean.TRUE.equals(headers.get("secure"))) {
// Add security headers for secure messages
target.add("X-Security-Level", "HIGH");
if (headers.containsKey("api_key")) {
target.add("X-API-Key", headers.get("api_key").toString());
}
}
// Dynamic header based on payload type
if (headers.containsKey(MessageHeaders.CONTENT_TYPE)) {
String contentType = headers.get(MessageHeaders.CONTENT_TYPE).toString();
if (contentType.contains("json")) {
target.add("X-Data-Format", "JSON");
} else if (contentType.contains("xml")) {
target.add("X-Data-Format", "XML");
}
}
}
};
}Configure multiple message converters for different content types:
@Configuration
public class MultiConverterConfig {
@Bean
public HttpRequestHandlingMessagingGateway multiConverterGateway() {
HttpRequestHandlingMessagingGateway gateway =
new HttpRequestHandlingMessagingGateway();
RequestMapping mapping = new RequestMapping();
mapping.setPathPatterns("/api/data");
mapping.setMethods(HttpMethod.POST);
mapping.setConsumes("application/json", "application/xml",
"application/x-www-form-urlencoded",
"multipart/form-data");
gateway.setRequestMapping(mapping);
// Configure multiple converters
List<HttpMessageConverter<?>> converters = new ArrayList<>();
// JSON converter
MappingJackson2HttpMessageConverter jsonConverter =
new MappingJackson2HttpMessageConverter();
jsonConverter.setSupportedMediaTypes(
Collections.singletonList(MediaType.APPLICATION_JSON));
converters.add(jsonConverter);
// XML converter
MappingJackson2XmlHttpMessageConverter xmlConverter =
new MappingJackson2XmlHttpMessageConverter();
xmlConverter.setSupportedMediaTypes(
Collections.singletonList(MediaType.APPLICATION_XML));
converters.add(xmlConverter);
// Form converter
FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
converters.add(formConverter);
// Multipart converter
MultipartAwareFormHttpMessageConverter multipartConverter =
new MultipartAwareFormHttpMessageConverter();
multipartConverter.setMultipartFileReader(
new FileCopyingMultipartFileReader());
converters.add(multipartConverter);
// String converter (fallback)
StringHttpMessageConverter stringConverter =
new StringHttpMessageConverter(StandardCharsets.UTF_8);
converters.add(stringConverter);
gateway.setMessageConverters(converters);
gateway.setRequestChannel(dataChannel());
return gateway;
}
}Configure content negotiation for outbound requests:
@Bean
public HttpRequestExecutingMessageHandler contentNegotiationHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler("https://api.example.com/data");
// Configure multiple converters for content negotiation
List<HttpMessageConverter<?>> converters = new ArrayList<>();
// JSON - preferred
MappingJackson2HttpMessageConverter jsonConverter =
new MappingJackson2HttpMessageConverter();
converters.add(jsonConverter);
// XML - alternate
MappingJackson2XmlHttpMessageConverter xmlConverter =
new MappingJackson2XmlHttpMessageConverter();
converters.add(xmlConverter);
handler.setMessageConverters(converters);
handler.setHttpMethod(HttpMethod.POST);
// Configure header mapper to set Accept header
DefaultHttpHeaderMapper headerMapper = new DefaultHttpHeaderMapper();
headerMapper.setOutboundHeaderNames("Content-Type", "Accept");
handler.setHeaderMapper(headerMapper);
return handler;
}Configure header mapping using Java DSL:
@Bean
public IntegrationFlow headerMappingFlow() {
DefaultHttpHeaderMapper headerMapper = new DefaultHttpHeaderMapper();
headerMapper.setOutboundHeaderNames(
"Content-Type",
"Authorization",
"X-Request-*");
headerMapper.setInboundHeaderNames(
"Content-Type",
"X-Response-*");
return IntegrationFlow
.from("inputChannel")
.handle(Http.outboundGateway("https://api.example.com/process")
.httpMethod(HttpMethod.POST)
.headerMapper(headerMapper)
.mappedRequestHeaders("Authorization", "X-Request-Id")
.mappedResponseHeaders("X-Transaction-Id", "X-Status")
.expectedResponseType(String.class))
.get();
}Configure JSON message conversion for REST API:
@Configuration
public class JsonApiConfig {
@Bean
public IntegrationFlow jsonApiFlow() {
MappingJackson2HttpMessageConverter jsonConverter =
new MappingJackson2HttpMessageConverter();
DefaultHttpHeaderMapper headerMapper =
DefaultHttpHeaderMapper.outboundMapper();
headerMapper.setOutboundHeaderNames(
"Content-Type",
"Accept",
"Authorization");
return IntegrationFlow
.from(Http.inboundGateway("/api/users")
.requestMapping(m -> m
.methods(HttpMethod.POST)
.consumes("application/json")
.produces("application/json"))
.messageConverters(jsonConverter)
.headerMapper(headerMapper)
.requestPayloadType(User.class))
.handle("userService", "createUser")
.get();
}
}Handle file uploads with additional metadata:
@Bean
public IntegrationFlow fileUploadWithMetadataFlow() {
MultipartAwareFormHttpMessageConverter converter =
new MultipartAwareFormHttpMessageConverter();
converter.setMultipartFileReader(new DefaultMultipartFileReader());
return IntegrationFlow
.from(Http.inboundGateway("/api/files/upload")
.requestMapping(m -> m
.methods(HttpMethod.POST)
.consumes("multipart/form-data"))
.messageConverters(converter)
.requestPayloadType(MultiValueMap.class))
.<MultiValueMap<String, Object>>handle((payload, headers) -> {
// Extract file
MultipartFile file = (MultipartFile) payload.getFirst("file");
// Extract metadata
String description = (String) payload.getFirst("description");
String category = (String) payload.getFirst("category");
// Process upload
return fileService.processUpload(file, description, category);
})
.get();
}Propagate custom headers through integration flow:
@Bean
public IntegrationFlow headerPropagationFlow() {
DefaultHttpHeaderMapper inboundMapper =
DefaultHttpHeaderMapper.inboundMapper();
inboundMapper.setInboundHeaderNames("X-*", "Authorization");
DefaultHttpHeaderMapper outboundMapper =
DefaultHttpHeaderMapper.outboundMapper();
outboundMapper.setOutboundHeaderNames("X-*", "Authorization");
return IntegrationFlow
.from(Http.inboundGateway("/api/proxy")
.headerMapper(inboundMapper))
.handle(Http.outboundGateway("https://backend.example.com/api")
.headerMapper(outboundMapper))
.get();
}