5
votes

This is my first attempt using ControlBus to turn inbound channel adapters on/off.

To make it simple, I'm sending my control message by writing an empty file into a directory watched by a inbound file adapter (this one is perpetually turned on), which I then route to a service activator that will turn on/off my other inbound adapters.

<int:channel id="controlBusChannel" />
<int:control-bus input-channel="controlBusChannel" auto-startup="true"/>
<file:inbound-channel-adapter id="controlFilesIn" directory="file:/tmp/control/input" prevent-duplicates="true" auto-startup="true">
    <int:poller id="poller" fixed-delay="500"/>
</file:inbound-channel-adapter>
<int:service-activator input-channel="controlFilesIn" output-channel="controlFilesOut" ref="controlFileHandler" method="handleUpdate"/>
<bean id="controlFileHandler" class="com.myproj.integration.ControlBusController"/>
<file:outbound-channel-adapter id="controlFilesOut" directory="file:/tmp/control/output" delete-source-files="true" />

<file:inbound-channel-adapter id="filesIn" directory="file:/tmp/filesIn/input" prevent-duplicates="true" filter="FileFilterOnLastModifiedTime" auto-startup="false">
    <int:poller id="poller" fixed-delay="500"/>
</file:inbound-channel-adapter>

In my ControlBusController bean:

@Component
public class ControlBusController implements ApplicationContextAware {
    final static Logger logger = LoggerFactory.getLogger(ControlBusController.class);

    private ApplicationContext ctx;

    public File handleUpdate(File input) throws ParseException, IOException, FileNotFoundException {
        String fileName = input.getName();
        logger.info("===================================");
        logger.info("Triggering control bus update by " + fileName);
        String[] fnArray = fileName.split("_");
        String inputChannel = fnArray[1];
        String inputCommand = fnArray[2];
        if ("FILESIN".equals(inputChannel) && "START".equals(inputCommand)) {
            MessageChannel channel = ctx.getBean("controlBusChannel", MessageChannel.class);
            if (channel != null) {
                String controlMessage = "@filesIn.start()";
                logger.info("Sending control message: " + controlMessage);
                channel.send(new GenericMessage<>(controlMessage));
            } else logger.error("Could not get Message Channel from context or context was null");
        }
        return input;
    }

    @Override
    public void setApplicationContext(ApplicationContext ac) throws BeansException {
        this.ctx = ac;
    }
}

The message gets sent through into the controlBusChannel, but I get an error saying:

Caused by: org.springframework.expression.EvaluationException: The method 'start' is not supported by this command processor. If using the Control Bus, consider adding @ManagedOperation or @ManagedAttribute.
        at org.springframework.integration.handler.ExpressionCommandMessageProcessor$ExpressionCommandMethodResolver.validateMethod(ExpressionCommandMessageProcessor.java:111)

filesIn is already declared as the ID for my adapter, as seen above in the XML snippet.

Any ideas? Thanks!

P.S. I've tried just putting in the @ManagedOperation / @ManagedAttribute annotations and they don't seem to have any positive effect.

1

1 Answers

3
votes

Since you don't have a channel attribute on the <int-file:inbound-channel-adapter>, but just an id, so the channel is auto-created and it is exactly with that id. The adapter itself gets a bean name like filesIn.adapter.

So, you must change your ControlBus command expression to this:

String controlMessage = "@'filesIn.adapter'.start()";