CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-micronaut--micronaut-inject

Core dependency injection interfaces and components for the Micronaut Framework

Pending
Overview
Eval results
Files

exceptions.mddocs/

Exception Handling

Micronaut Inject provides a comprehensive exception hierarchy for handling dependency injection errors, bean resolution failures, and configuration issues. Understanding these exceptions is crucial for proper error handling and debugging.

Exception Hierarchy

BeanContextException

Base exception for all bean context related errors.

public class BeanContextException extends RuntimeException {
    public BeanContextException(String message);
    public BeanContextException(String message, Throwable cause);
}

NoSuchBeanException

Thrown when a required bean cannot be found in the context.

public class NoSuchBeanException extends BeanContextException {
    public NoSuchBeanException(Class<?> beanType);
    public NoSuchBeanException(Class<?> beanType, Qualifier<?> qualifier);
    public NoSuchBeanException(String message);
    
    public Class<?> getBeanType();
    public Qualifier<?> getQualifier();
}

NonUniqueBeanException

Thrown when multiple beans match a type but only one is expected.

public class NonUniqueBeanException extends BeanContextException {
    public NonUniqueBeanException(Class<?> beanType, Collection<BeanDefinition<?>> possibleCandidates);
    
    public Class<?> getBeanType();
    public Collection<BeanDefinition<?>> getPossibleCandidates();
}

BeanInstantiationException

Thrown when bean instantiation fails.

public class BeanInstantiationException extends BeanContextException {
    public BeanInstantiationException(String message);
    public BeanInstantiationException(String message, Throwable cause);
    public BeanInstantiationException(BeanDefinition<?> beanDefinition, Throwable cause);
    
    public BeanDefinition<?> getBeanDefinition();
}

DependencyInjectionException

Thrown when dependency injection fails.

public class DependencyInjectionException extends BeanContextException {
    public DependencyInjectionException(String message);
    public DependencyInjectionException(String message, Throwable cause);
    public DependencyInjectionException(BeanDefinition<?> beanDefinition, Argument<?> argument, String message);
    
    public BeanDefinition<?> getBeanDefinition();
    public Argument<?> getArgument();
}

Configuration Exceptions

ConfigurationException

Thrown when configuration-related errors occur.

public class ConfigurationException extends RuntimeException {
    public ConfigurationException(String message);
    public ConfigurationException(String message, Throwable cause);
}

Common Error Scenarios

Missing Bean Errors

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.exceptions.NoSuchBeanException;

public class MissingBeanExample {
    public static void main(String[] args) {
        try (ApplicationContext context = ApplicationContext.run()) {
            
            try {
                // This will throw NoSuchBeanException if UserService is not registered
                UserService service = context.getBean(UserService.class);
                service.createUser("John");
                
            } catch (NoSuchBeanException e) {
                System.err.println("Bean not found: " + e.getBeanType().getSimpleName());
                System.err.println("Available alternatives:");
                
                // Try to find similar beans
                context.getBeanDefinitions(Object.class).stream()
                    .filter(def -> def.getBeanType().getSimpleName().contains("Service"))
                    .forEach(def -> System.err.println("  - " + def.getBeanType().getName()));
            }
        }
    }
}

Multiple Bean Candidates

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.exceptions.NonUniqueBeanException;
import io.micronaut.inject.qualifiers.Qualifiers;

// Multiple implementations
@Singleton
public class EmailNotificationService implements NotificationService {
    // Email implementation
}

@Singleton  
public class SmsNotificationService implements NotificationService {
    // SMS implementation
}

public class NonUniqueBeanExample {
    public static void main(String[] args) {
        try (ApplicationContext context = ApplicationContext.run()) {
            
            try {
                // This will throw NonUniqueBeanException
                NotificationService service = context.getBean(NotificationService.class);
                
            } catch (NonUniqueBeanException e) {
                System.err.println("Multiple beans found for: " + e.getBeanType().getSimpleName());
                System.err.println("Candidates:");
                
                for (BeanDefinition<?> candidate : e.getPossibleCandidates()) {
                    System.err.println("  - " + candidate.getBeanType().getName());
                }
                
                // Resolve using qualifier
                NotificationService emailService = context.getBean(
                    NotificationService.class, 
                    Qualifiers.byName("email")
                );
            }
        }
    }
}

Bean Instantiation Failures

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.exceptions.BeanInstantiationException;

@Singleton
public class ProblematicService {
    
    public ProblematicService() {
        // This constructor throws an exception
        if (System.currentTimeMillis() % 2 == 0) {
            throw new RuntimeException("Random initialization failure");
        }
    }
}

public class InstantiationErrorExample {
    public static void main(String[] args) {
        try (ApplicationContext context = ApplicationContext.run()) {
            
            try {
                ProblematicService service = context.getBean(ProblematicService.class);
                
            } catch (BeanInstantiationException e) {
                System.err.println("Failed to create bean: " + e.getBeanDefinition().getBeanType());
                System.err.println("Cause: " + e.getCause().getMessage());
                
                // Log full stack trace for debugging
                e.printStackTrace();
            }
        }
    }
}

Dependency Injection Failures

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.exceptions.DependencyInjectionException;

@Singleton
public class ServiceWithDependency {
    
    @Inject
    public ServiceWithDependency(NonExistentService dependency) {
        // This will fail because NonExistentService doesn't exist
    }
}

public class DependencyInjectionErrorExample {
    public static void main(String[] args) {
        try (ApplicationContext context = ApplicationContext.run()) {
            
            try {
                ServiceWithDependency service = context.getBean(ServiceWithDependency.class);
                
            } catch (DependencyInjectionException e) {
                System.err.println("Dependency injection failed for: " + 
                    e.getBeanDefinition().getBeanType().getSimpleName());
                
                if (e.getArgument() != null) {
                    System.err.println("Failed argument: " + e.getArgument().getName() + 
                        " (" + e.getArgument().getType().getSimpleName() + ")");
                }
                
                System.err.println("Reason: " + e.getMessage());
            }
        }
    }
}

Configuration Error Handling

Property Resolution Errors

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.exceptions.ConfigurationException;
import io.micronaut.context.env.Environment;

public class ConfigurationErrorExample {
    public static void main(String[] args) {
        try (ApplicationContext context = ApplicationContext.run()) {
            Environment env = context.getEnvironment();
            
            try {
                // This will throw ConfigurationException if property is missing
                String requiredValue = env.getRequiredProperty("required.property", String.class);
                
            } catch (ConfigurationException e) {
                System.err.println("Configuration error: " + e.getMessage());
                
                // Show available properties for debugging
                System.err.println("Available properties:");
                env.getPropertySources().forEach(source -> {
                    System.err.println("  Source: " + source.getName());
                });
            }
        }
    }
}

Configuration Properties Validation

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.exceptions.BeanInstantiationException;
import jakarta.validation.ConstraintViolationException;

@ConfigurationProperties("database")
public class DatabaseConfig {
    
    @NotBlank
    private String url;
    
    @Min(1)
    @Max(100)
    private int maxConnections;
    
    // Getters and setters
}

public class ValidationErrorExample {
    public static void main(String[] args) {
        // Run without proper configuration
        try (ApplicationContext context = ApplicationContext.run()) {
            
            try {
                DatabaseConfig config = context.getBean(DatabaseConfig.class);
                
            } catch (BeanInstantiationException e) {
                if (e.getCause() instanceof ConstraintViolationException) {
                    ConstraintViolationException validationError = 
                        (ConstraintViolationException) e.getCause();
                    
                    System.err.println("Configuration validation failed:");
                    validationError.getConstraintViolations().forEach(violation -> {
                        System.err.println("  " + violation.getPropertyPath() + 
                            ": " + violation.getMessage());
                    });
                }
            }
        }
    }
}

Error Recovery Strategies

Graceful Degradation

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.exceptions.NoSuchBeanException;

@Singleton
public class ResilientService {
    
    private final NotificationService notificationService;
    private final boolean notificationEnabled;
    
    @Inject
    public ResilientService(ApplicationContext context) {
        // Try to get notification service, fall back to null if not available
        NotificationService service = null;
        boolean enabled = false;
        
        try {
            service = context.getBean(NotificationService.class);
            enabled = true;
        } catch (NoSuchBeanException e) {
            System.warn.println("Notification service not available, continuing without notifications");
        }
        
        this.notificationService = service;
        this.notificationEnabled = enabled;
    }
    
    public void processOrder(Order order) {
        // Core processing always works
        order.setStatus(OrderStatus.PROCESSED);
        
        // Optional notification
        if (notificationEnabled && notificationService != null) {
            try {
                notificationService.sendOrderConfirmation(order);
            } catch (Exception e) {
                System.err.println("Failed to send notification, but order was processed: " + e.getMessage());
            }
        }
    }
}

Optional Dependencies

import io.micronaut.context.ApplicationContext;
import java.util.Optional;

@Singleton
public class FlexibleService {
    
    private final Optional<CacheService> cacheService;
    private final Optional<MetricsService> metricsService;
    
    @Inject  
    public FlexibleService(ApplicationContext context) {
        this.cacheService = context.findBean(CacheService.class);
        this.metricsService = context.findBean(MetricsService.class);
    }
    
    public String getData(String key) {
        // Try cache first if available
        if (cacheService.isPresent()) {
            String cached = cacheService.get().get(key);
            if (cached != null) {
                metricsService.ifPresent(metrics -> metrics.increment("cache.hit"));
                return cached;
            }
        }
        
        // Fetch from database
        String data = fetchFromDatabase(key);
        
        // Cache if service available
        cacheService.ifPresent(cache -> cache.put(key, data));
        metricsService.ifPresent(metrics -> metrics.increment("cache.miss"));
        
        return data;
    }
}

Retry and Fallback

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.exceptions.BeanInstantiationException;

@Singleton
public class RetryableService {
    
    private ExternalService externalService;
    private final int maxRetries = 3;
    
    @PostConstruct
    public void initialize() {
        // Retry bean creation with backoff
        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                this.externalService = createExternalService();
                break;
            } catch (BeanInstantiationException e) {
                System.err.println("Attempt " + attempt + " failed: " + e.getMessage());
                
                if (attempt == maxRetries) {
                    System.err.println("All attempts failed, using fallback service");
                    this.externalService = new FallbackExternalService();
                } else {
                    // Wait before retry
                    try {
                        Thread.sleep(1000 * attempt);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
    }
}

Debugging Bean Issues

Bean Resolution Debugging

import io.micronaut.context.ApplicationContext;
import io.micronaut.inject.BeanDefinition;

public class BeanDebuggingUtils {
    
    public static void debugBeanResolution(ApplicationContext context, Class<?> beanType) {
        System.out.println("Debugging bean resolution for: " + beanType.getSimpleName());
        
        // Check if bean exists
        boolean exists = context.containsBean(beanType);
        System.out.println("Bean exists: " + exists);
        
        if (!exists) {
            // Show similar beans
            System.out.println("Similar beans:");
            context.getBeanDefinitions(Object.class).stream()
                .filter(def -> def.getBeanType().getSimpleName().contains(beanType.getSimpleName()))
                .forEach(def -> System.out.println("  - " + def.getBeanType().getName()));
        } else {
            // Show bean details
            Collection<BeanDefinition<?>> definitions = context.getBeanDefinitions(beanType);
            System.out.println("Found " + definitions.size() + " bean(s):");
            
            for (BeanDefinition<?> def : definitions) {
                System.out.println("  Bean: " + def.getBeanType().getName());
                System.out.println("    Scope: " + (def.isSingleton() ? "Singleton" : "Prototype"));
                System.out.println("    Constructor args: " + def.getConstructorArguments().size());
                System.out.println("    Injected methods: " + def.getInjectedMethods().size());
                System.out.println("    Injected fields: " + def.getInjectedFields().size());
            }
        }
    }
    
    public static void listAllBeans(ApplicationContext context) {
        System.out.println("All registered beans:");
        
        context.getBeanDefinitions(Object.class).stream()
            .sorted((a, b) -> a.getBeanType().getName().compareTo(b.getBeanType().getName()))
            .forEach(def -> {
                System.out.println("  " + def.getBeanType().getName() + 
                    " [" + (def.isSingleton() ? "Singleton" : "Prototype") + "]");
            });
    }
}

Exception Chaining Analysis

import io.micronaut.context.exceptions.BeanContextException;

public class ExceptionAnalyzer {
    
    public static void analyzeBeanException(BeanContextException e) {
        System.err.println("=== Bean Exception Analysis ===");
        System.err.println("Exception type: " + e.getClass().getSimpleName());
        System.err.println("Message: " + e.getMessage());
        
        // Analyze specific exception types
        if (e instanceof NoSuchBeanException) {
            NoSuchBeanException nsbe = (NoSuchBeanException) e;
            System.err.println("Missing bean type: " + nsbe.getBeanType());
            if (nsbe.getQualifier() != null) {
                System.err.println("Required qualifier: " + nsbe.getQualifier());
            }
            
        } else if (e instanceof NonUniqueBeanException) {
            NonUniqueBeanException nube = (NonUniqueBeanException) e;
            System.err.println("Ambiguous bean type: " + nube.getBeanType());
            System.err.println("Candidates (" + nube.getPossibleCandidates().size() + "):");
            nube.getPossibleCandidates().forEach(candidate -> 
                System.err.println("  - " + candidate.getBeanType().getName()));
                
        } else if (e instanceof BeanInstantiationException) {
            BeanInstantiationException bie = (BeanInstantiationException) e;
            if (bie.getBeanDefinition() != null) {
                System.err.println("Failed bean: " + bie.getBeanDefinition().getBeanType());
            }
        }
        
        // Show cause chain
        Throwable cause = e.getCause();
        int level = 1;
        while (cause != null) {
            System.err.println("Cause " + level + ": " + cause.getClass().getSimpleName() + 
                " - " + cause.getMessage());
            cause = cause.getCause();
            level++;
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-io-micronaut--micronaut-inject

docs

annotations.md

application-context.md

bean-definition.md

bean-factory.md

bean-processing.md

bean-providers.md

environment-config.md

events.md

exceptions.md

index.md

scoping.md

tile.json