Search code examples
javaspring-bootwatchservice

How can I abort Spring-Boot startup?


I'm writing a Spring-Boot application to monitor a directory and process files that are being added to it. I register the directory with WatchService in a configuration class:

@Configuration
public class WatchServiceConfig {

    private static final Logger logger = LogManager.getLogger(WatchServiceConfig.class);

    @Value("${dirPath}")
    private String dirPath;

    @Bean
    public WatchService register() {
        WatchService watchService = null;

        try {
            watchService = FileSystems.getDefault().newWatchService();
            Paths.get(dirPath).register(watchService, ENTRY_CREATE);
            logger.info("Started watching \"{}\" directory ", dlsDirPath);
        } catch (IOException e) {
            logger.error("Failed to create WatchService for directory \"" + dirPath + "\"", e);
        }

        return watchService;
    }
}

I would like to abort Spring Boot startup gracefully if registering the directory fails. Does anybody know how I can do this?


Solution

  • Get the Application Context, e.g.:

    @Autowired
    private ConfigurableApplicationContext ctx;
    

    Then call the close method if you cannot find the directory:

    ctx.close();
    

    That gracefully shutdowns the Application Context and thus the Spring Boot Application itself.

    Update:

    A more detailed example based on the code provided in the Question.

    Main Class

    @SpringBootApplication
    public class GracefulShutdownApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext ctx = SpringApplication.run(GracefulShutdownApplication.class, args);
            try{
                ctx.getBean("watchService");
            }catch(NoSuchBeanDefinitionException e){
                System.out.println("No folder to watch...Shutting Down");
                ctx.close();
            }
        }
    
    }
    

    WatchService Configuration

    @Configuration
    public class WatchServiceConfig {
    
        @Value("${dirPath}")
        private String dirPath;
    
        @Conditional(FolderCondition.class)
        @Bean
        public WatchService watchService() throws IOException {
            WatchService watchService = null;
            watchService = FileSystems.getDefault().newWatchService();
            Paths.get(dirPath).register(watchService, ENTRY_CREATE);
            System.out.println("Started watching directory");
            return watchService;
        }
    

    Folder Condition

    public class FolderCondition implements Condition{
    
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            String folderPath = conditionContext.getEnvironment().getProperty("dirPath");
            File folder = new File(folderPath);
            return folder.exists();
        }
    }
    

    Make the WatchService Bean @Conditional based on whether the directory is present or not. Then in your Main Class, check whether the WatchService Bean exists, and if not shutdown the Application Context by calling close().