0

I am having a Repository through which I'm getting data from Elasticsearch. It is working correctly when I send a GEt request. I need that data from Elasticsearch without sending a GET request for which I've written a Service and annotated that repository in Service class using @Autowired.
Repository

@Repository
public interface RecipeDtoRepository extends 
ElasticsearchRepository<RecipeDto, Integer> {}

Controller

@RestController
@RequestMapping("/repo")
public class RecipeRepoController {
@Autowired
public RecipeDtoRepository recipeDtoRepository;

@GetMapping("/all")
public String getRecipes() {
    List<RecipeDto> recipe_list = new ArrayList<>();
    recipeDtoRepository.findAll().forEach(recipe_list::add);
    return recipe_list.toString();
}

Service

@Service
@Component
public class ClusterService implements ApplicationContextAware {
  @Autowired
public RecipeDtoRepository recipeDtoRepository;
List<RecipeDto> recipe_list = new ArrayList<>();
   new ClusterService(). applicationContext.getBean(RecipeRepoController.class).recipeDtoRepository.findAll().forEach(recipe_list::add);
}
@Override
public void setApplicationContext(ApplicationContext 
applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
}

Problem when calling the method in controller using GET request, it is working fine but when I call it using Service class, it is throwing NullPointerException which it shouldn't be according to my knowledge. I read an article where it was suggested to get the Bean in Service class which you can see I've done using ApplicationContext but it is throwing that exception. I've tried it without using ApplicationContext and it throws NullPointerException in that case too. I'm working over it for the last two days and unable to find a solution.

@Service
@Configurable
public class ClusterService {
@Autowired
public  RecipeDtoRepository recipeDtoRepository;

private  String getRecipes() {
    List<RecipeDto> recipe_list = new ArrayList<>();
    recipeDtoRepository.findAll().forEach(recipe_list::add);
    return recipe_list.toString();
}


public static void main(String[] a) {

    ClusterService clusterService = new ClusterService();
    clusterService.getRecipes();

}}
E_net4
  • 27,810
  • 13
  • 101
  • 139
Jamshaid
  • 370
  • 2
  • 11
  • 40
  • You appear to be using `new ClusterService()` which would create the `ClusterService` outside of Spring. – Ashley Frieze Sep 17 '19 at 15:35
  • @AshleyFrieze what am I supposed to do. I've to call Repository in **ClusterService** class and fetch data in it – Jamshaid Sep 17 '19 at 15:37
  • I presume you're trying to get your controller to use the service. So Autowire the service into the controller. Wherever you need a Spring Bean you need to get Spring to provide it to your calling code. You should not be using the application context directly, instead, you let Spring build all your beans and you express how they need each other. – Ashley Frieze Sep 17 '19 at 15:38
  • @Jamshaid replace `new ClusterService(). applicationContext` with `context` and `@Autowired private ApplicationContext context;` – Pasupathi Rajamanickam Sep 17 '19 at 15:39
  • ` new ClusterService(). applicationContext.getBean ... ` this line in class context does not even compile. Please take time to post your example in a form that at least compiles. On top of that: you probably don't need ApplicationContextAware to inject a bean, can you show us your attempt with that approach? – Lesiak Sep 17 '19 at 15:41
  • @PasupathiRajamanickam I'm in main() and need it there. As I've tried, we can't apply **Autowired** on static fields and by creating a new object, it'll again leave spring – Jamshaid Sep 17 '19 at 15:43
  • @AshleyFrieze I've posted the controller in order to show how code is there and is in working form. I'm not calling Service in controller – Jamshaid Sep 17 '19 at 15:44
  • Super confused, can you format your code add all the static stuff you're talking about? – Pasupathi Rajamanickam Sep 17 '19 at 15:46
  • @Lesiak I didn't get your point. would you please elaborate it more. Thans – Jamshaid Sep 17 '19 at 15:46
  • Possible duplicate of [Why is my Spring @Autowired field null?](https://stackoverflow.com/questions/19896870/why-is-my-spring-autowired-field-null) – daniu Sep 17 '19 at 15:46
  • @PasupathiRajamanickam please have a look at the question again – Jamshaid Sep 17 '19 at 16:09
  • @Jamshaid how you are binding the service in controller, also can you post the stacktrace? – triples13 Sep 17 '19 at 16:23
  • @Jamshaid i know you are trying to test but please don't do ClusterService clusterService = new ClusterService(); if you have used stereotype annotation – triples13 Sep 17 '19 at 16:25
  • @triples13 I'm not using service in controller. – Jamshaid Sep 17 '19 at 16:26
  • @Jamshaid so you are trying to call the service using main method? – triples13 Sep 17 '19 at 16:27
  • Yeah/. You're right . I'm calling it using main. Please see the question again. Have a look at edit 1 – Jamshaid Sep 17 '19 at 16:30
  • @Jamshaid Why do you have a main method in the middle of spring bean class? There is no such thing exist. You should have only one main that initialize SpringbootApplication. Spring wont work with main in middle of bean. – Pasupathi Rajamanickam Sep 17 '19 at 16:30
  • You should autowire your service class in controller and call method inside service class that's how things works. If you would like to persist something in memory, you should consider using `@PostConstruct` and utilize the member list – Pasupathi Rajamanickam Sep 17 '19 at 16:32
  • @PasupathiRajamanickam can you please provide a reference link for your 2nd last comment. Thanks – Jamshaid Sep 17 '19 at 16:36
  • @Jamshaid answered please check if that helps – Pasupathi Rajamanickam Sep 17 '19 at 16:43

3 Answers3

1

Remove the contextAware and dont call the instance of repository from the controller since you have injected it yet just do this

public void addThings(){
this.recipeDtoRepository.findAll().forEach(recipe_list::add)
}
heyhooo
  • 82
  • 6
1

if you have annotated your class using stereotype annotation and you are trying to get bean in main class try this

     ApplicationContext context= 
           SpringApplication.run(Main.class,args);
                ClusterService clusterService=context.getBean(ClusterService.class);
clusterService.getRecipes();
triples13
  • 206
  • 4
  • 18
  • @Jamshaid please see https://stackoverflow.com/questions/52267478/should-i-never-use-new-keyword-on-a-spring-boot-project – triples13 Sep 17 '19 at 16:36
1

Assuming that OP wants to persist a list and use it through out the lifecycle. Here is my recommendation

@Service
public class ClusterService {
    @Autowired
    public RecipeDtoRepository recipeDtoRepository;

    private List<RecipeDto> recipeList = null;

    @PostContruct
    public void setup() {
       recipeList = new ArrayList<>();
       recipeDtoRepository.findAll().forEach(recipeList::add);
    }

    public getReceipeList() {
      return recipeList;
    }

}

@RestController
@RequestMapping("/repo")
public class RecipeRepoController {
    @Autowired
    ClusterService clusterService

    @GetMapping("/all")
    public String getRecipes() {
        return clusterService.getReceipeList().toString();
    }
}
Pasupathi Rajamanickam
  • 1,982
  • 1
  • 24
  • 48