Components for executing HTTP requests from Spring Integration messages. Outbound handlers use Spring's RestTemplate to make HTTP calls, supporting both one-way (fire-and-forget) and request-reply patterns with extensive configuration options for URIs, HTTP methods, headers, and response handling.
Required Dependencies:
spring-web (for RestTemplate)spring-integration-core is requiredDefault Behaviors:
expectReply=true by default (request-reply pattern)extractPayload=true by default (only payload sent as request body)extractResponseBody=true by default (only body in reply, not full ResponseEntity)transferCookies=false by defaultThreading Model:
ClientHttpRequestFactory (connect timeout, read timeout)URI Configuration:
{variableName}setUriVariableExpressions() or setUriVariablesExpression()Response Handling:
expectedResponseType required when expectReply=trueClass<?>, ParameterizedTypeReference<?>, or SpEL ExpressionextractResponseBody=false, returns full ResponseEntity<?>extractResponseBody=true, returns only response bodyExceptions:
HttpClientErrorException - 4xx HTTP errors (wrapped in MessagingException)HttpServerErrorException - 5xx HTTP errors (wrapped in MessagingException)HttpMessageNotReadableException - response conversion failuresHttpMessageNotWritableException - request conversion failuresMessageTimeoutException - if reply timeout exceeded (when expectReply=true)Edge Cases:
expectReply=false, handler returns null immediately after sending requestIllegalArgumentExceptionIllegalArgumentExceptionextractResponseBody=true returns nullPerformance Considerations:
The primary message handler for executing HTTP requests using RestTemplate. Processes messages from Spring Integration flows and makes HTTP calls to external services, with optional response handling for request-reply scenarios.
public class HttpRequestExecutingMessageHandler
extends AbstractHttpRequestExecutingMessageHandler {
/**
* Creates handler for static URI.
*
* @param uri the target URI
*/
public HttpRequestExecutingMessageHandler(URI uri);
/**
* Creates handler for URI string.
*
* @param uri the target URI as string
*/
public HttpRequestExecutingMessageHandler(String uri);
/**
* Creates handler with SpEL expression for dynamic URI evaluation.
* Expression is evaluated against each message.
*
* @param uriExpression the URI expression
*/
public HttpRequestExecutingMessageHandler(Expression uriExpression);
/**
* Creates handler with URI and custom RestTemplate.
*
* @param uri the target URI as string
* @param restTemplate the RestTemplate to use
*/
public HttpRequestExecutingMessageHandler(
String uri,
RestTemplate restTemplate);
/**
* Creates handler with URI expression and custom RestTemplate.
*
* @param uriExpression the URI expression
* @param restTemplate the RestTemplate to use
*/
public HttpRequestExecutingMessageHandler(
Expression uriExpression,
RestTemplate restTemplate);
/**
* Sets ClientHttpRequestFactory for customizing HTTP client behavior.
* Allows configuration of timeouts, connection pooling, etc.
*
* @param requestFactory the request factory
*/
public void setRequestFactory(ClientHttpRequestFactory requestFactory);
/**
* Sets ResponseErrorHandler for custom HTTP error handling.
* Default handler throws exceptions for 4xx and 5xx responses.
*
* @param errorHandler the error handler
*/
public void setErrorHandler(ResponseErrorHandler errorHandler);
/**
* Sets HttpMessageConverters for request/response conversion.
* Replaces default converters provided by RestTemplate.
*
* @param messageConverters the list of message converters
*/
public void setMessageConverters(
List<HttpMessageConverter<?>> messageConverters);
/**
* Sets encoding mode for URI template processing.
*
* @param encodingMode the encoding mode
*/
public void setEncodingMode(
DefaultUriBuilderFactory.EncodingMode encodingMode);
public String getComponentType();
}Usage Example - Basic GET Request:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.http.HttpMethod;
@Configuration
public class OutboundGetConfig {
@Bean
public HttpRequestExecutingMessageHandler getDataHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/data/{id}");
handler.setHttpMethod(HttpMethod.GET);
handler.setExpectedResponseType(DataResponse.class);
// Configure URI variables
SpelExpressionParser parser = new SpelExpressionParser();
Map<String, Expression> uriVars = new HashMap<>();
uriVars.put("id", parser.parseExpression("payload.dataId"));
handler.setUriVariableExpressions(uriVars);
return handler;
}
}Usage Example - POST Request with JSON:
@Bean
public HttpRequestExecutingMessageHandler postOrderHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/orders");
handler.setHttpMethod(HttpMethod.POST);
handler.setExpectedResponseType(OrderResponse.class);
// Extract payload for request body
handler.setExtractPayload(true);
// Configure custom request factory with timeouts
SimpleClientHttpRequestFactory factory =
new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000);
factory.setReadTimeout(10000);
handler.setRequestFactory(factory);
return handler;
}Usage Example - Dynamic URI and Method:
@Bean
public HttpRequestExecutingMessageHandler dynamicHandler() {
SpelExpressionParser parser = new SpelExpressionParser();
// Dynamic URI based on message headers
Expression uriExpression = parser.parseExpression(
"headers['target_url']");
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(uriExpression);
// Dynamic HTTP method
handler.setHttpMethodExpression(
parser.parseExpression("headers['http_method']"));
// Dynamic response type
handler.setExpectedResponseTypeExpression(
parser.parseExpression("headers['response_type']"));
handler.setExpectReply(true);
return handler;
}Base class for HTTP outbound handlers providing common configuration and functionality. This abstract class can be extended to create custom HTTP request executors with specialized behavior.
public abstract class AbstractHttpRequestExecutingMessageHandler
extends AbstractReplyProducingMessageHandler {
/**
* Creates handler with URI expression.
*
* @param uriExpression the URI expression
*/
protected AbstractHttpRequestExecutingMessageHandler(
Expression uriExpression);
/**
* Sets URI encoding mode for template variable encoding.
* Default: TEMPLATE_AND_VALUES.
*
* @param encodingMode the encoding mode
*/
public void setEncodingMode(
DefaultUriBuilderFactory.EncodingMode encodingMode);
/**
* Sets SpEL expression to determine HttpMethod dynamically.
* Expression is evaluated against each message.
*
* @param httpMethodExpression the HTTP method expression
*/
public void setHttpMethodExpression(Expression httpMethodExpression);
/**
* Sets the HttpMethod for all requests.
* Default: POST.
*
* @param httpMethod the HTTP method
*/
public void setHttpMethod(HttpMethod httpMethod);
/**
* Controls whether message payload should be extracted for request body.
* When false, entire Message is used (rarely needed).
* Default: true.
*
* @param extractPayload true to extract payload
*/
public void setExtractPayload(boolean extractPayload);
/**
* Sets charset for converting String payloads to bytes.
* Default: UTF-8.
*
* @param charset the charset name
*/
public void setCharset(String charset);
/**
* Returns whether reply Message is expected.
*
* @return true if reply is expected
*/
public boolean isExpectReply();
/**
* Sets whether reply Message is expected (request-reply vs fire-and-forget).
* Default: true.
*
* @param expectReply true for request-reply
*/
public void setExpectReply(boolean expectReply);
/**
* Sets expected response type for conversion.
*
* @param expectedResponseType the response type class
*/
public void setExpectedResponseType(Class<?> expectedResponseType);
/**
* Sets SpEL expression to determine response type dynamically.
* Expression is evaluated against each message.
*
* @param expectedResponseTypeExpression the response type expression
*/
public void setExpectedResponseTypeExpression(
Expression expectedResponseTypeExpression);
/**
* Sets HeaderMapper for mapping between Message and HTTP headers.
*
* @param headerMapper the header mapper
*/
public void setHeaderMapper(HeaderMapper<HttpHeaders> headerMapper);
/**
* Sets Map of SpEL expressions for URI variable substitution.
* Each expression is evaluated against the message.
*
* @param uriVariableExpressions map of variable name to expression
*/
public void setUriVariableExpressions(
Map<String, Expression> uriVariableExpressions);
/**
* Sets SpEL expression to evaluate a Map of URI variables.
* Expression should return Map<String, ?>.
*
* @param uriVariablesExpression the URI variables expression
*/
public void setUriVariablesExpression(Expression uriVariablesExpression);
/**
* Controls whether Set-Cookie headers from responses should be
* transferred as Cookie headers in subsequent requests.
* Useful for maintaining sessions across requests.
* Default: false.
*
* @param transferCookies true to transfer cookies
*/
public void setTransferCookies(boolean transferCookies);
/**
* Sets whether to trust SpEL expressions from message headers.
* When false, expressions are not evaluated (security).
* Default: false.
*
* @param trustedSpel true to trust SpEL
*/
public void setTrustedSpel(boolean trustedSpel);
/**
* Controls whether ResponseEntity body should be extracted for reply.
* When false, entire ResponseEntity (with status, headers) is returned.
* Default: true.
*
* @param extractResponseBody true to extract body only
*/
public void setExtractResponseBody(boolean extractResponseBody);
public IntegrationPatternType getIntegrationPatternType();
/**
* Abstract method to perform HTTP exchange.
* Must be implemented by subclasses.
*
* @param uri the target URI (String or URI)
* @param httpMethod the HTTP method
* @param httpRequest the HTTP request entity
* @param expectedResponseType the expected response type
* @param requestMessage the original message
* @param uriVariables the URI variables map
* @return the response entity
*/
protected abstract Object exchange(
Object uri,
HttpMethod httpMethod,
HttpEntity<?> httpRequest,
Object expectedResponseType,
Message<?> requestMessage,
Map<String, ?> uriVariables);
}Configure RestTemplate with custom settings for connection pooling, timeouts, and SSL:
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
@Bean
public HttpRequestExecutingMessageHandler customRestTemplateHandler() {
// Configure connection pooling
PoolingHttpClientConnectionManager connectionManager =
new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(100);
connectionManager.setDefaultMaxPerRoute(20);
// Build HTTP client
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
// Create request factory with timeouts
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory(httpClient);
factory.setConnectTimeout(5000);
factory.setReadTimeout(10000);
// Create RestTemplate
RestTemplate restTemplate = new RestTemplate(factory);
// Configure message converters
List<HttpMessageConverter<?>> converters = new ArrayList<>();
converters.add(new MappingJackson2HttpMessageConverter());
converters.add(new StringHttpMessageConverter());
restTemplate.setMessageConverters(converters);
// Create handler
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/data",
restTemplate);
handler.setHttpMethod(HttpMethod.POST);
handler.setExpectedResponseType(String.class);
return handler;
}Implement custom error handling for HTTP responses:
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.ResponseErrorHandler;
@Bean
public HttpRequestExecutingMessageHandler errorHandlingHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/data");
// Custom error handler
handler.setErrorHandler(new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse response)
throws IOException {
int statusCode = response.getStatusCode().value();
return statusCode >= 400;
}
@Override
public void handleError(ClientHttpResponse response)
throws IOException {
int statusCode = response.getStatusCode().value();
String statusText = response.getStatusText();
if (statusCode >= 500) {
throw new ServerErrorException(
"Server error: " + statusCode + " " + statusText);
} else if (statusCode >= 400) {
throw new ClientErrorException(
"Client error: " + statusCode + " " + statusText);
}
}
});
handler.setHttpMethod(HttpMethod.GET);
handler.setExpectedResponseType(String.class);
return handler;
}Configure complex URI variable substitution with SpEL expressions:
@Bean
public HttpRequestExecutingMessageHandler uriVariableHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/{version}/users/{userId}/orders/{orderId}");
SpelExpressionParser parser = new SpelExpressionParser();
Map<String, Expression> uriVars = new HashMap<>();
// Extract from payload
uriVars.put("userId", parser.parseExpression("payload.userId"));
uriVars.put("orderId", parser.parseExpression("payload.orderId"));
// Extract from headers
uriVars.put("version", parser.parseExpression("headers['api-version']"));
handler.setUriVariableExpressions(uriVars);
handler.setHttpMethod(HttpMethod.GET);
handler.setExpectedResponseType(Order.class);
return handler;
}Use a single expression to provide all URI variables:
@Bean
public HttpRequestExecutingMessageHandler uriVarsExpressionHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/{type}/{id}");
SpelExpressionParser parser = new SpelExpressionParser();
// Expression returns Map<String, Object>
handler.setUriVariablesExpression(
parser.parseExpression("payload.uriParameters"));
handler.setHttpMethod(HttpMethod.GET);
handler.setExpectedResponseType(String.class);
return handler;
}Configure which headers are mapped from messages to HTTP requests:
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
@Bean
public HttpRequestExecutingMessageHandler headerMappingHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/data");
// Configure header mapper
DefaultHttpHeaderMapper headerMapper =
DefaultHttpHeaderMapper.outboundMapper();
// Map specific headers
headerMapper.setOutboundHeaderNames(
"Content-Type",
"Accept",
"Authorization",
"X-Custom-*"); // Pattern for custom headers
// Set prefix for user-defined headers
headerMapper.setUserDefinedHeaderPrefix("X-");
handler.setHeaderMapper(headerMapper);
handler.setHttpMethod(HttpMethod.POST);
handler.setExpectedResponseType(String.class);
return handler;
}Enable cookie transfer to maintain sessions across requests:
@Bean
public HttpRequestExecutingMessageHandler sessionHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/data");
// Enable cookie transfer
handler.setTransferCookies(true);
handler.setHttpMethod(HttpMethod.GET);
handler.setExpectedResponseType(String.class);
return handler;
}When transferCookies is enabled, Set-Cookie headers from responses are automatically converted to Cookie headers in subsequent requests, maintaining session state.
Access complete response including status code and headers:
@Bean
public HttpRequestExecutingMessageHandler fullResponseHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/data");
handler.setHttpMethod(HttpMethod.GET);
// Don't extract body - return full ResponseEntity
handler.setExtractResponseBody(false);
// Response type is ResponseEntity<String>
handler.setExpectedResponseType(String.class);
return handler;
}The reply message will contain a ResponseEntity<String> as payload, allowing access to status code, headers, and body.
Configure one-way communication without expecting responses:
@Bean
public HttpRequestExecutingMessageHandler fireAndForgetHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/events");
handler.setHttpMethod(HttpMethod.POST);
// Don't expect reply
handler.setExpectReply(false);
// No response type needed
handler.setExtractPayload(true);
return handler;
}When expectReply is false, the handler doesn't wait for or process the response, returning null immediately after sending the request.
Determine response type dynamically based on message content:
@Bean
public HttpRequestExecutingMessageHandler dynamicResponseTypeHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/data");
SpelExpressionParser parser = new SpelExpressionParser();
// Dynamic response type based on message header
handler.setExpectedResponseTypeExpression(
parser.parseExpression(
"headers['response_format'] == 'json' ? " +
"T(com.example.JsonResponse) : T(com.example.XmlResponse)"));
handler.setHttpMethod(HttpMethod.GET);
handler.setExpectReply(true);
return handler;
}Handle generic response types with ParameterizedTypeReference:
import org.springframework.core.ParameterizedTypeReference;
@Bean
public HttpRequestExecutingMessageHandler genericResponseHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/users");
handler.setHttpMethod(HttpMethod.GET);
// For List<User> response
ParameterizedTypeReference<List<User>> responseType =
new ParameterizedTypeReference<List<User>>() {};
handler.setExpectedResponseType(responseType);
return handler;
}Configure how URI templates are encoded:
import org.springframework.web.util.DefaultUriBuilderFactory;
@Bean
public HttpRequestExecutingMessageHandler encodingHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/search?q={query}");
// Configure URI encoding mode
handler.setEncodingMode(
DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
SpelExpressionParser parser = new SpelExpressionParser();
Map<String, Expression> uriVars = new HashMap<>();
uriVars.put("query", parser.parseExpression("payload.searchTerm"));
handler.setUriVariableExpressions(uriVars);
handler.setHttpMethod(HttpMethod.GET);
handler.setExpectedResponseType(String.class);
return handler;
}Available encoding modes:
TEMPLATE_AND_VALUES: Encode both template and variable valuesVALUES_ONLY: Encode only variable values (template already encoded)URI_COMPONENT: Encode each URI component separatelyNONE: No encodingSet charset for String payload conversion:
@Bean
public HttpRequestExecutingMessageHandler charsetHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/data");
handler.setHttpMethod(HttpMethod.POST);
// Set charset for String to byte[] conversion
handler.setCharset("ISO-8859-1");
handler.setExpectedResponseType(String.class);
return handler;
}Complete integration flow with HTTP request-reply:
@Bean
public IntegrationFlow httpRequestReplyFlow() {
return IntegrationFlow
.from("inputChannel")
.handle(outboundGatewayHandler())
.transform(response -> processResponse(response))
.channel("outputChannel")
.get();
}
@Bean
public HttpRequestExecutingMessageHandler outboundGatewayHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/process");
handler.setHttpMethod(HttpMethod.POST);
handler.setExpectReply(true);
handler.setExpectedResponseType(String.class);
return handler;
}Integration flow with HTTP error handling:
@Bean
public IntegrationFlow httpWithErrorHandlingFlow() {
return IntegrationFlow
.from("inputChannel")
.handle(outboundHandler(),
e -> e.advice(retryAdvice()))
.transform(response -> processResponse(response))
.channel("outputChannel")
.get();
}
@Bean
public RequestHandlerRetryAdvice retryAdvice() {
RequestHandlerRetryAdvice advice = new RequestHandlerRetryAdvice();
RetryTemplate retryTemplate = new RetryTemplate();
// Retry on HTTP errors
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3);
retryTemplate.setRetryPolicy(retryPolicy);
// Exponential backoff
ExponentialBackOffPolicy backOffPolicy =
new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(1000);
backOffPolicy.setMultiplier(2.0);
backOffPolicy.setMaxInterval(10000);
retryTemplate.setBackOffPolicy(backOffPolicy);
advice.setRetryTemplate(retryTemplate);
return advice;
}Enrich messages with data from HTTP service:
@Bean
public IntegrationFlow enrichmentFlow() {
return IntegrationFlow
.from("orderChannel")
.enrich(e -> e
.requestChannel("lookupCustomerChannel")
.requestPayload(m -> m.getPayload().getCustomerId())
.propertyExpression("customerData", "payload"))
.handle("orderService", "processOrder")
.get();
}
@Bean
public IntegrationFlow customerLookupFlow() {
return IntegrationFlow
.from("lookupCustomerChannel")
.handle(customerLookupHandler())
.get();
}
@Bean
public HttpRequestExecutingMessageHandler customerLookupHandler() {
HttpRequestExecutingMessageHandler handler =
new HttpRequestExecutingMessageHandler(
"https://api.example.com/customers/{id}");
SpelExpressionParser parser = new SpelExpressionParser();
Map<String, Expression> uriVars = new HashMap<>();
uriVars.put("id", parser.parseExpression("payload"));
handler.setUriVariableExpressions(uriVars);
handler.setHttpMethod(HttpMethod.GET);
handler.setExpectedResponseType(Customer.class);
return handler;
}