Reputation:
I am having trouble with spring-boot setting up a simple application when the Application.java, controller (@Controller), services (@Service) and repositories (@Repository) are in different packages.
I know it's a common issue and I've found here that it's a matter of setting up the @ComponentScan annotation in the main class.
However, despite doing this, I still get a 404 error when I try to access my REST service.
Here's my project structure :
main
├── java
│ ├── application
│ │ └── Application.java
│ ├── controllers
│ │ └── CategoryController.java
│ ├── dto
│ │ └── ReturnMessage.java
│ ├── entities
│ │ ├── Category.java
│ │ ├── Post.java
│ │ └── User.java
│ ├── repositories
│ │ └── CategoryRepository.java
│ ├── services
│ │ ├── CategoryService.java
│ │ └── CategoryServiceImpl.java
│ └── utils
│ └── Constants.java
Here's my Application.java :
package application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@EnableJpaRepositories
@SpringBootApplication
@Configuration
@ComponentScan("main.java")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And the beginning of my CategoryController.java :
@RestController
public class CategoryController {
@Autowired
CategoryService categoryService;
/**
* Retourne la liste des catégories
*/
@RequestMapping(value = Constants.REST_BASE_URL + "/categories", method = RequestMethod.GET)
public List<Category> readAll() {
return categoryService.readAll();
}
Constants.REST_BASE_URL is "rest/", and I get a 404 error when I call localhost:8080/rest/categories. I tried removing the base URL and it changed nothing. It works if I put the controller in the Application.java class.
Any guess as to why it is not working ? I'm new to Spring-boot so there may be something obvious that I forgot to do.
Upvotes: 0
Views: 1195
Reputation: 116231
The problem is your @ComponentScan
annotation. You've configured it to look in a package named main.java
, however you have no such package in your application. The packages that you do have are:
application
controllers
dto
entities
repositories
services
utils
You could list all of these packages:
@ComponentScan({"application", "controllers", "dto", "entities", "repositories", "services", "utils"})
However, this would be rather unconventional.
It's more conventional for all of your packages to have a common root. If you place your Application
class in this package there's then no need for an explicit @ComponentScan
at all. Something like this:
main
├── java
| | foo
│ │ ├── Application.java
| │ ├── controllers
| │ │ └── CategoryController.java
| │ ├── dto
| │ │ └── ReturnMessage.java
| │ ├── entities
│ │ ├── Category.java
│ │ ├── Post.java
│ │ ├── User.java
| │ ├── repositories
| │ │ └── CategoryRepository.java
| │ ├── services
| │ │ ├── CategoryService.java
| │ │ └── CategoryServiceImpl.java
| │ └── utils
| │ └── Constants.java
Your package names would now be:
foo
foo.controllers
foo.dto
foo.entities
foo.repositories
foo.services
foo.utils
And your Application
class being in the foo
package will meant that component scanning is enabled for it and all of its sub-packages without you having to explicitly configure it.
Upvotes: 1