0

I am trying to use a file storage service in a REST controller. I am using the StorageService from this Spring Boot tutorial. This is the controller class:

@RestController
public class MessageController {
    @Autowired
    private StorageService storageService;
}

And this is the service class:

@Service
public interface StorageService {
    void init();
    void store(MultipartFile file);
    Path load(String filename);
    Resource loadAsResource(String filename);
    Stream<Path> loadAll();
    void deleteAll();
}

This empty controller class with the service autowired results in a runtime error:

Field storageService in com.wais.app.MessageApp.controllers.MessageController required a
bean of type 'com.wais.app.MessageApp.services.StorageService' that could not be found.

I've also come across this thread: Spring Boot @autowired does not work, classes in different package, but in my case the main application class (which is annotated with @SpringBootApplication) resides in package com.wais.app.MessageApp, the service resides in com.wais.app.MessageApp.services and the controller resides in com.wais.app.MessageApp.controllers. Moreover, I can successfully autowire repositories from package com.wais.app.MessageApp.repositories in the same controller.

What is going on here?

Wais Kamal
  • 5,858
  • 2
  • 17
  • 36

2 Answers2

1

Only classes annotated with @Component (@Service is a component too) will be initialize by Spring and made available for other classes as @Autowired. An interface has no "body" and no constructor. It can't be used by Spring this way.

Solution

Please implement the interface in a class and annotate the implementation class (a bean) with @Service, not the interface.

Mar-Z
  • 2,660
  • 2
  • 4
  • 16
0

The error shows that you should use constructor dependency injection like this and remove the @AutoWired annotation as it is field injection and it is not recommended

@RestController
 public class MessageController {


private final StorageService storageService;
   
 public MessageController(StorageService storageService){

    this.storageService = storageService
  }

}

if you want to use @Autowired annotation then use it without private access modifier like this

@RestController
public class MessageController {
@Autowired
 StorageService storageService;

 }
umar
  • 20
  • 7
  • I actually tried constructor injection also, and that was the error from constructor injection. Sorry for that, I will edit the question. I also tried removing the private modifier but the issue remains. – Wais Kamal Mar 30 '23 at 19:09