๐ด The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method userController in com.devinhyderabad.config.AppConfig required a single bean, but 2 were found:
- userServiceImpl: defined in file [/com/devinhyderabad/service/UserServiceImpl.class]
- mockUserService: defined in file [/com/devinhyderabad/service/MockUserService.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumedโก Quick Fix Works 80% of the time
Add @Primary to the implementation you want Spring to use by default.
@Service
@Primary
public class UserServiceImpl implements UserService {}๐ง Why this Happens
Tap to expand the deep technical explanation
Spring found multiple classes implementing the same interface (e.g., `UserService`). When you tried to autowire `UserService`, Spring didn't know which one to inject, so it crashed and asked you to clarify which one is the primary choice.
The HITEC City Parking Spot Analogy:
You ask a friend to bring you 'a soda'. They look in the fridge and see both Coke and Pepsi. They freeze, unsure which one you want, and refuse to bring either until you specify (@Qualifier) or tell them your default favorite (@Primary).
๐ How to Reproduce Confirm this is your error
Create two classes `UserServiceImpl` and `MockUserService` that both implement `UserService`. Annotate both with `@Service`. In a controller, `@Autowired private UserService userService;`. Run the app.
๐ ๏ธ Solutions (5 Ways to Fix)
Mark one bean as @Primary
๐ Use this when you have a default implementation and want Spring to pick it automatically.
Adding @Primary tells Spring: 'If you find multiple candidates, always choose this one.'
@Service
@Primary
public class UserServiceImpl implements UserService { ... }Use @Qualifier at the injection point
๐ Use this when you want explicit control over which bean is injected at different locations.
Tell Spring exactly which bean name to inject at the exact @Autowired field.
@RestController
public class UserController {
@Autowired
@Qualifier("mockUserService")
private UserService userService;
}Use a specific implementation type instead of interface
๐ Use this if you are okay with tight coupling and don't want to use @Qualifier.
Instead of autowiring the interface, autowire the exact implementation class.
@RestController
public class UserController {
@Autowired
private UserServiceImpl userService; // Specifically asks for UserServiceImpl
}Exclude one implementation from component scanning
๐ Use this if one of the beans was created by mistake or for testing and shouldn't be in the app.
Remove the @Service annotation from the unwanted class, or use @ComponentScan excludeFilters to block it.
@SpringBootApplication
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MockUserService.class))
public class Application { ... }Combine implementations using a List/Map injection
๐ Use this if you actually want to use all implementations dynamically (e.g., plugin pattern).
Spring can inject all beans of a type into a List. You can then iterate over them.
@Service
public class Dispatcher {
@Autowired
private List<UserService> userServices; // Spring injects all implementations
}๐ Version Notes
Throws NoUniqueBeanDefinitionException.
Provides the 'Consider marking one of the beans as @Primary' FailureAnalyzer message.
๐ก๏ธ How to Prevent This Next Time
When creating mock or alternative implementations for testing, ensure they are only active in specific profiles using `@Profile("test")`.