Your Spring Boot app crashes with NoSuchBeanDefinitionException. You wrote the class, added @Service, but Spring still can’t find it.
TLDR - Quick Fix
NoSuchBeanDefinitionException means Spring can’t find a bean you’re trying to autowire. Most common causes:
// ❌ PROBLEM: Missing annotation
package com.example.service;
public class EmailService { // No @Service annotation!
public void send(String message) { }
}
// ✅ FIX: Add the annotation
@Service
public class EmailService {
public void send(String message) { }
}
Quick diagnostic steps:
- Check if the class has
@Component,@Service,@Repository, or@Controller - Verify the class is in the component scan path
- Look for typos in
@Qualifiernames - Check if the bean is conditionally excluded (
@Profile,@ConditionalOnProperty) - Verify bean name conflicts aren’t causing issues
Let’s troubleshoot each cause systematically and get your beans wired correctly.
The Error Message
When Spring can’t find a bean, you’ll see something like this:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field userService in com.example.controller.UserController required a bean of type
'com.example.service.UserService' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.example.service.UserService' in your configuration.
This tells you exactly what’s missing:
- Where:
UserControllerneeds a bean - What type:
UserService - How it’s injected:
@Autowired
Armed with this info, you can jump to the right fix.
Cause #1: Missing Component Annotation
This is by far the most common cause. You created the class but forgot to tell Spring it’s a bean.
The symptom:
No qualifying bean of type 'com.example.service.NotificationService' available
What your code looks like:
// ❌ Spring doesn't know this exists
package com.example.service;
public class NotificationService {
public void notify(String message) {
System.out.println("Notification: " + message);
}
}
Meanwhile, in your controller:
@RestController
public class OrderController {
@Autowired
private NotificationService notificationService; // Trying to inject it
@PostMapping("/orders")
public Order createOrder(@RequestBody Order order) {
// Use notification service
notificationService.notify("Order created");
return order;
}
}
Spring scans for components but can’t find NotificationService because it has no annotation.
The fix:
// ✅ Add @Service annotation
package com.example.service;
import org.springframework.stereotype.Service;
@Service
public class NotificationService {
public void notify(String message) {
System.out.println("Notification: " + message);
}
}
Which annotation should you use?
@Service- Business logic layer (most services)@Repository- Data access layer (DAOs, repositories)@Controller/@RestController- Web/API layer@Component- Generic Spring-managed component (utilities, helpers)@Configuration- Configuration classes with@Beanmethods
They’re all functionally equivalent—they all register the class as a Spring bean—but using the semantically correct one makes your code more readable.
Cause #2: Component Not in Scan Path
Even with the annotation, Spring won’t find your bean if it’s outside the component scan path.
How component scanning works:
By default, @SpringBootApplication scans the package where it’s located and all sub-packages:
package com.example;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
This scans:
- ✅
com.example(same package) - ✅
com.example.controller(sub-package) - ✅
com.example.service(sub-package) - ✅
com.example.repository(sub-package) - ❌
com.other(different root package) - ❌
org.utilities(different root package)
The problem - class outside scan path:
src/
main/
java/
com/
example/
Application.java // @SpringBootApplication here
controller/
OrderController.java
org/
external/
service/
PaymentService.java // ❌ Outside com.example!
PaymentService is in org.external.service, which isn’t under com.example, so Spring won’t find it.
Fix #1: Move the class into the scan path
src/
main/
java/
com/
example/
Application.java
controller/
OrderController.java
service/
PaymentService.java // ✅ Now in com.example.service
This is the cleanest solution—keep all your code under one root package.
Fix #2: Add explicit component scan
If you can’t move the class (e.g., it’s from a library or module you don’t control):
@SpringBootApplication
@ComponentScan(basePackages = {
"com.example", // Default package
"org.external" // Additional package to scan
})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Fix #3: Define it as a @Bean
If the class doesn’t have annotations (e.g., third-party library):
@Configuration
public class AppConfig {
@Bean
public PaymentService paymentService() {
return new PaymentService();
}
}
Now Spring knows about PaymentService even though it doesn’t have a @Service annotation.
Cause #3: Qualifier Mismatch
When you have multiple beans of the same type, you use @Qualifier to specify which one you want. Typos or incorrect names cause NoSuchBeanDefinitionException.
The error:
No qualifying bean of type 'com.example.service.PaymentProcessor' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true),
@org.springframework.beans.factory.annotation.Qualifier(value=paypalService)}
The problem:
// Two implementations of the same interface
@Service("creditCardProcessor") // Named "creditCardProcessor"
public class CreditCardProcessor implements PaymentProcessor {
public void process(double amount) { }
}
@Service("stripeProcessor") // Named "stripeProcessor"
public class StripeProcessor implements PaymentProcessor {
public void process(double amount) { }
}
// Trying to inject with wrong name
@RestController
public class PaymentController {
@Autowired
@Qualifier("paypalService") // ❌ No bean with this name!
private PaymentProcessor paymentProcessor;
}
The fix - use correct qualifier:
@RestController
public class PaymentController {
@Autowired
@Qualifier("creditCardProcessor") // ✅ Matches bean name
private PaymentProcessor paymentProcessor;
}
Alternative - use @Primary:
If one implementation is the default choice:
@Service
@Primary // This is the default
public class CreditCardProcessor implements PaymentProcessor {
public void process(double amount) { }
}
@Service
public class StripeProcessor implements PaymentProcessor {
public void process(double amount) { }
}
// No @Qualifier needed - gets the @Primary bean
@RestController
public class PaymentController {
@Autowired
private PaymentProcessor paymentProcessor; // ✅ Gets CreditCardProcessor
}
Cause #4: Conditional Beans Not Created
Spring Boot supports conditional bean creation. If the condition isn’t met, the bean doesn’t exist.
Common conditionals:
@Profile - environment-specific beans:
@Service
@Profile("production") // Only created in production
public class ProductionEmailService implements EmailService {
public void send(String to, String message) {
// Real email sending via SMTP
}
}
@Service
@Profile("dev") // Only created in dev
public class MockEmailService implements EmailService {
public void send(String to, String message) {
System.out.println("Mock email to " + to + ": " + message);
}
}
If you run with --spring.profiles.active=production, only ProductionEmailService gets created. Trying to inject MockEmailService fails.
The fix - use the correct profile:
# Run with dev profile
java -jar app.jar --spring.profiles.active=dev
# Or in application.properties
spring.profiles.active=dev
@ConditionalOnProperty - feature toggles:
@Service
@ConditionalOnProperty(name = "features.notifications.enabled", havingValue = "true")
public class NotificationService {
// Only created if features.notifications.enabled=true
}
If your application.properties has:
features.notifications.enabled=false
The bean won’t be created. Update the property:
features.notifications.enabled=true
@ConditionalOnClass - dependency-based beans:
@Service
@ConditionalOnClass(name = "org.springframework.kafka.core.KafkaTemplate")
public class KafkaEventPublisher {
// Only created if Kafka is on the classpath
}
If Kafka isn’t in your dependencies, this bean doesn’t exist. Add the dependency:
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
@ConditionalOnMissingBean - default implementations:
@Service
@ConditionalOnMissingBean(CacheService.class)
public class DefaultCacheService implements CacheService {
// Only created if no other CacheService exists
}
If you define your own CacheService elsewhere, the default won’t be created. That’s by design.
Cause #5: Constructor vs Field Injection Issues
How you inject dependencies matters. Constructor injection has stricter requirements.
Field injection (more forgiving):
@RestController
public class UserController {
@Autowired
private UserService userService; // Set after construction
}
Spring creates the controller first, then sets the field. If UserService is missing, you get NoSuchBeanDefinitionException at startup.
Constructor injection (fails fast):
@RestController
public class UserController {
private final UserService userService;
// Spring calls this constructor
public UserController(UserService userService) {
this.userService = userService;
}
}
Spring needs UserService to construct UserController. If it’s missing, startup fails immediately.
The problem - optional dependency:
Sometimes you want a bean to be optional:
@RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService; // Fails if UserService doesn't exist
}
}
The fix - make it optional:
@RestController
public class UserController {
private final UserService userService;
// required=false allows null injection
@Autowired(required = false)
public UserController(UserService userService) {
this.userService = userService; // Can be null
}
@GetMapping("/users")
public List<User> getUsers() {
if (userService != null) {
return userService.findAll();
}
return Collections.emptyList();
}
}
Better - use Optional:
@RestController
public class UserController {
private final Optional<UserService> userService;
public UserController(Optional<UserService> userService) {
this.userService = userService;
}
@GetMapping("/users")
public List<User> getUsers() {
return userService
.map(UserService::findAll)
.orElse(Collections.emptyList());
}
}
This makes the optionality explicit in the code.
Cause #6: Bean Definition in @Configuration Not Called
When you define beans manually in @Configuration classes, common mistakes prevent the bean from being created.
Problem #1: Missing @Bean annotation
@Configuration
public class AppConfig {
// ❌ Method runs but Spring doesn't know it creates a bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUrl("jdbc:mysql://localhost/mydb");
return ds;
}
}
Fix:
@Configuration
public class AppConfig {
@Bean // ✅ Now Spring knows this creates a bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUrl("jdbc:mysql://localhost/mydb");
return ds;
}
}
Problem #2: Configuration class not scanned
// ❌ Outside component scan path
package org.other.config;
@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource();
}
}
Fix - import it explicitly:
@SpringBootApplication
@Import(DatabaseConfig.class) // ✅ Explicitly import configuration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Problem #3: Conditional prevents bean creation
@Configuration
public class CacheConfig {
@Bean
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
}
If cache.enabled isn’t set to true, the bean doesn’t exist. Check your properties file.
Debugging Strategy
When you hit NoSuchBeanDefinitionException, follow this systematic approach:
Step 1: Read the error carefully
Extract key information:
- Which bean is missing? (type name)
- Where is it being injected? (controller, service, etc.)
- What’s the qualifier if any?
Step 2: Check if the bean class exists
Search your codebase for the class name from the error. Does it exist?
Step 3: Verify the annotation
Does the class have @Service, @Component, @Repository, or @Controller?
Step 4: Check package structure
Is the class in the component scan path? Print your package structure:
src/main/java/
com/
example/ <-- @SpringBootApplication should be here or above
Application.java
service/ <-- Services should be here or deeper
UserService.java
Step 5: Enable debug logging
Add to application.properties:
logging.level.org.springframework=DEBUG
Look for lines like:
Identified candidate component class: file [UserService.class]
If your bean isn’t listed, Spring isn’t finding it.
Step 6: Check for conditional exclusions
Does the bean have @Profile, @ConditionalOnProperty, etc.? Verify the condition is met.
Step 7: Check bean name
If using @Qualifier, verify the name matches:
@Service("myService") // Bean name is "myService"
public class MyService { }
// Must match exactly
@Autowired
@Qualifier("myService") // ✅ Correct
private MyService service;
Real-World Example: Multi-Module Project
Let me show you a realistic scenario where NoSuchBeanDefinitionException occurs and how to fix it.
Project structure:
my-app/
app-core/
src/main/java/
com/example/core/
service/
UserService.java
app-web/
src/main/java/
com/example/web/
Application.java // @SpringBootApplication
controller/
UserController.java
The problem:
// app-web/controller/UserController.java
@RestController
public class UserController {
@Autowired
private UserService userService; // ❌ NoSuchBeanDefinitionException
}
// app-core/service/UserService.java
@Service
public class UserService {
public List<User> findAll() { return List.of(); }
}
UserService has @Service, but Spring still can’t find it. Why?
The issue: Multi-module projects require explicit component scanning across modules.
Solution #1: Scan the core package
@SpringBootApplication
@ComponentScan(basePackages = {
"com.example.web", // Web module (default)
"com.example.core" // Core module
})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Solution #2: Use a shared base package
Restructure so both modules share a common parent package:
my-app/
app-core/
src/main/java/
com/example/ // Shared parent
core/
service/
UserService.java
app-web/
src/main/java/
com/example/ // Same parent
web/
Application.java
controller/
UserController.java
Now @SpringBootApplication at com.example.web scans com.example, which includes both web and core.
Solution #3: Create a configuration in core module
// app-core/config/CoreConfig.java
@Configuration
@ComponentScan("com.example.core")
public class CoreConfig {
// Configuration for core module
}
// app-web/Application.java
@SpringBootApplication
@Import(CoreConfig.class) // Import core configuration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
This is cleaner because each module declares its own component scanning.
Common Edge Cases
Edge case #1: Abstract classes can’t be beans
@Service // ❌ Spring can't instantiate abstract classes
public abstract class BaseService {
public abstract void execute();
}
// You need a concrete implementation
@Service // ✅ This works
public class ConcreteService extends BaseService {
@Override
public void execute() { }
}
Edge case #2: Interfaces aren’t beans
public interface UserService {
List<User> findAll();
}
@RestController
public class UserController {
@Autowired
private UserService userService; // ❌ Can't inject interface directly
}
// You need an implementation
@Service // ✅ Implementation is the bean
public class UserServiceImpl implements UserService {
@Override
public List<User> findAll() {
return List.of();
}
}
Spring injects the implementation, not the interface.
Edge case #3: Generic types need careful handling
public interface Repository<T> {
T findById(Long id);
}
@Repository
public class UserRepository implements Repository<User> {
public User findById(Long id) { return null; }
}
@Repository
public class OrderRepository implements Repository<Order> {
public Order findById(Long id) { return null; }
}
// This is ambiguous
@Service
public class MyService {
@Autowired
private Repository<?> repository; // ❌ Which one?
}
// Be specific
@Service
public class MyService {
@Autowired
private Repository<User> userRepository; // ✅ Better, but still tricky
// Or use concrete types
@Autowired
private UserRepository userRepository; // ✅ Clearest
}
Edge case #4: Scoped beans accessed incorrectly
@Component
@Scope("prototype") // New instance each time
public class TaskProcessor {
public void process() { }
}
@Configuration
public class AppConfig {
@Autowired
private TaskProcessor taskProcessor; // ❌ Singleton config autowiring prototype
@Bean
public TaskRunner taskRunner() {
// This creates only ONE TaskProcessor instance for the singleton config
return new TaskRunner(taskProcessor);
}
}
// Better approach
@Configuration
public class AppConfig {
@Bean
public TaskRunner taskRunner(TaskProcessor taskProcessor) {
// Prototype bean properly injected
return new TaskRunner(taskProcessor);
}
}
Prevention Checklist
Make these practices standard to avoid NoSuchBeanDefinitionException:
1. Consistent package structure:
com/
yourcompany/
yourapp/
Application.java // @SpringBootApplication here
controller/ // All controllers
service/ // All services
repository/ // All repositories
config/ // All @Configuration classes
2. Always use stereotype annotations:
- Business logic →
@Service - Data access →
@Repository - Web/API →
@Controller/@RestController - Configuration →
@Configuration - Everything else →
@Component
3. Constructor injection (best practice):
@Service
@RequiredArgsConstructor // Lombok generates constructor
public class OrderService {
private final UserRepository userRepository;
private final EmailService emailService;
// Dependencies are final and injected via constructor
}
4. Enable component scan warnings:
# application.properties
logging.level.org.springframework.context.annotation=DEBUG
This logs which components are found during scanning.
5. Write integration tests:
@SpringBootTest
public class ApplicationContextTest {
@Autowired
private ApplicationContext context;
@Test
public void shouldLoadAllRequiredBeans() {
assertNotNull(context.getBean(UserService.class));
assertNotNull(context.getBean(OrderService.class));
assertNotNull(context.getBean(EmailService.class));
// Test all critical beans exist
}
}
This catches missing beans before production.
Key Takeaways
- Check the annotation - 90% of the time, it’s a missing
@Service,@Component, etc. - Verify package structure - Beans must be in the component scan path
- Mind your qualifiers - Typos in
@Qualifiernames cause failures - Check conditionals -
@Profileand@ConditionalOn*can exclude beans - Multi-module projects need explicit scanning - Don’t assume Spring finds everything
- Use debug logging -
logging.level.org.springframework=DEBUGshows what Spring finds - Fail fast with constructor injection - Catches missing dependencies at startup
When you hit NoSuchBeanDefinitionException, the error message tells you exactly what’s missing and where. Use Debugly’s trace formatter to quickly parse and analyze Java stack traces. It highlights the bean type and injection point, helping you identify whether it’s a scanning issue, annotation problem, or conditional exclusion. The formatted output makes it easy to trace back from the error to the root cause.
For more Spring Boot dependency injection problems, check out our guides on Spring Boot BeanCreationException and Spring Boot Circular Dependency.
Happy bean hunting!