Search code examples
javaspringintellij-ideajavabeansautowired

Standalone Java Application, no beans get created in the Spring Application Context? (IntelliJ, JavaConfig)


I am new to Spring so I've no doubt I've probably overlooked something simple. I am making a standalone application using Spring to aid with dependency injection and AOP.

The problem is none of the beans are available in the spring application context when I run the application. The bean I want to inject is of type: WatchKey. The application seems to run fine but when an event occurs in the "watched" folder I'll get NullPointerException saying the WatchKey variable is null.


These are the beans I'm declaring in my config file

@Configuration
public class FileManagerConfig
{
    @Bean
    public Path FTPPath ()
    {
        Path FTPDir = null;
        try {
            FTPDir = FileSystems.getDefault().getPath("PATH_TO_FOLDER");
        } catch (Exception e) {
        e.printStackTrace();
        }
        return FTPDir;
    }

    @Bean
    public WatchService getWatcher ()
    {
        WatchService watcher = null;
        try {
            watcher = FileSystems.getDefault().newWatchService();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
        return watcher;
    }

    @Bean
    public WatchKey getKey(Path path, WatchService FTPWatcher)
    {
        WatchKey key = null;
        try {
            key = path.register(FTPWatcher, ENTRY_CREATE);
            key = FTPWatcher.take();
        } catch (IOException | InterruptedException e) {
            System.out.println(e.getMessage());
        }
        return key;
    }
}

The last bean is the one I want to autowire in the main application. The other beans are injected into the last bean.

Please note I have told IntelliJ about this configuration file in Project Structure > Facets.

Please also note when getKey is run, the key is NOT null (I put an if statement in the try block to check).


The following is the class that requires the WatchKey dependency:

public class FTPWatchZip extends Observable
{
    private boolean run;

    @Autowired
    private WatchKey key;

    public FTPWatchZip()
    {
        run = true;
        watch(key);
    }

    @Autowired
    private void watch(WatchKey key)
    {
        try {
            while(run)
            {
                for (WatchEvent<?> event : key.pollEvents())
                {
                    if (event.kind() == ENTRY_CREATE) {
                        System.out.println("New file detected in FTP Folder\nDownloading...");
                        TimeUnit.SECONDS.sleep(30);
                        System.out.println("Notify subscribers\n");
                    }
                }
                key.reset();
            }
        } catch(InterruptedException e) {
            System.out.println(e.getMessage());
        }
    }
}

I have noticed IntelliJ tells me (when I hover over @Autowired):

Autowired members must be defined in valid Spring bean (@Component|@Servuce|...).

Which suggests to me the necessary beans are not being put into the Spring Application Context.


For completeness here is my main class, I have tried different versions of main in order to try and solve this issue but this is what it is at the moment:

public class DuckCreekMonitor
{
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(FileManagerConfig.class);
        new FTPWatchZip();
    }
}

When I run the program the following is printed to the console:

Jun 07, 2017 5:01:25 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5ef04b5: startup date [Wed Jun 07 17:01:25 BST 2017]; root of context hierarchy

It then appears to "Watch" the folder for changes, anytime it detects a change in that directory I get a NullPointerException and a stacktrace.

Therefore I don't think the beans are being autowired into my function. Would anyone know anything I can try?


Solution

  • How would Spring be aware of your FTPWatchZip class? you should annotate it with @Component or @Service, and this is what IntelliJ is telling you. or Make it a bean as you did for the others:

        @Bean
        public FTPWatchZip getFTPWatch ()
        {
    
            return new FTPWatchZip();
        }