0

In my former life I worked on a few Apache Camel projects, so I'm not entirely new to EIPs, but I am now trying to learn & understand Spring Integration. I have (what I think is) a small snippet of code for a "flow" that:

  1. Defines a control bus for managing & monitoring the flow
  2. Flow starts by fetching PNG images out of a folder (polling for new ones once a day); then
  3. Uploads them to a directory on an FTP server
FileReadingMessageSource fileSource = new FileReadingMessageSource();
fileSource.setBeanName("fileMessageSource");
fileSource.setDirectory(new File("C:/DestDir"));
fileSource.setAutoCreateDirectory(true);

DefaultFtpSessionFactory ftpSessionFactory = new DefaultFtpSessionFactory();

IntegrationFlow flow = IntegrationFlows.from(fileSource, configurer -> configurer.poller(Pollers.cron("0 0 * * *")))
    .filter("*.png")    // only allow PNG files through
    .controlBus()       // add a control bus
    .handle(Ftp.outboundAdapter(ftpSessionFactory, FileExistsMode.FAIL)
        .useTemporaryFileName(false)
        .remoteDirectory("uploadDir"))
    .get();

Although admittedly I am a little unsure of the differences between "flows" and "channels" in Spring Integration parlance (I believe a flow is a composition of channels, and channels connect individual endpoints, maybe?), I am not understanding how, given my code above, the control bus can be leverage to turn the fileSource input endpoint on/off.

I know that with control buses, you send SPeL messages to channels and the control bus takes those SPeL messages and uses them to figure out which beans/methods to invoke, but above I am starting my flow from a FileReadingMessageSource. So what is the exact message I would need to send to which channel so that it stops/pauses or starts/restarts the FileReadingMessageSource endpoint?

The idea would be that if I used the control bus to turn the FileReadingMessageSource off, then days and days could pass and no PNG files would ever be uploaded to the FTP server, until I used the control bus to turn it back on.

Thanks for any-and-all help here!

hotmeatballsoup
  • 385
  • 6
  • 58
  • 136

1 Answers1

1

The control bus needs to be in its own flow, not a component in another flow; you send control messages to it, to control other endpoints.

See a recent example in this question and answer.

Using Control Bus EIP in Spring Integration to start/stop channels dynamically

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Huh? That is your question and you accepted the answer. – Gary Russell Nov 30 '22 at 21:35
  • See what is Message Channel in EIP Book: https://www.enterpriseintegrationpatterns.com/MessageChannel.html. An `IntegrationFlow` is just a configuration container to logically compose endpoints and channels between them. At runtime the flow does not have any values and only channels and endpoints are communicate. Or better to say endpoints exchange messages via channels between them. The `filter()` is wrong. I assume you mean `FileReadingMessageSource.setFilter(FileListFilter filter)` instead. – Artem Bilan Nov 30 '22 at 21:36
  • Shouldn't we provide a `@ControlBus` for the `MessageChannel` `@Bean`!? :smile: – Artem Bilan Nov 30 '22 at 21:40
  • Could I be so bold as to see a living breathing example of: **(a)** a control bus "being in its own flow" and then **(b)** sending "control messages to it" such that **(c)** it effectively stops/pauses the `FileReadingMessageSource` in my example? Pseudo-code is fine, I'm just not seeing the "forest through the trees" here. – hotmeatballsoup Nov 30 '22 at 21:51
  • (a) you already did that in your other question. (b, c) See Artem's answer where he gives the input endpoint an `id` and sends a message to control that endpoint. – Gary Russell Nov 30 '22 at 21:57
  • Thanks @GaryRussell, but where does he set an `id` on the endpoint?!? The only thing that _looks_ like it might be an `id` is his use of sending `@myS3SourceEndpoint` in a `GenericMessage`, but I don't see how `@myS3SourceEndpoint` maps to a `FileReadingMessageSource` bean anywhere...thanks for any clarification. – hotmeatballsoup Dec 01 '22 at 01:31
  • On the lambda parameter. Artem used e, you used configurer. So `configurer.id(“foo”).poller(…`. – Gary Russell Dec 01 '22 at 13:09