Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @Autowired not working on new thread

When I run TaskJob I am getting null pointer exception because Spring doesn't autowiring serviceJob service. Is new thread causing this problem because Spring autowired mysqlService without any problem?

public class TaskJob implements Runnable {
    @Autowired
    private ServiceJob serviceJob;

    String name;
    String source;

    public TaskJob(String name, String source) {
        this.name = name;
        this.source = source;
    }

    public void run() {
        serviceJob.run();
    }
}

@Service
public class ServiceJob extends BaseJob{

    @Autowired
    private MysqlService mysqlService;

    public void run(){
    ....
    }
}

@Service
public class MysqlService {
...
}

My applicationContext.xml;

<context:component-scan base-package="cm.*" /> 

And my classes are;

cm.tasks.jobs.TaskJob
cm.jobs.ServiceJob
cm.services.MysqlService;

EDIT: TaskJob instanciated with;

TaskJob taskJob = new TaskJob(name, source);
Thread taskThread = new Thread(taskJob);
taskThread.start();
like image 644
hellzone Avatar asked Feb 28 '17 07:02

hellzone


People also ask

Can we Autowire thread class?

The answer for your question is YES. You can use autowired in thread class.

Why is @autowired not working?

When @Autowired doesn't work. There are several reasons @Autowired might not work. When a new instance is created not by Spring but by for example manually calling a constructor, the instance of the class will not be registered in the Spring context and thus not available for dependency injection.

How do I run an Autowired thread in Spring boot?

Need to call the service method executeAsynchronously() to start the flow. You may auto-wire AsynchronousService to the ThreadAppRunner as follows and call service. executeAsynchronously() .

What can I use instead of Autowired?

Since Spring is the most popular DI and IOC container for Java application, @Autowired is more common and @Inject is lesser-known, but from a portability point of view, it's better to use @Inject. Spring 3.0 supports JSR-330 annotation, so if you are using Spring 3.0 or higher release, prefer @Inject over @Autowired.


Video Answer


2 Answers

Spring only autowires components it creates. You are calling new TaskJob(), Spring doesn't know about this object so no autowiring will take place.

As a workaround you can call the application context directly. Firstly get a handle on the application context. This can be done by adding @Autowire for the application context itself.

@Autowired
private ApplicationContext applicationContext;

When you create TaskJob, ask the app context to do your auto-wiring.

TaskJob taskJob = new TaskJob(name, source);
applicationContext.getAutowireCapableBeanFactory().autowireBean(taskJob);

Additionally if you have any @PostConstruct annotated methods you need triggering you can call initializeBean()

applicationContext.getAutowireCapableBeanFactory().initializeBean(taskJob, null);
like image 196
Adam Avatar answered Oct 19 '22 11:10

Adam


Your TaskJob is instantiated wihh "new" operator which means the object created is not a spring bean. So you will have to write code to create object for the property (ServiceJob) with the new operator.

While using Spring spring framework Service objects are not created like this. Kindly use getBean method of Applicationcontext. Please see here

like image 34
subir Avatar answered Oct 19 '22 10:10

subir