38

I start with learning Spring and I create basic project which creates database, insert values and next print it in web browser. My problem is that when I have RestController in the same package like main class - its OK, but I want distribute it to other package and when I create new package, move the RestController it doesn't work. Let met explain:

My project looks like:

          |-Springtestv_01
            |-src/main/java
              |--com.person <-- it's a main package
                 |-Main.java
                 |-Person.java
                 |-PersonLineRunner.java
                 |-PersonRepository.java
                 |-PersonController.java
              |-com.controller <-- second package, I want put here PersonController.java
            |-src/main/resources
              |-data.sql
            pom.xml

My controller looks:

@RestController
public class PersonController {

    @Autowired PersonRepository personRepository;

    @RequestMapping("/persons")
    Collection<Person> persons(){
        return this.personRepository.findAll();
    }
}  

When everything is in com.person package, I write in web brower http://localhost:8080/persons and it works correctly... But I Want move PersonController.java to com.controller package, and when I moved it, my webbrowers calls me

There was an unexpected error (type=Not Found, status=404). No message available

and I have no idea what I should do to repair it. Maybe I should change something in my pom.xml ??

My pom.xml looks like

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.person</groupId>
    <artifactId>person</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>SpringTest_v0_1</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.0.BUILD-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId><artifactId>h2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>
                spring-boot-starter-data-elasticsearch
            </artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

</project>

It is generated automatically, I write only one dependency

    <dependency>
        <groupId>com.h2database</groupId><artifactId>h2</artifactId>
    </dependency>
CeZet
  • 1,473
  • 5
  • 22
  • 44

12 Answers12

85

Use basePackages:

@ComponentScan(basePackages = { "com.person","com.controller"} )
Imal Hasaranga Perera
  • 9,683
  • 3
  • 51
  • 41
question_maven_com
  • 2,457
  • 16
  • 21
  • 5
    Where write it ? In my `Main.java` ? – CeZet Oct 09 '15 at 14:24
  • 11
    `@SpringBootApplication @ComponentScan({"com.person","com.controller"}) public class Main { public static void main(String[] args) { SpringApplication.run(Main.class, args); } }` I add like U see and it works !! THANKS ! :) – CeZet Oct 09 '15 at 14:37
  • The variable `basePackages` is needed to something ? – CeZet Oct 09 '15 at 14:38
  • hi i wanna know why and when should we need to add base packages lik this for what kind of annotation to work with? – Jasbin karki Jul 02 '18 at 13:45
7

I had the same problem the answers provided here worked for me but i had to add another spring annotation and it's more general in case dealing with a lot of repositories. We have the following structure :

 |-src/main/java
    |--com.person 
       |--repositories
       |--controllers
       |--...

This then should be added in th main

@SpringBootApplication(scanBasePackages = {"com.person"}) 
@EnableMongoRepositories(basePackages = "com.person.repositories")
public class MainDemoApplication { //
}
DevRj
  • 448
  • 8
  • 19
6

Using a @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan.

From the documentation:

ComponentScan configures component scanning directives for use with @Configuration classes. Provides support parallel with Spring XML's element.

One of basePackageClasses(), basePackages() or its alias value() may be specified to define specific packages to scan. If specific packages are not defined scanning will occur from the package of the class with this annotation.

You can either move it as you did or specify basePackages in @ComponentScan.

sco1
  • 12,154
  • 5
  • 26
  • 48
spm
  • 190
  • 9
4

We can use @ComponentScan (basePackages = {"include your package name here"}).

Also if you have some common package naming format, then we can include just common part of package name with * like @ComponentScan(basePackages = { "com.*"}, so that all packages having that common package name will get scanned.

Pavlo Zhukov
  • 3,007
  • 3
  • 26
  • 43
Adimax
  • 41
  • 1
4

I had the same problem but suddenly found that my Application.java class (the class with main method and @SpringBootApplication annotation) located in different but parallel package with @Controller class.

The thing is that Application.java class should be in same or on top of all other packages, then we don't need any @ComponentScan and all beans will be scanned automatically. For example: if Application.java located in com.person and all application beans located in com.person, then it will work without @ComponentScan.

Denys
  • 1,308
  • 12
  • 13
  • This is my preferred solution. In my case I simply moved the Application.java one directory up to automatically scan both controllers from different sub-packages. – Pam Stums Jul 21 '20 at 19:39
4

Assuming the main method is in the package called com.setech.app and a controller is in a package called com.setech.controller.

For spring-boot 1.3.x upwards try this by adding "scanBasePackages" like this.

@SpringBootApplication(scanBasePackages = { "com.setech"} )
public class ResttanslatorApplication {

    public static void main(String[] args) {

        SpringApplication.run(ResttanslatorApplication.class, args);
    }

}

Credit goes to Kamil Wozniak from here.

Shirantha Madusanka
  • 1,461
  • 1
  • 11
  • 16
2

Instead of using ComponentsScan, we can use @Import.

@Configuration

@Import({PersonController.class})

public class MainClassHome {

    public static void main(String[] args) {
        SpringApplication.run(MainClassHome.class, args);
    }
}
Akash
  • 58
  • 4
2

For Maven Case: if you put the controller in another different sub-module(not same as main class), you should add dependency in pom.xml.

andy65007
  • 35
  • 5
2

Moving the Springbootapplication(application.java) file to another package resolved the issue for me. Keep it separate from the controllers and repositories. You can use any number of packages and have multiple controllers.But use @ComponenScan(basePackages={" "," "}) and mention all the packages.

Also, you may face this issue Consider defining a bean of type.. click here!

Chakri
  • 139
  • 1
  • 11
1

You just only define a package name in @ComponentScan like :

@SpringBootApplication
@ComponentScan({"com.project.pck_name"})
public class MainClassHome {

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

and update project after that:- right click on Your project -> maven -> update project

Geet Thakur
  • 1,966
  • 1
  • 16
  • 23
0

As the one who has struggled with the issue, if you found provided solution didn't work.
Please check whether you put source files at the root level directly, for instance,
src\main\java\xxx.java

It has negative effect to project but I don't know the root cause. Anyway,

Please put source files to at least a self-created package like: src\main\java\pack1\xxx.java

Try other settings again. It did solve my problem.

Eugene
  • 10,627
  • 5
  • 49
  • 67
0

I find, that if you put the Controller classes in a separate jar, @Componentscan does not find the @RestControllers. However, @SpringBootApplication(scanBasePackages =.. does that trick much better. I used release train springboot spring-cloud-starter-parent, Greenwich.SR4 This resolves to spring boot 2.1.10.Release So, in this release, @SpringBootApplication <> @Componentscan behaviour on that matter.

Roland Roos
  • 1,003
  • 10
  • 4