skip to content

Spring Integration (EIP)

Spring Integration realizes the enterprise integration patterns as Spring beans: channels, endpoints and service activators, transformers and routers and aggregators, adapters and gateways, and the Java DSL. Interviewers ask about it whenever a system stitches together files, queues and legacy APIs.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

25

In Spring Integration, what is a channel adapter, and what is the difference between an inbound and an outbound channel adapter?

level: juniorimportance: must knowfreq 60%

answer

  1. Adapter = one-way bridge to external system
  2. Inbound = MessageSource + poller (or message-driven push)
  3. Outbound = MessageHandler, returns nothing
  4. Two-way = gateway, not adapter
  5. File/JMS-send = adapter; HTTP/TCP = often gateway

basics

~20 s

A channel adapter connects an external system to a Spring Integration message channel. Inbound adapters bring external data IN as messages; outbound adapters send message payloads OUT to an external system. Both are one-way (no reply).

solid answer

~40 s

A channel adapter is a one-way bridge between an external system (file, JMS, HTTP, TCP, etc.) and a message channel. An inbound channel adapter reads from the outside world and publishes each item as a Spring Message onto a channel; internally it is a MessageSource that a poller polls (or, for message-driven sources like JMS, a listener container pushes). An outbound channel adapter is a MessageHandler that consumes messages from a channel and writes the payload to the external system, returning nothing. The defining trait is directionality plus one-way semantics: no reply flows back. When you need request-reply (send and get an answer), you use a gateway instead of an adapter.

code

java · 24 lines
java
@Configuration
public class FileFlowConfig {

    // INBOUND channel adapter: polls a directory, emits each file as a Message
    @Bean
    public IntegrationFlow inboundFileFlow() {
        return IntegrationFlow
            .from(Files.inboundAdapter(new File("/data/in"))
                        .autoCreateDirectory(true),
                   e -> e.poller(Pollers.fixedDelay(1000)))
            .channel("filesChannel")
            .get();
    }

    // OUTBOUND channel adapter: writes payloads out to disk, returns nothing
    @Bean
    public IntegrationFlow outboundFileFlow() {
        return IntegrationFlow
            .from("toWriteChannel")
            .handle(Files.outboundAdapter(new File("/data/out"))
                        .fileExistsMode(FileExistsMode.REPLACE))
            .get();
    }
}

go deeper

for a junior

Must know: adapter connects to an external system and is one-way; inbound brings data in, outbound sends data out.

for a middle

Should explain the MessageSource+poller (inbound) vs MessageHandler (outbound) internals and the polled-vs-message-driven distinction.

for a senior

Frames adapter-vs-gateway as one-way-vs-request-reply and knows which transports default to which.

for a principal

Reasons about backpressure, poller tuning, and transactional boundaries around inbound adapters and how adapter choice affects delivery guarantees.

**Spring Integration in one paragraph.** Spring Integration implements the Enterprise Integration Patterns (EIP). Components communicate by passing `Message<T>` objects (a payload plus a `MessageHeaders` map) over `MessageChannel`s. Endpoints connect channels to logic or to the outside world. A **channel adapter** is the endpoint type that connects a message channel to an *external system* — a file system, a JMS broker, an HTTP endpoint, a TCP socket, a database, etc. **Directionality.** - An **inbound channel adapter** moves data *from the external world into the flow*. It is backed by a `MessageSource<T>` (e.g. `FileReadingMessageSource`, `JdbcPollingChannelAdapter`). A **poller** (`@Poller` / `PollerMetadata`) calls `receive()` on the source on a schedule; each returned item becomes a `Message` placed on the adapter's output channel. Some inbound adapters are instead **message-driven** (push, not poll) — e.g. the JMS message-driven channel adapter uses a listener container, so there is no poller. - An **outbound channel adapter** moves data *from the flow out to the external world*. It is backed by a `MessageHandler` (e.g. `FileWritingMessageHandler`, `JmsSendingMessageHandler`). It consumes a message and performs a side effect (write file, publish JMS message) and returns **nothing**. **One-way is the key trait.** The word *adapter* signals **one-way** semantics. An inbound adapter only receives; an outbound adapter only sends. Neither produces a reply. This is the crucial contrast with a **gateway**, which is **two-way / request-reply**: an inbound gateway receives a request *and* sends a reply back to the caller; an outbound gateway sends a request *and* waits for a response. Choose adapter for fire-and-forget, gateway for request-reply. HTTP and TCP, being naturally request-reply, are most often used as gateways; file and (send-side) JMS are commonly adapters. **Java DSL vs XML vs annotations.** You can declare adapters three ways: XML namespaces (`<int-file:inbound-channel-adapter>`), the Java DSL (`IntegrationFlow` with `Files.inboundAdapter(...)` / `.handle(...)`), or annotations (`@InboundChannelAdapter` on a bean method returning a `MessageSource`, plus `@Poller`). All three produce the same runtime endpoints. **Gotchas.** - Forgetting a poller on a *polled* inbound adapter means nothing ever fires — there must be a default poller bean or an explicit `@Poller`. Message-driven adapters (JMS listener, TCP receiving) don't need one. - An outbound *adapter* silently discards any return value; if you actually needed the external system's response, you picked the wrong component and want an outbound *gateway*. - Adapters are one-way, so you cannot attach a reply channel to them.

  • When would you use a gateway instead of a channel adapter?
    When you need request-reply: the caller expects a response. An inbound gateway receives a request and returns a reply; an outbound gateway sends a request and waits for the answer. Adapters are one-way only.
  • How does a polled inbound adapter differ from a message-driven one?
    A polled adapter (e.g. file, JDBC) wraps a MessageSource that a poller calls on a schedule. A message-driven adapter (e.g. JMS listener container, TCP receiving adapter) is pushed by the external system, so it needs no poller.

saying these in an interview costs you the question

  • Claiming channel adapters can do request-reply
  • Saying an outbound adapter returns the external system's response
  • Thinking all inbound adapters must be polled (JMS/TCP are message-driven)
  • Confusing adapter (one-way) with gateway (two-way)

context

open as a page

What is a Spring Integration message channel, and what is the difference between point-to-point and publish-subscribe channels?

level: juniorimportance: must knowfreq 62%

basics

~10 s

A message channel is the pipe connecting components; producers send messages to it and consumers receive from it. Point-to-point delivers each message to exactly one consumer; publish-subscribe broadcasts each message to every subscriber.

open as a page

What does @Transformer do in Spring Integration, and how does a transformer endpoint fit into a message flow?

level: juniorimportance: must knowfreq 60%

basics

~20 s

@Transformer marks a method that takes an incoming message (or its payload) and returns a changed version — a new payload or modified headers. It sits between two channels, reading from one and writing the result to the other.

open as a page

What is a @ServiceActivator in Spring Integration, and what does it do?

level: juniorimportance: must knowfreq 35%

basics

~20 s

A @ServiceActivator marks a method (or bean) that consumes messages from an input channel, runs your business logic, and optionally sends the return value to an output channel. It connects a message channel to plain application code.

open as a page

What is the Spring Integration Java DSL and how do you define a basic flow with it?

level: juniorimportance: must knowfreq 60%

basics

~10 s

It's a fluent Java API for building Spring Integration message pipelines instead of XML. You define an IntegrationFlow bean starting with IntegrationFlow.from(a source), then chain steps like .transform() and .handle().

open as a page

What does @MessagingGateway do, and how does it let application code call an integration flow through a plain Java interface?

level: middleimportance: must knowfreq 55%

basics

~20 s

@MessagingGateway on an interface makes Spring create a proxy. Calling an interface method turns the arguments into a Message sent to a request channel; the reply Message's payload is returned. Your code never touches MessageChannel or Message APIs.

open as a page

Compare DirectChannel and QueueChannel: threading, buffering, polling, and transaction behaviour.

level: middleimportance: must knowfreq 55%

basics

~20 s

DirectChannel runs the consumer synchronously on the sender's thread with no buffer, so send and handling share one thread and transaction. QueueChannel buffers messages and needs a poller; the consumer runs on a separate poller thread later.

open as a page

How does @Router implement content-based routing in Spring Integration, and what is HeaderValueRouter?

level: middleimportance: must knowfreq 55%

basics

~20 s

@Router marks a method that inspects a message and returns the name(s) of the channel(s) to send it to — content-based routing. HeaderValueRouter is a built-in that picks the channel based on the value of a specified message header.

open as a page

Explain the difference between event-driven and polling consumers in Spring Integration. When does each get used?

level: middleimportance: must knowfreq 32%

basics

~20 s

An event-driven consumer subscribes to a channel and is invoked immediately when a message is sent (push). A polling consumer periodically checks a channel for messages (pull). Which you get depends on whether the input channel is subscribable or pollable.

open as a page

Explain the difference between .transform(), .filter(), .route(), and .handle() in the Integration Java DSL.

level: middleimportance: must knowfreq 55%

basics

~20 s

transform changes the payload and passes it on; filter drops messages that fail a boolean test; route sends messages to different channels/sub-flows based on a value; handle consumes the message to do work, often ending the flow.

open as a page

Explain @Splitter and @Aggregator, and how correlation and release strategies tie a split flow back together.

level: seniorimportance: must knowfreq 50%

basics

~20 s

@Splitter breaks one message into many (e.g. a list into per-item messages). @Aggregator collects related messages back into one. They pair up: the aggregator uses a correlation strategy to group messages and a release strategy to decide when a group is complete and ready to emit.

open as a page

How does a file inbound channel adapter work, and how do you stop it from re-processing files it has already picked up?

level: middleimportance: should knowfreq 40%

basics

~20 s

A file inbound channel adapter uses FileReadingMessageSource, polled on a schedule, to emit each new file as a Message. To avoid re-reading the same file, add a FileListFilter such as AcceptOnceFileListFilter (in-memory) or a persistent one backed by a MetadataStore.

open as a page

What is @Filter in Spring Integration, and how does it differ from a router and a transformer?

level: middleimportance: should knowfreq 45%

basics

~20 s

@Filter marks a method returning a boolean: true forwards the message unchanged to the output channel, false drops it. It's a keep-or-drop gate — unlike a router (which picks among destinations) or a transformer (which changes the message).

open as a page

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%

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.

open as a page

What does ExecutorChannel do, and how does it differ from DirectChannel and QueueChannel with respect to threading and transactions?

level: seniorimportance: should knowfreq 40%

basics

~20 s

ExecutorChannel is a subscribable point-to-point channel that hands each message to a TaskExecutor, so the handler runs asynchronously on an executor thread instead of the sender's thread — but unlike QueueChannel it has no buffer/poller.

open as a page

Describe AbstractEndpoint and how endpoint lifecycle connects a MessageHandler to its channel.

level: seniorimportance: should knowfreq 16%

basics

~20 s

AbstractEndpoint is the base class for consumers; it implements Spring's SmartLifecycle. On start() it wires the handler to the channel (an EventDrivenConsumer subscribes; a PollingConsumer schedules polling). On stop() it unsubscribes or cancels the poll. autoStartup and phase control when it starts.

open as a page

How do PollerMetadata and @Poller configure a polling consumer, and what is the default-poller mechanism?

level: seniorimportance: should knowfreq 22%

basics

~20 s

PollerMetadata is a bean holding a poller's settings — trigger, maxMessagesPerPoll, receiveTimeout, task executor, transaction/advice, error handler. @Poller is the annotation form on an endpoint. If none is given, Spring uses a bean named the default poller; if that's missing too, startup fails.

open as a page

How does a @Bean-returned IntegrationFlow get turned into running channels and endpoints, and what advantages does it have over XML configuration?

level: seniorimportance: should knowfreq 40%

basics

~10 s

Spring Integration's IntegrationFlowBeanPostProcessor detects the IntegrationFlow bean, unpacks its endpoints and channels, and registers each as its own bean in the context. Versus XML you get compile-time safety, DI, lambdas, and top-to-bottom readability.

open as a page

In a DSL flow, when does processing switch threads or become asynchronous, and how do you control that?

level: seniorimportance: should knowfreq 35%

basics

~20 s

By default consecutive steps are joined by DirectChannels that run synchronously on the caller's thread. To go async or switch threads you insert an explicit .channel() that is an ExecutorChannel (thread pool) or a QueueChannel (with a poller).

open as a page

Explain ChannelInterceptor: its callbacks, how it applies to subscribable vs pollable channels, and what you'd use it for.

level: principalimportance: should knowfreq 33%

basics

~20 s

A ChannelInterceptor is a hook attached to a channel that fires around send and receive. Its callbacks (preSend, postSend, afterSendCompletion, preReceive, postReceive, afterReceiveCompletion) let you inspect, transform, filter, log, or measure messages without changing endpoints. Receive callbacks only apply to pollable channels.

open as a page

As a principal engineer, how would you design a reliable aggregator: correlation-key lifecycle, timeouts, persistence, and handling stragglers/duplicates?

level: principalimportance: should knowfreq 30%

basics

~20 s

Use a persistent MessageGroupStore so partial groups survive restarts, set a group-timeout so incomplete groups don't leak, decide via send-partial-result-on-expiry whether to emit or discard partial groups, and configure expire-groups-upon-completion plus idempotency to handle late/duplicate messages for a reused correlation key.

open as a page

What are PriorityChannel and RendezvousChannel, and when would you use each?

level: seniorimportance: nice to knowfreq 26%

basics

~20 s

Both are pollable point-to-point channels. PriorityChannel is a QueueChannel that orders buffered messages by priority instead of FIFO. RendezvousChannel is a zero-capacity queue where the sender blocks until a receiver takes the message (direct handoff).

open as a page

Explain how Spring Integration bridges raw TCP sockets — connection factories, the adapter-pair vs gateway choice, and how replies are correlated on a shared server connection.

level: principalimportance: nice to knowfreq 18%

basics

~20 s

TCP endpoints share a connection factory (server or client) that owns sockets plus a serializer/deserializer defining message framing. Use TcpInboundGateway/TcpOutboundGateway for request-reply, or a TcpReceivingChannelAdapter + TcpSendingMessageHandler pair sharing one factory for asynchronous flows, correlating replies by the connection id header.

open as a page

In a Spring Integration flow, how do threading and error propagation differ between an event-driven service activator and a polling one, and how would you design for reliability?

level: principalimportance: nice to knowfreq 12%

basics

~20 s

With a DirectChannel the handler runs on the sender's thread, so exceptions propagate straight back to the caller in the caller's transaction. With a polling consumer (or ExecutorChannel) the handler runs on a scheduler/pool thread, so errors go to an error channel or the poller's errorHandler instead. Design reliability with transactional pollers, error channels, and retry advice.

open as a page

As an architect, how do you decide whether to use Spring Integration Java DSL versus plain service classes or a dedicated message broker, and how do you keep flows maintainable?

level: principalimportance: nice to knowfreq 20%

basics

~20 s

Use the DSL for in-JVM EIP-style orchestration across adapters (files, HTTP, JDBC, Kafka) where routing/transforming/filtering adds value. For simple call chains, plain services are clearer; for cross-service, durable, scalable messaging, use a real broker. Keep flows small and composed from reusable sub-flows.

open as a page