skip to content

Endpoints & Service Activators

Endpoints connect handlers to channels, either event-driven or polled through a configured poller, with a managed lifecycle. Interviewers ask about poller configuration because it silently sets your throughput ceiling.

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

explore

questions

5

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

level: juniorimportance: must knowfreq 35%

answer

  1. method -> ServiceActivatingHandler (a MessageHandler)
  2. inputChannel / outputChannel / replyChannel header
  3. payload, @Header, whole Message mapping
  4. void/null return = terminal; requiresReply -> ReplyRequiredException
  5. general-purpose endpoint (vs transformer/filter/router)

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.

solid answer

~40 s

@ServiceActivator is the annotation that turns an ordinary bean method into a message endpoint. You put it on a method with attributes like inputChannel and outputChannel. Spring wraps that method in a ServiceActivatingHandler (a MessageHandler), and creates an endpoint that reads Messages from the input channel, invokes your method, and — if the method returns a value — sends the result to the outputChannel, or to the replyChannel header if no outputChannel is set. Method arguments are populated from the Message: the whole Message, its payload, or headers (via @Header/@Payload). It is the primary way to plug business logic into an integration flow. If requiresReply=true and the method returns null/void, it throws ReplyRequiredException.

code

java · 12 lines
java
@Component
public class OrderService {

    // Reads Messages from "orders", runs logic, sends result to "receipts".
    @ServiceActivator(inputChannel = "orders", outputChannel = "receipts")
    public Receipt handle(@Payload Order order,
                          @Header("tenantId") String tenantId) {
        return process(order, tenantId); // return value becomes the next Message payload
    }

    private Receipt process(Order o, String t) { /* ... */ return new Receipt(); }
}

go deeper

for a junior

Know it connects a channel to a method and can send the return value onward.

for a middle

Explain parameter mapping (payload/@Header/Message) and the outputChannel vs replyChannel-header behaviour.

for a senior

Discuss ServiceActivatingHandler/MessagingMethodInvokerHelper, requiresReply, and threading implications.

for a principal

Reason about it as one uniform MessageHandler abstraction among endpoint types and how advice chains/error handling attach.

## What it is Spring Integration models data flow as **Messages** (payload + headers) moving through **MessageChannels**. A **service activator** is the endpoint that connects a channel to a piece of business logic — it "activates" a service when a message arrives. `@ServiceActivator` is placed on a bean **method**. At startup, Spring Integration's annotation post-processor wraps that method in a **`ServiceActivatingHandler`**, which is a `MessageHandler`. The method invocation itself is done reflectively through **`MessagingMethodInvokerHelper`**, which maps the incoming `Message` onto your method parameters. ## Key attributes - **`inputChannel`** — the channel the endpoint reads from. This is what causes an endpoint (a `PollingConsumer` or `EventDrivenConsumer`) to be created and wired to the handler. - **`outputChannel`** — where the return value is sent. If omitted, the result is sent to the channel named in the message's **`replyChannel`** header (enabling request/reply). - **`requiresReply`** — if `true` and the method returns `null` or `void`, a **`ReplyRequiredException`** is thrown. - **`sendTimeout`**, **`async`**, **`poller`**, **`adviceChain`**, **`order`** — additional tuning. ## Parameter mapping Your method can take: the whole `Message<?>`, just the payload (auto-converted to the parameter type), specific headers via `@Header("name")`, all headers via `@Headers Map`, or `@Payload` with a SpEL expression. If it returns `void` or `null`, the flow ends there (a one-way/terminal endpoint). ## Where it sits A service activator is one of several endpoint types (transformer, filter, router, splitter, aggregator). It is the general-purpose one: any method that takes a message/payload and optionally returns a result. ## Gotchas - Forgetting an `outputChannel` on a method that returns a value is fine **only** if a `replyChannel` header exists; otherwise you get a `DestinationResolutionException` ("no output-channel or replyChannel header available"). - If the input channel is a **pollable** channel (e.g., `QueueChannel`), the endpoint is a `PollingConsumer` and you **must** supply a poller (see `@Poller`/default poller) or startup fails. - The handler runs on the thread that delivers the message — for a subscribable channel that's the **sender's** thread (synchronous), which surprises people expecting async behavior. ## When to use Use a service activator whenever you need to call arbitrary business logic from a flow and don't need the specialized semantics of a transformer/filter/router.

  • If your @ServiceActivator method returns a value but you set no outputChannel, where does the result go?
    To the channel named in the incoming message's replyChannel header. If there is no such header, a DestinationResolutionException is thrown because there is nowhere to send the reply.
  • What happens if requiresReply=true and the method returns null?
    The ServiceActivatingHandler throws a ReplyRequiredException, signalling that a downstream reply was mandatory but the handler produced none.

saying these in an interview costs you the question

  • Thinking @ServiceActivator always runs asynchronously (it runs on the delivering thread unless the channel is executor/queue-backed)
  • Believing a method must always return a value (void/terminal is valid)
  • Confusing service activator with a transformer — a transformer must return a value; a service activator need not

context

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

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

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