Resolving UnsatisfiedDependencyException When Adding ShedLock to Spring Boot

Resolving UnsatisfiedDependencyException When Adding ShedLock to Spring Boot

Understanding the Problem

The UnsatisfiedDependencyException in your Spring Boot application arises due to a misconfigured PoolingHttpClientConnectionManager bean. The error explicitly states:

java.lang.IllegalArgumentException: Max per route value may not be negative or zero

This occurs when the parameters httpConnMaxTotal and httpConnMaxPerRoute in your connectionManagerTest() method are not properly initialized, leading to invalid values (≤ 0) for connection pool limits.


Root Cause Analysis

  1. Missing Property Injection
    The @Value annotations for httpConnMaxTotal and httpConnMaxPerRoute are likely missing or pointing to undefined properties in your application.properties/application.yml file. For example:
   @Value("${http.conn.max.total}")  // Ensure these properties exist
   private int httpConnMaxTotal;
   @Value("${http.conn.max.per.route}")
   private int httpConnMaxPerRoute;


If these properties are not set, Spring defaults to 0, triggering the error.

  1. Profile-Specific Configuration
    The @Profile({"test", "default"}) annotation indicates this bean is active only in specific environments. If your test environment lacks these properties, the values default to 0.
  2. ShedLock Configuration Conflicts
    Adding ShedLock may interfere with existing beans (e.g., ScheduledExecutorService), especially if PROXY_SCHEDULER mode is used. However, in this case, the primary issue is unrelated to ShedLock itself but stems from the connection manager setup.

Step-by-Step Fix

1. Validate Property Values

Ensure your properties file (e.g., application-test.properties) includes:

http.conn.max.total=20    # Example value > 0
http.conn.max.per.route=10


Always use positive integers for connection pool limits.

2. Fix the Bean Configuration

Update the connectionManagerTest() method to avoid duplicate setDefaultMaxPerRoute calls and ensure correct property injection:

@Profile({"test", "default"})
@Bean(name = "connectionManager")
public PoolingHttpClientConnectionManager connectionManagerTest(
    @Value("${http.conn.max.total}") int maxTotal,
    @Value("${http.conn.max.per.route}") int maxPerRoute) {

    PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
    connManager.setMaxTotal(maxTotal);  // Set max total connections
    connManager.setDefaultMaxPerRoute(maxPerRoute);  // Set per-route limit
    return connManager;
}

3. Verify ShedLock Configuration

While ShedLock isn’t the direct cause here, ensure its setup doesn’t conflict with other beans:

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT10M")
public class ShedLockConfig {
    @Bean
    public LockProvider lockProvider(DataSource dataSource) {
        return new JdbcTemplateLockProvider(dataSource);
    }
}


Avoid defining multiple ScheduledExecutorService beans unless necessary.


Preventing Future Issues

  • Use Constructor Injection: Reduces ambiguity in dependency resolution.
  • Profile-Specific Properties: Define environment-specific configurations to avoid defaulting to invalid values.
  • Integration Tests: Validate bean creation in test environments using @SpringBootTest.

Conclusion

The error stems from uninitialized properties for HTTP connection limits, not ShedLock itself. By ensuring proper property injection and validating profile-specific configurations, you can resolve the UnsatisfiedDependencyException and maintain robust distributed task scheduling with ShedLock. For further ShedLock best practices, refer to 42talents.com.

Need more help? Explore Baeldung’s guide on dependency resolution in Spring.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *