user6094181
user6094181

Reputation:

404 error if controller not in Application.java package. @ComponentScan not working

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

Answers (1)

Andy Wilkinson
Andy Wilkinson

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

Related Questions