Могу ли я предоставить пользовательский блокировщик файлов для обработчика сообщений FileWritingMessageHandler?

#spring-boot #spring-integration #distributed-lock

Вопрос:

Я использую a FileReadingMessageSource с пользовательским FileLocker :

 @Component
public class JdbcFileLocker implements FileLocker {
...
 
 @Autowired
JdbcFileLocker jdbcFileLocker;

@Bean
@InboundChannelAdapter(value = "fileInputChannel", poller = @Poller(fixedDelay = "1000"))
public MessageSource<File> fileReadingMessageSource() {
    FileReadingMessageSource source = new FileReadingMessageSource();
    source.setDirectory(new File("/workspace/in"));
    source.setFilter(new SimplePatternFileListFilter("input"));
    source.getScanner().setLocker(jdbcFileLocker);
    return source;
}
 

Теперь я хочу использовать FileLocker jdbcFileLocker , чтобы разблокировать файл после обработки его в FileWritingMessageHandler :

 @Bean
@ServiceActivator(inputChannel = "fileInputChannel")
  public MessageHandler fileWritingMessageHandler() {
    FileWritingMessageHandler fileWritingMessageHandler = 
      new FileWritingMessageHandler(new File("/workspace/out"));

 

Должен ли я разблокировать файл самостоятельно @ServiceActivator или я могу FileLocker каким-то образом передать свой файл в файлообменник?


ИЗМЕНИТЬ: Добавление ExpressionEvaluatingRequestHandlerAdvice

 @Bean
ExpressionEvaluatingRequestHandlerAdvice unlockAdvice() {
  ExpressionEvaluatingRequestHandlerAdvice advice = 
    new ExpressionEvaluatingRequestHandlerAdvice();
  advice.setSuccessChannel(unlockChannel);
  return advice;
}
 

Так что я могу добавить это Advice в свой FileWritingMessageHandler :

 @Autowired
ExpressionEvaluatingRequestHandlerAdvice unlockAdvice;

@Bean
@ServiceActivator(inputChannel = "fileInputChannel")
public MessageHandler fileWritingMessageHandler() {
  FileWritingMessageHandler handler = 
    new FileWritingMessageHandler(new File("/workspace/out"));
  handler.setFileExistsMode(FileExistsMode.REPLACE);
  handler.setDeleteSourceFiles(true);
  handler.setExpectReply(false);
  handler.setFileNameGenerator(message -> "output");
  handler.setAdviceChain(List.of(unlockAdvice));
  return handler;
}
 

Разблокировка затем обрабатывается @ServiceActivator прослушиванием unlockChannel .

Ответ №1:

Прежде всего рассмотрите возможность использования fileWritingMessageHandler.setExpectReply(false) . Поскольку по умолчанию a FileWritingMessageHandler ведет себя как шлюз и попытается выдать ответ, который не обрабатывается в вашем потоке, и поэтому вашему опрашивающему будет выдана некоторая ошибка.

Для вашего FileLocker варианта использования см. активатор ExpressionEvaluatingRequestHandlerAdvice вашего fileWritingMessageHandler сервиса. Его onSuccessExpression можно было бы разблокировать, что действительно будет сделано после FileWritingMessageHandler завершения процесса. Дополнительную информацию смотрите в документах: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints.html#message-handler-advice-chain

Другой способ-иметь a fileInputChannel как a PublishSubscribeChannel без изменения конфигурации для текущего fileWritingMessageHandler . Но вы добавляете в этот канал другого подписчика активатора услуг, который будет выполнять FileLocker.unlock() логику. Чтобы убедиться, что второй подписчик будет вызван после первого, подумайте о том, чтобы добавить @Order(100) активатор службы разблокировки для вашего устройства. Также смотрите документы: https://docs.spring.io/spring-integration/docs/current/reference/html/core.html#channel-implementations-publishsubscribechannel

Комментарии:

1. Большое спасибо! Я выбрал Advice решение (видно в ПРАВКЕ выше 🙂