Arthur
Arthur

Reputation: 3473

@Autowired in ThreadPoolTaskExecutor doesn't work

I trying to run async thread on button press in Java GUI application.

My code is:

Config class:

@Configuration
@ComponentScan({"khartn", "khartn.torrentsuploader.processor"})
public class AppConfig {

    @Bean(initMethod = "init")
    public NewJFrame mainForm() {
        System.out.println("init mainForm");
        return new NewJFrame();
    }

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
        pool.setCorePoolSize(5);
        pool.setMaxPoolSize(10);
        pool.setWaitForTasksToCompleteOnShutdown(true);
        pool.initialize();
        return pool;
    }

}

JFrame class:

public class NewJFrame extends javax.swing.JFrame {

    @Autowired
    FileProcessor fileProcessor;
    @Autowired
    ThreadPoolTaskExecutor taskExecutor;

   private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        taskExecutor.execute(new Runnable() {

            @Autowired
            MyDirectoryReader myDirectoryReader;

            @Autowired
            AuthThread authThread;

            @Override
            public void run() {
                jLabel3.setText("Авторизация...");
                Boolean authSuccessfull = false;
                while (!authSuccessfull) {
                    authSuccessfull = authThread.auth();

                }
                jLabel3.setText("Загрузка файлов");

                myDirectoryReader.readDir();
            }

        });

    }   

I got error on line

authSuccessfull = authThread.auth();



java.lang.NullPointerException
    at khartn.torrentsuploader.form.NewJFrame$4.run(NewJFrame.java:162)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Why this exception occurs?

And how to fix this exception?

Why my components is not autowired?

Thank you.

Upvotes: 1

Views: 6280

Answers (2)

CodeBender
CodeBender

Reputation: 267

Basically, you should not use

taskExecutor.execute(new Runnable(){
    // do something here
});

Firstly you have to understand what is Managed Bean and Unmanaged Bean. When you are using Spring, all instances of your java classes will be instantiated and "pre-loaded" the moment you start your application. In another word, all classes will be instantiated and managed by the spring container. In practice, you use @Component (or @Bean if done at @Configuration class) and @Autowired annotations.

When you are using the "new" keyword for the class Runnable, what you are doing is breaking the rule of having spring to manage all your beans (or classes). Now the "new Runnable(){}" is no longer managed by spring, yet you are expecting spring to inject all the @Autowired classes in your Runnable class. All @Autowired objects in the new Runnable(){}is already out of reach from spring.

You may refer to this link to check out how mkyong uses ThreadPoolTaskExecutor. Do note on the part where he named the class PrintTask implements Runnable. Hope this helps =)

Upvotes: 0

Faraj Farook
Faraj Farook

Reputation: 14855

Beans will not get autowired if your class is not initiated by the context. In other words,

If your class NewJFrame is manually initiated by the new keyword, spring framework will not be able to autowire the property variables inside that class.

Do something thing like this.

@Component("mainForm")
public class NewJFrame extends javax.swing.JFrame {

And remove the bean method mainForm from the configuration java file. And then redesign the NewJform as below. I didn't compile this program. So excuse me for any compilation errors.

Note: The key is to make sure all the @Autowired properties inside the class where it's initiated by the DI and NOT by the new. Your Runnable is also initated by the new keyword, thats why we need to take the myDirectoryReader and authThread out from the anonymous Runnable object.

@Component("mainForm")
public class NewJFrame extends javax.swing.JFrame {

    @Autowired
    FileProcessor fileProcessor;

    @Autowired
    ThreadPoolTaskExecutor taskExecutor;

    @Autowired
    MyDirectoryReader myDirectoryReader;

    @Autowired
    AuthThread authThread;


    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        taskExecutor.execute(new Runnable() {

           @Override
           public void run() {
              ...
              authSuccessfull = authThread.auth();
              ...
           }
    });
}   

Upvotes: 2

Related Questions