Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring UnsatisfiedDependencyException after project tree changed

I am new to Spring and I am trying to make a simple rest application. When I had all of my files in one package, the application worked fine. Since I've changed my project organisation, I can't build my project. I am getting this error:

2017-09-30 22:32:48.428  WARN 9428 --- [           main] o.s.w.c.s.GenericWebApplicationContext   : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'application': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'socketApp.dal.repository.CustomerRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    2017-09-30 22:32:48.431  INFO 9428 --- [           main] utoConfigurationReportLoggingInitializer : 

    Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
    2017-09-30 22:32:48.495 ERROR 9428 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

    ***************************
    APPLICATION FAILED TO START
    ***************************

    Description:

    Field repository in socketApp.main.Application required a bean of type 'socketApp.dal.repository.CustomerRepository' that could not be found.


    Action:

    Consider defining a bean of type 'socketApp.dal.repository.CustomerRepository' in your configuration.

    2017-09-30 22:32:48.496 ERROR 9428 --- [           main] o.s.test.context.TestContextManager      : Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@16267862] to prepare test instance [hello.GreetingControllerTests@47f08b81]

My current project tree looks like this

src 
  main 
    java
      app
        dal
          model
            -Customer.java
          repository
            -CustomerRepository.java
        main
          -Aplication.java
        webServices
          -GreetingController.java

Here is my Customer.java file:

package socketApp.dal.model;

import org.springframework.data.annotation.Id;


public class Customer {

    @Id
    public String id;

    public String firstName;
    public String lastName;

    public Customer() {}

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format(
                "Customer[id=%s, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }

}

My CustomerRepository.java file:

    package socketApp.dal.repository;


import java.util.List;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import socketApp.dal.model.Customer;

@Repository
public interface CustomerRepository extends MongoRepository<Customer, String> {

    public Customer findByFirstName(String firstName);
    public List<Customer> findByLastName(String lastName);


}

My Application.java

    package socketApp.main;



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import socketApp.dal.model.Customer;
import socketApp.dal.repository.CustomerRepository;

@SpringBootApplication

public class Application implements CommandLineRunner{

    @Autowired 
    private CustomerRepository repository;

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

    @Override
    public void run(String... args) throws Exception {

        repository.deleteAll();

        // save a couple of customers
        repository.save(new Customer("Alice", "Smith"));
        repository.save(new Customer("Bob", "Smith"));

        // fetch all customers
        System.out.println("Customers found with findAll():");
        System.out.println("-------------------------------");
        for (Customer customer : repository.findAll()) {
            System.out.println(customer);
        }
        System.out.println();

        // fetch an individual customer
        System.out.println("Customer found with findByFirstName('Alice'):");
        System.out.println("--------------------------------");
        System.out.println(repository.findByFirstName("Alice"));

        System.out.println("Customers found with findByLastName('Smith'):");
        System.out.println("--------------------------------");
        for (Customer customer : repository.findByLastName("Smith")) {
            System.out.println(customer);
        }

    }
}

And finally my GreetingController.java

   package socketApp.webServices;



import socketApp.dal.repository.CustomerRepository;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import socketApp.dal.model.Customer;
import socketApp.dal.model.Greeting;

@RestController
public class GreetingController {

    @Autowired 
    private CustomerRepository repository;


    @RequestMapping("/")
    public List<Customer> getAllCustomers(){
        // fetch all customers
    return repository.findAll();
    }
} 
like image 802
tprieboj Avatar asked Aug 01 '26 15:08

tprieboj


2 Answers

You either have to move the Application class up one package so that the class is in a package above the others or manually specify the basePackage via scanBasePackages or scanBasePackageClasses for the component scan initiated by your @SpringBootApplication.

See

  • Using the @SpringBootApplication annotation and
  • Structuring your code

for more details.

like image 83
luk2302 Avatar answered Aug 04 '26 07:08

luk2302


By default @SpringBootApplication will scan for components only packages "descending" from package of annotated class.

So in your case, because main class is in socketApp.main and repository is in socketApp.dal.repository then it won't be found.

You have two options:

Move Application to package socketApp.

package socketApp;    

...

@SpringBootApplication
public class Application implements CommandLineRunner {
...

Or add additional @ComponentScan annotation. In your case it would be:

@SpringBootApplication
@ComponentScan("socketApp")
public class Application implements CommandLineRunner {
...

I my opinion first option is better.

like image 22
Krzysztof Atłasik Avatar answered Aug 04 '26 06:08

Krzysztof Atłasik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!