2

There's a Job which has a list of tasks. Each task has id, name, status.

I've created service activators for each tasks, as follows:

@ServiceActivator
public Message<Task> execute(Message<Task> message){
    //do stuff
}

I've created a gateway for Job and in the Integration flow, starting from the gateway:

@Bean
    public IntegrationFlow startJob() {
        return f -> f
                .handle("jobService", "execute")
                .channel("TaskRoutingChannel");
    }

@Bean
    public IntegrationFlow startJobTask() {
        return IntegrationFlows.from("TaskRoutingChannel")
                .handle("jobService", "executeTasks")
                .route("headers['Destination-Channel']")
                .get();
    }

@Bean
    public IntegrationFlow TaskFlow() {
        return IntegrationFlows.from("testTaskChannel")
                .handle("aTaskService", "execute")
                .channel("TaskRoutingChannel")
                .get();
    }

@Bean
    public IntegrationFlow TaskFlow2() {
        return IntegrationFlows.from("test2TaskChannel")
                .handle("bTaskService", "execute")
                .channel("TaskRoutingChannel")
                .get();
    }

I've got the tasks to execute sequentially, using routers as above.

However, I need to start the job, execute all of it's tasks in parallel. I couldn't figure out how to get that going.. I tried using @Async on the service activator methods and making it return void. but in that case, how do i chain it back to the routing channel and make it start next task? Please help. Thanks.

EDIT:

I used the RecepientListRouter along with ExecutorChannel to get the parallel execution:

@Bean
public IntegrationFlow startJobTask() {
    return IntegrationFlows.from("TaskRoutingChannel")
            .handle("jobService", "executeTasks")
            .routeToRecipients(r -> r
                .recipient("testTaskChannel")
                .recipient("test2TaskChannel"))
            .get();
}

@Bean ExecutorChannel testTaskChannel(){
    return new ExecutorChannel(this.getAsyncExecutor());
}

@Bean ExecutorChannel test2TaskChannel(){
    return new ExecutorChannel(this.getAsyncExecutor());
}
@Bean
public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(5);
    executor.setMaxPoolSize(10);
    executor.setQueueCapacity(10);
    executor.initialize();
    return executor;
}

Now, 3 questions: 1) If this is a good approach, how do i send specific parts of the payload to each recipient channel. Assume the payload is a List<>, and i want to send each list item to each channel. 2) How do I dynamically set the recipient channel? say from header? or a list? 3) Is this really a good approach? Is there a preferred way to do this?

Thanks in Advance.

Ocelot
  • 1,733
  • 4
  • 29
  • 53

1 Answers1

3

Your TaskRoutingChannel must be an instance of ExecutorChannel. For example:

return f -> f
            .handle("jobService", "execute")
            .channel(c -> c.executor("TaskRoutingChannel", threadPoolTaskExecutor()));

Otherwise, yes: everything is invoked with the single Thread and it isn't good for your task.

UPDATE

Let me try to answer to your questions one by one, although it sounds like each of them must as separate SO one :-).

  1. If you really need to send the same message to several services, you can use routeToRecipients, or can back to the publishSubscribe. Or even can do dynamic routing based on the header, for example.

  2. To send the part of message to each channel there is just enough place .split() before your .routeToRecipients()

  3. To answer to your last question I need to know the business requirements for the task.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Thanks for the response. I guess I didn't specify in question that I would like the individual tasks to execute asynchronously.. testTaskChannel and test2TaskChannel.. Would that mean I have to make these two channels ExecutorChannel – Ocelot Aug 12 '15 at 03:34
  • Also, Please check this thread as well? - http://stackoverflow.com/q/31959480/1866983 – Ocelot Aug 12 '15 at 08:07
  • Yes, you can make them as `ExecutorChannel` – Artem Bilan Aug 13 '15 at 20:40