Announcement Announcement Module
No announcement yet.
Clarification on task scheduling and concurrency Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Clarification on task scheduling and concurrency


    I'm working with a very simple SI configuration. I have a FileReadingMessageSource polling a directory and delivering messages via a DirectChannel to an application specific MessageHandler which processes files. Everything works fine, but I have questions regarding the concurrency control of this kind of configuration.

    As I understand it, messages sent to a DirectChannel are delivered within the same thread as they are sent. If this is indeed the case this means the file directory scanner is blocked until processing is complete and the maximum degree of concurrency is then one. Is this correct?

    If that is correct, it seems like the options for allowing concurrent processing of messages on a channel are:

    1. Have the MessageHandler implementation have its own Executor (i.e. handle concurrency exclusively in the recipient.). This seems subpar because the receiver loses the ability to throw MessageHandlingException or MessageRejectedException and then must accept the recovery / error handling responsibility.

    2. Use an ExecutorChannel. From the looks of this, this means writing custom code to support concurrent dispatching to MessageHandlers. My only concern is that there doesn't seem to be a out of the box implementation that simply wires an ExecutorChannel to a MessageHandler. If this is in fact the case, would the SI folks be interested in a contribution of such a support class to be bundled in the future (and officially supported)?

    Is there another option I've missed?


  • #2
    You can add a task-exeuctor reference within a "dispatcher" sub-element of "channel" as shown here:

    Alternatively, you could configure the thread-pool for the poller on the file adapter itself.


    • #3
      I've answered half of my own question (re: the ExecutorChannel) and wanted to document it here, although I'm still interested in thoughts and confirmation from the group at large.

      I just read through the source for ExecutorChannel. Here's a synopsis.

      ExecutorChannel is a very thin wrapper around a UnicastingDispatcher and provides no real concurrency itself. The magic is actually in the latter.

      UnicastingDispatcher (an implementation of MessageDispatcher) takes an optional org.springframework.core.task.TaskExecutor as a constructor arg. During invocation of doDispatch() (called when actually attempting to deliver a Message), if there is a supplied TaskExecutor, a one line anonymous Runnable wraps the call and passes it to the executor. If there is no executor supplied, it invokes doDispatch() directly. Here's the relevant code.

      // From UnicastingDispatcher#dispatch() SI 1.0.3.RELEASE
      public final boolean dispatch(final Message<?> message) {
      	if (this.taskExecutor != null) {
      		this.taskExecutor.execute(new Runnable() {
      			public void run() {
      		return true;
      	return this.doDispatch(message);
      The only thing special about ExecutorChannel is that it accepts a TaskExecutor and passes it to the instance of UnicastingDispatcher when it's instantiated. This answers my question about whether or not custom code was required when using an ExecutorChannel. The answer is no; it will do The Right Thing(tm) when given a configured executor.

      SS-SI folk, please feel free to correct this if I missed / incorrectly represented anything.


      • #4
        Thanks for the quick reply Mark. My question was how the underbelly worked, but I think I see it now (but please correct me if I was wrong in my synopsis).



        • #5
          Yes. That's a good synopsis. The ExecutorChannel is really just a high-level convenience for setting up the strategies, including the dispatcher.

          In fact, if you look at DirectChannel, it's even simpler.