No found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: – Java

Photo of author
Written By M Ibrahim
amazon-web-services azure-java-sdk soapui spring

Quick Fix: Annotate the implementing class UserDaoImp with @Component or @Repository, allowing component scan to automatically create a bean for it, similar to how you did for UserService. Alternatively, manually add the bean definition in the XML file, ensuring it is defined before the component scan.

The Problem:

When trying to write a Spring-based SOAP service, you encounter a Dependency Injection issue stemming from the use of @Autowired in the service. The error states there is no qualifying bean for the UserDao dependency, despite having a bean defined for it in the XML mapping file.

The Solutions:

Solution 1: Add the `UserDaoImpl` bean manually to the xml file.

This approach is a little more verbose than using component scanning, but it gives you more control over the bean definition. Here’s how you would do it:

Step 1: Add the bean definition to the xml file. Place this code before the component scan:

<bean id="userDao" class="edu.java.spring.ws.dao.UserDaoImpl" />

Step 2: Remove the @Autowired annotation from the UserDaoImpl class.

Now, Spring should be able to inject the userDao bean into the UserBoImpl class. When the userBo bean is created, Spring will automatically wire it into the UserService class.

This is the rewritten solution according to the given constraints.

Solution 2: Use `@MockBean` to provide beans for dependency injection

To fix the issue, you can use the `@MockBean` annotation to provide beans for dependency injection in your test class. This annotation allows you to create a mock implementation of the `UserDao` interface and inject it into the `UserService` instance.

Here’s an updated version of your test class:

@WebMvcTest(UserService.class)
@AutoConfigureMockMvc
class UserServiceTests {

@Autowired
private MockMvc mockMvc;

@MockBean
private UserBo userBo;

@MockBean
private UserDao userDao;

@Test
void shouldSayHello() throws Exception {
    mockMvc.perform(get("/user/say?name=John Doe"))
            .andExpect(status().isOk())
            .andExpect(content().string("Hello Java to John Doe"));
}

@Test
void shouldGetUser() throws Exception {
    User user = new User();
    user.setId(1L);
    user.setUsername("John Doe");

    Mockito.when(userDao.getUser("John Doe")).thenReturn(user);

    mockMvc.perform(get("/user/get?username=John Doe"))
            .andExpect(status().isOk())
            .andExpect(content().json(objectMapper.writeValueAsString(user)));
}

}

Solution 3: Annotate the Implementation Class with `@Repository`

To resolve the NoSuchBeanDefinitionException, you need to explicitly specify that the UserDaoImpl class is a Spring Data repository. To do this, add the @Repository annotation to the UserDaoImpl class:

@Repository
public class UserDaoImpl implements UserDao {
    // ... your existing code
}

The @Repository annotation indicates that the UserDaoImpl class is a Spring Data repository, making it eligible for automatic bean discovery and dependency injection.

With this modification, Spring will be able to recognize the UserDaoImpl class as a repository and will automatically create a bean for it, allowing the UserBoImpl class to successfully inject the UserDao dependency.

Remember, the @Repository annotation is typically used for classes that implement the Spring Data repository interfaces (CrudRepository, JpaRepository, etc.), but it can also be used on custom repository implementations like UserDaoImpl in this case.

Solution 4: Use @SpringBootTest instead of @DataJpaTest

When using the @DataJpaTest annotation, only the JPA part of a Spring Boot application is loaded. This can cause issues if you are trying to use other beans that are not related to JPA.

To fix this issue, you can change the @DataJpaTest annotation to @SpringBootTest. This will load the full application context, including all of the beans that are defined in your configuration files.

Here is an example of how you can use the @SpringBootTest annotation:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class UserServiceTest {

        @Autowired
        private UserService userService;

        @Test
        public void testSayHello() {
            String result = userService.sayHello("John");
            assertEquals("Hello John", result);
        }

    }

This test will now be able to autowire the UserService bean and call the sayHello() method.

Note: The @SpringBootTest annotation can also be used with the @AutoConfigureTestDatabase annotation to override the default in-memory database settings. For more information, please see the Spring Boot documentation.

Solution 5: Adding @Service Annotation

The @Service annotation is used to mark a class as a Spring bean. It’s a stereotype annotation that is used to indicate that the class is a service component. This annotation is typically used with classes that provide some kind of business logic or functionality.

In your case, you have a class called UserBoImpl that implements the UserBo interface. This class is used to provide business logic for user-related operations. When you add the @Service annotation to this class, it tells Spring that this class is a service component and should be automatically detected and managed by the Spring IoC container.

By adding the @Service annotation, you’re essentially telling Spring that this class is a part of your application’s business logic and should be managed by Spring. This allows Spring to automatically wire up the dependencies of this class and make it available for use in other parts of your application.

Here’s the updated code with the @Service annotation:

@Service
public class UserBoImpl implements UserBo {
    @Autowired
    private UserDao userDao;

    @Override
    public User loadUser(String username) {
        // TODO Auto-generated method stub
        return userDao.getUser(username);
    }
}

After adding the @Service annotation, the error you were encountering should go away. Spring will now be able to automatically wire up the dependencies of the UserBoImpl class and make it available for use in other parts of your application.