0

I'm developing an app with Spring boot, I'm using the MVC model. I have an entity called A, which has its controller, service and repository. all right up here.

I have an utility class, which is runnable and is called when the server start. This utility class create a set of A entities, and then, stored it into database. The problem is that the autowired service of the class is null, because I have created a new instance of the utility class in order to run it, so Spring doesn't create the autowired service correctly.

that is:

Main.java

@SpringBootApplication
public class MainClass {

    public static void main(String[] args) {
    ...
    Runnable task = new Utility();
    ...
}
}

Utility.java

@Autowired
private Service service;
...
public void run() {
   ...
   service.save(entities);      <-- NPE
}

I know that Spring cannot autowired the service of this new instance, but I need to create the utility instance in order to run it.

I have tried to access to the service through application context, but the problem is the same:

 @Autowired 
 private ApplicationContext applicationContext;

I have tried to make runnable the controller (where the service is autowired correctly), but the problem is the same, since I need to do the new controller();.

I have read these posts post 1 post 2, but any solution works.

UPDATE: I need that the task run in a new thread, since it will be executed each X hours. The task downloads a data set from Internet and save it into database.

tovarichML
  • 119
  • 1
  • 2
  • 9
  • Possible duplicate of [How to inject dependencies into a self-instantiated object in Spring?](https://stackoverflow.com/questions/3813588/how-to-inject-dependencies-into-a-self-instantiated-object-in-spring) – Amit Bera Feb 22 '19 at 18:19
  • I don't understand why you don't simply create a `@Bean` for the utility class, and then call it inside the `@PostConstruct`? – Coderino Javarino Feb 22 '19 at 18:21
  • Is Main.java your class with your main() method? – dunni Feb 22 '19 at 18:22
  • `autowiring` in Spring can be done in three ways, `contractor`, `method` and `field`, none matches in your case. Also, make sure you extend to an interface, else it will be `null` – Vishrant Feb 22 '19 at 18:31
  • I have updated the post to add extra information. – tovarichML Feb 22 '19 at 18:37
  • @tovarichML "executed each X hours" Sounds like you're looking for a scheduler? https://spring.io/guides/gs/scheduling-tasks/ – Coderino Javarino Feb 22 '19 at 18:42
  • @CoderinoJavarino, That works! I love you so much right now. If you wish, reply it and I close the post with the solution. – tovarichML Feb 22 '19 at 18:53

3 Answers3

0

If I understood correctly, you're trying to populate your database with dummy data.

This utility class create a set of A entities, and then, stored it into database

Why are you using a Runnable? Is this task run via a new Thread?
If not, then use @PostConstruct inside your @Controller, which has access to the right @Service. The marked method is guaranteed to be invoked after the Bean has been completely constructed, and all its dependencies have been satisfied.

@PostConstruct
private void persistEntities() {
   ...
   service.save(entities);
}

If you're on Spring Boot, you can just place a data-*.sql file under src/main/resources/. It will be run at startup.

LppEdd
  • 20,274
  • 11
  • 84
  • 139
  • The task run via a new Thread. I'm downloading each X hours a data set from Internet and saves it into database. The process must be transparent to the final web user. – tovarichML Feb 22 '19 at 18:32
0

If you need to do some task periodically:

@SpringBootApplication
@EnableScheduling
public class Application {

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

@Component
class Runner {

    @Autowired
    private Service service;

    @Scheduled(cron = "0 */2 * * * ?") // execute every 2 hours
    public void run() {
        // put your logic here
    }
}
Oleksii Zghurskyi
  • 3,967
  • 1
  • 16
  • 17
0

Just as said @CoderinoJavarino in comments, I need to use @Scheduled instance of a runnable class.

With scheduled, Spring can autowired correctly the service. So, finally, my initial runnable utility class has become into a scheduled class.

tovarichML
  • 119
  • 1
  • 2
  • 9