'Field required a bean of type that could not be found.' error spring restful API using mongodb

Eka Rudianto picture Eka Rudianto · Mar 20, 2017 · Viewed 259.2k times · Source

So I've been learning Spring in the couples of week, been following this tutorial

Building a RESTful Web Service

All was well until I tried to integrate it to mongodb. So I follow this tutorial.

Accessing Data with MongoDB

But my practice is partially still using the first one. So my project directory structure is like this.

src/
├── main/
│   └── java/
|       ├── model/
|       |   └── User.java
|       ├── rest/
|       |   ├── Application.java
|       |   ├── IndexController.java
|       |   └── UsersController.java
|       └── service/
|           └── UserService.java
└── resources/
    └── application.properties

This is my model/User.java file

package main.java.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection="user")
public class User {

    private int age;
    private String country; 
    @Id
    private String id;
    private String name;


    public User() {
        super();
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}

This is my rest/UsersController.java file

package main.java.rest;

import java.util.List;
import main.java.service.UserService;
import main.java.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/users")
public class UsersController {

    @Autowired
    UserService userService;

    @RequestMapping(method = RequestMethod.GET)
    public List<User> getAllUsers() {
        return userService.findAll();
    }
}

This is my service/UserService.java file

package main.java.service;

import java.util.List;
import main.java.model.User;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface UserService extends MongoRepository<User, String> {
    public List<User> findAll();
}

I could compile them (I'm using gradle for compilation because I'm following the tutorial), but when I run the jar file it was throwing this error.


APPLICATION FAILED TO START


Description:

Field userService in main.java.rest.UsersController required a bean of type 'main.java.service.UserService' that could not be found.

Action:

Consider defining a bean of type 'main.java.service.UserService' in your configuration.

Not sure what is wrong I start googling around and found that I need to include Beans.xml file and register the userService in it. I did that but it's not working. I'm really new to this so I really have no clue on what's going on.

Answer

Eka Rudianto picture Eka Rudianto · Apr 2, 2017

Solved it. So by default, all packages that falls under @SpringBootApplication declaration will be scanned.

Assuming my main class ExampleApplication that has @SpringBootApplication declaration is declared inside com.example.something, then all components that falls under com.example.something is scanned while com.example.applicant will not be scanned.

So, there are two ways to do it based on this question. Use

@SpringBootApplication(scanBasePackages={
"com.example.something", "com.example.application"})

That way, the application will scan all the specified components, but I think what if the scale were getting bigger ?

So I use the second approach, by restructuring my packages and it worked ! Now my packages structure became like this.

src/
├── main/
│   └── java/
|       ├── com.example/
|       |   └── Application.java
|       ├── com.example.model/
|       |   └── User.java
|       ├── com.example.controller/
|       |   ├── IndexController.java
|       |   └── UsersController.java
|       └── com.example.service/
|           └── UserService.java
└── resources/
    └── application.properties