skip to content

Contrast an inbound gateway with an outbound gateway using HTTP as the example, and explain why HTTP is usually modeled as a gateway rather than a channel adapter.

level: seniorimportance: should knowfreq 35%

answer

  1. Gateway = request + reply; adapter = one-way
  2. Inbound HTTP gateway = server: request→flow→HTTP response
  3. Outbound HTTP gateway = client: message→HTTP call→reply message
  4. HttpRequestHandlingMessagingGateway vs HttpRequestExecutingMessageHandler
  5. One-way HTTP adapter throws the response away

basics

~20 s

HTTP is request-reply, so it maps to gateways. An inbound HTTP gateway (HttpRequestHandlingMessagingGateway) receives an HTTP request, runs the flow, and writes the reply as the HTTP response. An outbound HTTP gateway (HttpRequestExecutingMessageHandler) calls a remote HTTP endpoint and puts the response back on the flow.

solid answer

~40 s

A gateway is the two-way endpoint: it both receives a request and returns a reply. Inbound vs outbound is about which side initiates. An inbound HTTP gateway (`HttpRequestHandlingMessagingGateway`, exposed via the HTTP inbound-gateway) accepts an incoming HTTP request, converts it to a Message, sends it into the flow, waits for the reply Message, and serializes that as the HTTP response — it is a server endpoint. An outbound HTTP gateway (`HttpRequestExecutingMessageHandler`) takes a Message from the flow, performs an HTTP call to a remote server, and emits the response as a reply Message back into the flow — it is a client. HTTP is inherently synchronous request-reply, so a one-way channel adapter would throw the response away; you only use the HTTP outbound *adapter* for genuine fire-and-forget where the response is irrelevant.

code

java · 22 lines
java
@Bean
public IntegrationFlow inboundHttp() {
    // SERVER: receives HTTP request, returns the flow's reply as the HTTP response
    return IntegrationFlow
        .from(Http.inboundGateway("/api/quote")
                    .requestMapping(m -> m.methods(HttpMethod.POST))
                    .requestPayloadType(QuoteRequest.class)
                    .replyTimeout(3000))
        .handle("quoteService", "quote")   // its return becomes the HTTP 200 body
        .get();
}

@Bean
public IntegrationFlow outboundHttp() {
    // CLIENT: calls a remote HTTP endpoint, puts the response back on the flow
    return IntegrationFlow.from("ratesRequest")
        .handle(Http.outboundGateway("https://rates.example.com/v1/rate")
                    .httpMethod(HttpMethod.POST)
                    .expectedResponseType(Rate.class))   // reply payload = Rate
        .channel("ratesReply")
        .get();
}

go deeper

for a junior

Knows a gateway is two-way and HTTP has requests and responses.

for a middle

Distinguishes inbound (server) vs outbound (client) gateways and names the HTTP handler classes.

for a senior

Must explain why HTTP maps to gateways not adapters, the reply/timeout/error-channel mechanics, and when the one-way adapter is still appropriate.

for a principal

Generalizes the adapter-vs-gateway decision across HTTP/JMS/TCP, reasons about synchronous-blocking vs reactive HTTP, backpressure, and error-to-response contracts at API boundaries.

**Gateway = request-reply endpoint.** Where a channel adapter is one-way, a **gateway** is two-way. Two orthogonal axes describe it: **direction** (inbound = data enters the flow from outside; outbound = flow reaches out) and **initiator** (who starts the exchange). A gateway always has *both* a request path and a reply path. **Inbound HTTP gateway (server side).** Backed by `HttpRequestHandlingMessagingGateway` (the DSL `Http.inboundGateway(...)`). An external client makes an HTTP request; the gateway maps method, headers, and body to a `Message` (payload from the body via `HttpMessageConverter`s, plus `MessageHeaders` for HTTP headers/URI variables), sends it to a **request channel**, then **waits** for a reply Message and writes it back as the HTTP **response** (status, headers, body). Because it returns a response to the caller, it is a *gateway*, not an adapter. Contrast `Http.inboundChannelAdapter(...)` (`HttpRequestHandlingController`/one-way), which acknowledges with a fixed status and does *not* send a business reply — used when the HTTP call is fire-and-forget (e.g. a webhook you 200-ack immediately). **Outbound HTTP gateway (client side).** Backed by `HttpRequestExecutingMessageHandler` (DSL `Http.outboundGateway(url)`), which uses a `RestTemplate`/`RestClient` under the hood. It consumes a Message, issues the HTTP request to the remote URL (method, body, headers derived from the message/expressions), receives the HTTP response, and produces a **reply Message** (payload = response body, headers = response headers/status) back onto the flow. Its one-way sibling is `HttpRequestExecutingMessageHandler` used as an outbound *adapter* — same call, but the response is discarded because the flow doesn't need it. **Why HTTP ⇒ gateway.** HTTP's semantics are inherently synchronous request/response: every request yields a status and (usually) a body. If you modeled the client side as a one-way **outbound channel adapter**, the framework would drop the HTTP response — you'd lose status codes and payloads, unable to detect 4xx/5xx meaningfully at the flow level. If you modeled the server side as a one-way **inbound channel adapter**, you couldn't return a computed response body, only a canned ack. So the natural mapping is *gateway on both ends*, reserving the adapter form for true fire-and-forget. **Reply/timeout mechanics.** Inbound gateways have a `replyTimeout`: if the flow doesn't produce a reply in time, the gateway returns a timeout/no-content response. Outbound gateways carry the transport's own timeouts (connect/read on the `RestTemplate`/`ClientHttpRequestFactory`) plus optional `expectedResponseType`/`extractPayload`. For inbound, `errorChannel`/error handling lets you convert downstream exceptions into an HTTP error response instead of a raw 500. **Same pattern, other transports.** JMS: `JmsInboundGateway` (consumes a request from a queue with a `JMSReplyTo`, sends the reply back) vs `JmsOutboundGateway` (sends a request and correlates the reply, using a reply queue and `JMSCorrelationID`). TCP: `TcpInboundGateway` / `TcpOutboundGateway`. The inbound-vs-outbound and gateway-vs-adapter reasoning is identical across transports — HTTP is just the most intuitive example because its request-reply nature is obvious. **When to use adapter vs gateway.** - Inbound gateway: you must return a computed response to the caller (REST endpoint driven by a flow). - Inbound adapter: you only need to accept-and-ack (webhook ingestion, one-way notification). - Outbound gateway: you need the remote system's response back in the flow (enrich, branch on status). - Outbound adapter: fire-and-forget notification where the response is genuinely irrelevant.

  • What breaks if you use an HTTP outbound channel adapter (one-way) instead of an outbound gateway?
    The HTTP call still happens, but the response — status code and body — is discarded and never returned to the flow. You can't enrich from or branch on the remote response, and you lose visibility into 4xx/5xx beyond a thrown exception. Use the gateway when the response matters.
  • How is the reply routed back on an inbound HTTP gateway?
    The gateway sets a temporary reply channel on the request message (like @MessagingGateway). The flow's terminating handler replies to it; the gateway serializes that reply Message into the HTTP response. If no reply arrives within replyTimeout, it returns a timeout response.
  • Give the JMS equivalents of inbound and outbound gateways.
    JmsInboundGateway consumes a request message (honoring JMSReplyTo) and sends the reply back to that destination; JmsOutboundGateway sends a request to a queue and correlates the reply (via a reply queue and JMSCorrelationID).

saying these in an interview costs you the question

  • Calling HTTP endpoints 'adapters' and expecting to still read the response
  • Confusing inbound (server) with outbound (client) direction
  • Thinking an inbound adapter can return a computed HTTP body
  • Assuming the inbound gateway never times out waiting for a reply

context