Hello i'am trying to add an advice to handle the case of empty files in a directory , the use case is when the directory is empty we should stop the application which is a springbok application .
here is my configuration file :
@Configuration
public class FlowConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(FlowConfiguration.class);
@Bean("creFileInboundChannel")
MessageChannel fileInputChannel() {
return new DirectChannel();
}
@Bean(name = PollerMetadata.DEFAULT_POLLER)
public PollerMetadata poller() {
return Pollers.fixedRate(1000)
.advice(emptyFolderAdvice())
.get();
}
@Bean
DirectoryScanner directoryScanner(@Value("${inbound.filename.regex:.*}") String regex) {
RecursiveDirectoryScanner scanner = new RecursiveDirectoryScanner();
CompositeFileListFilter filter = new CompositeFileListFilter<>(
Arrays.asList(new AcceptOnceFileListFilter<>(),
new RegexPatternFileListFilter(regex))
);
scanner.setFilter(filter);
return scanner;
}
@Bean
@InboundChannelAdapter(value = "creFileInboundChannel", poller = @Poller(fixedDelay = "1000"))
MessageSource<File> fileReadingMessageSource(DirectoryScanner directoryScanner, CreConfiguration creConfiguration) {
FileReadingMessageSource source = new FileReadingMessageSource();
source.setDirectory(new File(creConfiguration.getInputDir()));
source.setScanner(directoryScanner);
return source;
}
@Bean
@ServiceActivator(inputChannel = "creOutputChannel")
MessageHandler logOutputCreFileHandler() {
return message -> {
if (message.getPayload() instanceof Optional) {
Optional<File> filteredFile = (Optional<File>) message.getPayload();
if (filteredFile.isPresent()) {
LOGGER.info("end of process {}, writing file in the output directory", filteredFile.get());
}
}
};
}
@Bean
@ServiceActivator(inputChannel = "creFileInboundChannel")
MessageHandler creFileInFolderHandler(TraitementCreService traitementCreService) {
List<Advice> advices = new ArrayList<>();
advices.add(emptyFolderAdvice());
ServiceActivatingHandler serviceActivatingHandler = new ServiceActivatingHandler(traitementCreService, "invoke");
serviceActivatingHandler.setOutputChannelName("creOutputChannel");
serviceActivatingHandler.setAdviceChain(advices);
return serviceActivatingHandler;
}
@Bean
@ServiceActivator(inputChannel = "errorChannel")
MessageHandler erreurHandler() {
return message ->
LOGGER.info("Error when treating file : {}", ((ErrorMessage) message).getOriginalMessage().getPayload());
}
@Bean("errorChannel")
QueueChannel errorChannel() {
return new QueueChannel(500);
}
@Bean
public EmptyFolderAdvice emptyFolderAdvice() {
return new EmptyFolderAdvice();
}
}
here is my advice class that handles shutdown when directory is empty :
public class EmptyFolderAdvice extends AbstractMessageSourceAdvice {
@Override
public Message<?> afterReceive(Message<?> message, MessageSource<?> source) {
File directory = (File) source;
File[] files = directory.listFiles();
if (files == null || files.length == 0) {
System.exit(0); // Stop the application if no files exist
}
return message;
}
}
here is my integration test :
@SpringIntegrationTest
@SpringBootTest
@ContextConfiguration(classes = FiltrageApp.class)//{FlowConfiguration.class, FiltrageConfiguration.class})
public class StopApplicationTest {
@MockBean
private EmptyFolderAdvice advice; // Inject the advice under test
@Qualifier("creFileInboundChannel")
@Autowired
private MessageChannel inputChannel;
@MockBean
TraitementCreService traitementCreService;
@Autowired
private MessageSource<?> messageSource;
@Autowired
private ApplicationContext context;
@Autowired
private MessageHandler creFileInFolderHandler;
@Test
public void testAfterReceiveIsCalled() throws TechnicalException {
// Create a test message
Message<?> message = MessageBuilder.withPayload("").build();
// Send the message to the input channel
//traitementCreService.invoke(null);
inputChannel.send(message);
traitementCreService.invoke(null);
// Verify that the afterReceive method is called
Mockito.verify(advice).afterReceive(Mockito.any(Message.class), Mockito.any(MessageSource.class));
// You can also verify the number of times the method is called, e.g., Mockito.verify(mockAdvice, Mockito.times(1)).afterReceive(...)
}
my problem is that is does not work and the afterReceive method of the advice is never called.
thanks
You use an explicit poller in your configuration:
@InboundChannelAdapter(value = "creFileInboundChannel", poller = @Poller(fixedDelay = "1000"))
But you apply your emptyFolderAdvice()
which is out of use.
You still need to have a PollerMetadata
bean, but that must not be a PollerMetadata.DEFAULT_POLLER
and use its name in the @Poller
:
/**
* @return The {@link org.springframework.integration.scheduling.PollerMetadata} bean
* name.
*/
String value() default "";
The logic in your EmptyFolderAdvice
is also wrong:
public Message<?> afterReceive(Message<?> message, MessageSource<?> source) {
File directory = (File) source;
How a MessageSource
can be casted to a File
?
You just need to check for message == null
: if no files to produce from a FileReadingMessageSource
, then this afterReceive()
method is called with null
.