0

I have a runnable class

public class MissingPartitionsTask implements Runnable {
@Autowired
private PartitionsService partitionsService;

private Schedules schedule;

MissingPartitionsTask(Schedules schedule){
    this.schedule = schedule;
}

@Override
public void run() {
    partitionsService.findAll(schedule.getId());
}
}

When I run it, I get

java.lang.NullPointerException
    at MissingPartitionsTask.run(MissingPartitionsTask.java:26)

This is row 26

partitionsService.findAll(schedule.getId());

I checked schedule.getId(). It's not empty. There are 3 rows in the table with id 1, 2 and 3.

I also have a service

@GetMapping("/partitions/{id}")
public List<LocalDate> findAll(@PathVariable long id) {
    return partitionsService.findAll(id);
}

It works when I call it using my browser and returns a list of dates.

http://localhost:8181/partitions/3

Why does MissingPartitionsTask not work?

EDIT My application class

@SpringBootApplication
@EnableScheduling
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

EDIT2

@Service
public class SchedulerService {
    @Autowired
    private ScheduleRepository scheduleRepository;

    @Autowired
    private TaskExecutor taskExecutor;

    @Scheduled(fixedRate=60000)
    public void scheduleAll() {
        scheduleRepository.findAll().forEach(
            schedule -> {
                MissingPartitionsTask missingPartitionsTask = new MissingPartitionsTask(schedule);
                taskExecutor.execute(missingPartitionsTask);
            });
    }

}

EDIT3

Why is my Spring @Autowired field null?

Does not help. My service is autowired

@Autowired
private PartitionsService partitionsService;

and annotated

@Service
public class PartitionsService {

schedule IS NOT NULL. It returns values.

@Override
    public void run() {
        System.out.println(schedule.getId());
}

result 1 2 3

The service works when I do a GET, it does not work when I try calling it from a thread.

EDIT4

This helped

The problem was that Spring didn't control my runnable. Moving my run method to SchedulerService as

private Runnable newRunnable(Schedules schedule) {
        return () -> {
            List<String> missing = partitionsService.findMissing(schedule.getId());
        };
    }

And calling it like this

taskExecutor.execute(newRunnable(schedule));

instead of

taskExecutor.execute(missingPartitionsTask);

Solved it.

gjin
  • 860
  • 1
  • 14
  • 28

1 Answers1

0

You have to run application and not single class as stand alone application for this to work. As you are using autowire, spring has to initialise this class and then you have to call that function. If you run this class directly there wont be autowired class available and you will get null pointer exception.

I hope this helps

Vishal
  • 98
  • 1
  • 9
  • I do run it as Application. Otherwise the endpoint `/partitions/3` woudn't work, no? Or what do you mean? Added my application class. – gjin Nov 28 '19 at 10:02
  • Can you please post code which starts you thread and you get null pointer? I got how you run it through endpoint, but when do you get null pointer – Vishal Nov 28 '19 at 10:04
  • Added as EDIT2. – gjin Nov 28 '19 at 10:08
  • MissingPartitionsTask missingPartitionsTask = new MissingPartitionsTask(schedule) because of new operator this object is created manually and not a bean managed by spring and hence it will not create autowired object – Vishal Nov 28 '19 at 10:11
  • The problem is not here. When I call `schedule.getId()` from run method it works. The problem is in `partitionsService` it is autowired and the service is annotated, but it's still null. – gjin Nov 28 '19 at 10:17