CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-awaitility--awaitility

A Java DSL for synchronizing asynchronous operations

Pending
Overview
Eval results
Files

advanced-config.mddocs/

Advanced Configuration

Global defaults, fail-fast conditions, custom executors, and logging for complex testing scenarios and performance optimization.

Capabilities

Global Default Configuration

Set default behavior for all Awaitility await statements.

Timeout Defaults

/**
 * Set default timeout for all await statements
 * @param defaultTimeout maximum wait time for conditions
 */
static void setDefaultTimeout(Duration defaultTimeout);

/**
 * Set default timeout using value and time unit
 * @param timeout timeout value
 * @param unit time unit for timeout
 */
static void setDefaultTimeout(long timeout, TimeUnit unit);

Polling Defaults

/**
 * Set default poll interval for all await statements
 * @param pollInterval time between condition evaluations
 */
static void setDefaultPollInterval(Duration pollInterval);

/**
 * Set default poll interval using value and time unit
 * @param pollInterval interval value
 * @param unit time unit for interval
 */
static void setDefaultPollInterval(long pollInterval, TimeUnit unit);

/**
 * Set default poll interval using custom strategy
 * @param pollInterval polling strategy implementation
 */
static void setDefaultPollInterval(PollInterval pollInterval);

/**
 * Set default poll delay for all await statements
 * @param pollDelay initial delay before first condition check
 */
static void setDefaultPollDelay(Duration pollDelay);

/**
 * Set default poll delay using value and time unit
 * @param pollDelay delay value
 * @param unit time unit for delay
 */
static void setDefaultPollDelay(long pollDelay, TimeUnit unit);

Reset Configuration

/**
 * Reset all configuration to default values:
 * - timeout: 10 seconds
 * - poll interval: 100 milliseconds
 * - poll delay: 100 milliseconds  
 * - catch uncaught exceptions: true
 * - ignore exceptions: false
 * - no condition evaluation listener
 * - no fail fast condition
 */
static void reset();

Global Configuration Examples:

// Configure defaults in test setup
@BeforeClass
public static void setupAwaitility() {
    setDefaultTimeout(Duration.ofMinutes(2));
    setDefaultPollInterval(Duration.ofMillis(50));
    setDefaultPollDelay(Duration.ofMillis(10));
}

@AfterClass
public static void cleanupAwaitility() {
    reset(); // Clean slate for other tests
}

// Configure for specific test environments
public static void configureForIntegrationTests() {
    setDefaultTimeout(5, MINUTES);           // Longer timeouts
    setDefaultPollInterval(500, MILLISECONDS); // Less frequent polling
    setDefaultPollDelay(1, SECONDS);         // Initial delay
}

public static void configureForUnitTests() {  
    setDefaultTimeout(10, SECONDS);          // Shorter timeouts
    setDefaultPollInterval(10, MILLISECONDS); // Frequent polling  
    setDefaultPollDelay(0, MILLISECONDS);    // No initial delay
}

Fail-Fast Conditions

Configure terminal failure conditions to avoid unnecessary waiting.

Boolean Fail-Fast Conditions

/**
 * Set default fail-fast condition for all await statements
 * If condition ever returns true, terminate with TerminalFailureException
 * @param defaultFailFastCondition callable that indicates terminal failure
 */
static void setDefaultFailFastCondition(Callable<Boolean> defaultFailFastCondition);

/**
 * Set default fail-fast condition with descriptive reason
 * @param failFastFailureReason description included in exception
 * @param defaultFailFastCondition callable that indicates terminal failure
 */
static void setDefaultFailFastCondition(String failFastFailureReason, 
                                       Callable<Boolean> defaultFailFastCondition);

Assertion-Based Fail-Fast Conditions

/**
 * Set default fail-fast assertion for all await statements  
 * If assertion throws exception, terminate with TerminalFailureException
 * @param defaultFailFastAssertion runnable that performs failure checks
 */
static void setDefaultFailFastCondition(ThrowingRunnable defaultFailFastAssertion);

/**
 * Set default fail-fast assertion with descriptive reason
 * @param failFastFailureReason description included in exception
 * @param defaultFailFastAssertion runnable that performs failure checks
 */
static void setDefaultFailFastCondition(String failFastFailureReason, 
                                       ThrowingRunnable defaultFailFastAssertion);

Per-Await Fail-Fast Conditions

/**
 * Set fail-fast condition for this await statement
 * @param failFastCondition callable that indicates terminal failure
 * @return ConditionFactory for further configuration
 */
ConditionFactory failFast(Callable<Boolean> failFastCondition);

/**
 * Set fail-fast condition with reason for this await statement
 * @param failFastFailureReason description for failure
 * @param failFastCondition callable that indicates terminal failure
 * @return ConditionFactory for further configuration
 */
ConditionFactory failFast(String failFastFailureReason, 
                         Callable<Boolean> failFastCondition);

/**
 * Set fail-fast assertion for this await statement
 * @param failFastAssertion runnable that performs failure checks
 * @return ConditionFactory for further configuration
 */
ConditionFactory failFast(ThrowingRunnable failFastAssertion);

/**
 * Set fail-fast assertion with reason for this await statement
 * @param failFastFailureReason description for failure
 * @param failFastAssertion runnable that performs failure checks
 * @return ConditionFactory for further configuration
 */
ConditionFactory failFast(String failFastFailureReason, 
                         ThrowingRunnable failFastAssertion);

Fail-Fast Examples:

// Global fail-fast for system shutdown
setDefaultFailFastCondition("System is shutting down", 
    () -> systemStatus.equals("SHUTDOWN"));

// Per-await fail-fast for error conditions
await().failFast("Database connection lost", 
        () -> !databaseConnection.isValid(1))
    .until(() -> dataProcessor.isComplete());

// Assertion-based fail-fast
await().failFast("Critical error occurred", () -> {
        assertThat(errorCount.get()).isLessThan(10);
        assertThat(systemHealth.getStatus()).isNotEqualTo(Status.CRITICAL);
    })
    .until(() -> operationCompletes());

// Complex fail-fast conditions
await().failFast("Service degradation detected", () -> {
        double errorRate = errorCount.get() / (double) requestCount.get();
        return errorRate > 0.1 || // More than 10% error rate
               responseTime.get() > 5000 || // Response time > 5s
               memoryUsage.get() > 0.9; // Memory usage > 90%
    })
    .until(() -> healthCheck.isHealthy());

Thread and Executor Management

Configure custom execution strategies for condition evaluation.

Custom Executor Services

/**
 * Set default executor service for all await statements
 * @param executorService custom executor for condition evaluation
 */
static void pollExecutorService(ExecutorService executorService);

/**
 * Set executor service for this await statement
 * @param executorService custom executor for condition evaluation
 * @return ConditionFactory for further configuration
 */
ConditionFactory pollExecutorService(ExecutorService executorService);

Custom Thread Suppliers

/**
 * Set default thread supplier for all await statements
 * @param threadSupplier function that creates threads for polling
 */
static void pollThread(Function<Runnable, Thread> threadSupplier);

/**
 * Set thread supplier for this await statement
 * @param threadSupplier function that creates threads for polling
 * @return ConditionFactory for further configuration
 */
ConditionFactory pollThread(Function<Runnable, Thread> threadSupplier);

Same-Thread Execution

/**
 * Configure all await statements to poll in same thread as test
 * Use with test framework timeouts for safety
 */
static void pollInSameThread();

/**
 * Configure this await statement to poll in same thread as test
 * @return ConditionFactory for further configuration
 */
ConditionFactory pollInSameThread();

Thread Management Examples:

// Custom executor with specific thread pool size
ExecutorService customExecutor = Executors.newFixedThreadPool(2, r -> {
    Thread t = new Thread(r);
    t.setName("Awaitility-Custom-" + t.getId());
    t.setDaemon(true);
    return t;
});

// Set as default
pollExecutorService(customExecutor);

// Or use for specific await
await().pollExecutorService(customExecutor)
    .until(() -> expensiveOperation.isComplete());

// Custom thread with priority
await().pollThread(runnable -> {
        Thread thread = new Thread(runnable);
        thread.setName("HighPriorityAwait");
        thread.setPriority(Thread.MAX_PRIORITY);
        thread.setDaemon(true);
        return thread;
    })
    .until(() -> criticalOperation.isComplete());

// Same thread execution with JUnit timeout
@Test(timeout = 10000) // 10 second timeout
public void testWithSameThread() {
    await().pollInSameThread()
        .until(() -> quickOperation.isComplete());
}

Logging and Condition Evaluation

Configure detailed logging and monitoring of condition evaluation.

Condition Evaluation Listeners

/**
 * Set default condition evaluation listener for all await statements
 * @param defaultConditionEvaluationListener listener for evaluation events
 */
static void setDefaultConditionEvaluationListener(
    ConditionEvaluationListener defaultConditionEvaluationListener);

/**
 * Set condition evaluation listener for this await statement
 * @param conditionEvaluationListener listener for evaluation events
 * @return ConditionFactory for further configuration
 */
ConditionFactory conditionEvaluationListener(
    ConditionEvaluationListener conditionEvaluationListener);

Built-in Logging

/**
 * Enable default logging to System.out for all await statements
 */
static void setDefaultLogging();

/**
 * Enable custom logging for all await statements
 * @param logPrinter consumer that handles log messages
 */
static void setLogging(Consumer<String> logPrinter);

/**
 * Set custom logging listener for all await statements
 * @param loggingListener listener that handles evaluation logging
 */
static void setLoggingListener(ConditionEvaluationListener loggingListener);

/**
 * Enable default logging for this await statement
 * @return ConditionFactory for further configuration
 */
ConditionFactory logging();

/**
 * Enable custom logging for this await statement
 * @param logPrinter consumer that handles log messages
 * @return ConditionFactory for further configuration
 */
ConditionFactory logging(Consumer<String> logPrinter);

Logging Examples:

// Enable default logging globally
setDefaultLogging();

// Custom logging to file
Logger logger = LoggerFactory.getLogger("AwaitilityTest");
setLogging(message -> logger.debug("Awaitility: {}", message));

// Custom evaluation listener
setDefaultConditionEvaluationListener(new ConditionEvaluationListener<Object>() {
    @Override
    public void conditionEvaluated(EvaluatedCondition<Object> condition) {
        System.out.printf("Evaluation %d: %s = %s%n", 
            condition.getElapsedTimeInMS(),
            condition.getDescription(),
            condition.getValue());
    }
    
    @Override
    public void beforeEvaluation(StartEvaluationEvent<Object> startEvaluationEvent) {
        System.out.println("Starting evaluation of: " + 
            startEvaluationEvent.getDescription());
    }
    
    @Override
    public void onTimeout(TimeoutEvent timeoutEvent) {
        System.err.println("Timeout after: " + timeoutEvent.getElapsedTimeInMS() + "ms");
    }
});

// Per-await custom logging
await().logging(msg -> System.out.println("Custom: " + msg))
    .until(() -> operation.isComplete());

// Structured logging with additional context
await().conditionEvaluationListener(new ConditionEvaluationListener<Boolean>() {
    @Override
    public void conditionEvaluated(EvaluatedCondition<Boolean> condition) {
        Map<String, Object> logData = Map.of(
            "elapsed_ms", condition.getElapsedTimeInMS(),
            "value", condition.getValue(),
            "remaining_time_ms", condition.getRemainingTimeInMS(),
            "description", condition.getDescription()
        );
        logger.info("Condition evaluation: {}", logData);
    }
}).until(() -> complexOperation.isComplete());

Advanced Configuration Patterns

Complex configuration scenarios combining multiple advanced features.

Environment-Specific Configuration

public class AwaitilityConfig {
    
    public static void configureForEnvironment(String environment) {
        reset(); // Start clean
        
        switch (environment.toLowerCase()) {
            case "development":
                configureDevelopment();
                break;
            case "integration":
                configureIntegration();
                break;
            case "production":
                configureProduction();
                break;
            default:
                configureDefault();
        }
    }
    
    private static void configureDevelopment() {
        setDefaultTimeout(30, SECONDS);
        setDefaultPollInterval(100, MILLISECONDS);
        setDefaultLogging(); // Enable logging for debugging
        
        // Fail fast on obvious errors
        setDefaultFailFastCondition("Service crashed", 
            () -> serviceStatus.equals("CRASHED"));
    }
    
    private static void configureIntegration() {
        setDefaultTimeout(5, MINUTES);
        setDefaultPollInterval(500, MILLISECONDS);
        setDefaultPollDelay(1, SECONDS);
        
        // Custom executor for integration tests
        ExecutorService integrationExecutor = 
            Executors.newFixedThreadPool(4);
        pollExecutorService(integrationExecutor);
        
        // Comprehensive fail-fast conditions
        setDefaultFailFastCondition("Integration environment failure", () -> {
            return !databaseHealthy() || 
                   !messageQueueHealthy() || 
                   !externalServiceHealthy();
        });
    }
    
    private static void configureProduction() {
        setDefaultTimeout(10, MINUTES);
        setDefaultPollInterval(2, SECONDS);
        setDefaultPollDelay(5, SECONDS);
        
        // Minimal logging in production
        setLogging(msg -> productionLogger.debug("Awaitility: {}", msg));
        
        // Conservative fail-fast  
        setDefaultFailFastCondition("Critical system failure",
            () -> systemHealth.getOverallStatus() == HealthStatus.CRITICAL);
    }
}

Test Suite Configuration

public class BaseIntegrationTest {
    
    @BeforeEach
    public void setupAwaitility() {
        // Reset before each test
        reset();
        
        // Configure for integration testing
        setDefaultTimeout(Duration.ofMinutes(2));
        setDefaultPollInterval(Duration.ofMillis(200));
        
        // Enable detailed logging for failed tests
        setDefaultConditionEvaluationListener(new ConditionEvaluationListener<Object>() {
            @Override
            public void onTimeout(TimeoutEvent timeoutEvent) {
                logger.error("Awaitility timeout in {}: {} after {}ms", 
                    getCurrentTestMethod(),
                    timeoutEvent.getDescription(),
                    timeoutEvent.getElapsedTimeInMS());
            }
        });
        
        // Global fail-fast for test environment issues
        setDefaultFailFastCondition("Test environment unstable", () -> {
            return testDatabase.getConnectionPool().getActiveCount() == 0 ||
                   testMessageBroker.getStatus() != BrokerStatus.RUNNING;
        });
    }
    
    @AfterEach 
    public void cleanupAwaitility() {
        reset();
    }
    
    // Utility methods for common patterns
    protected ConditionFactory awaitSlowOperation() {
        return await().atMost(Duration.ofMinutes(5))
            .pollInterval(Duration.ofSeconds(2))
            .logging(msg -> logger.trace("SlowOp: {}", msg));
    }
    
    protected ConditionFactory awaitQuickOperation() {
        return await().atMost(Duration.ofSeconds(10))
            .pollInterval(Duration.ofMillis(50))
            .pollDelay(Duration.ofMillis(10));
    }
}

Performance Monitoring Integration

public class PerformanceAwareAwaitility {
    
    private static final MeterRegistry meterRegistry = Metrics.globalRegistry;
    private static final Timer awaitTimer = Timer.builder("awaitility.duration")
        .description("Time spent waiting in Awaitility")
        .register(meterRegistry);
    
    public static void configureWithMetrics() {
        setDefaultConditionEvaluationListener(new ConditionEvaluationListener<Object>() {
            private final Map<String, Timer.Sample> samples = new ConcurrentHashMap<>();
            
            @Override
            public void beforeEvaluation(StartEvaluationEvent<Object> event) {
                Timer.Sample sample = Timer.start(meterRegistry);
                samples.put(event.getDescription(), sample);
            }
            
            @Override
            public void conditionEvaluated(EvaluatedCondition<Object> condition) {
                // Record individual evaluation metrics
                meterRegistry.counter("awaitility.evaluations.total",
                    "condition", condition.getDescription(),
                    "result", String.valueOf(condition.isSatisfied()))
                    .increment();
            }
            
            @Override
            public void onTimeout(TimeoutEvent timeoutEvent) {
                Timer.Sample sample = samples.remove(timeoutEvent.getDescription());
                if (sample != null) {
                    sample.stop(awaitTimer.tag("result", "timeout"));
                }
                
                meterRegistry.counter("awaitility.timeouts.total",
                    "condition", timeoutEvent.getDescription())
                    .increment();
            }
        });
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-awaitility--awaitility

docs

advanced-config.md

atomic-variables.md

condition-evaluation.md

core-await.md

exception-handling.md

field-reflection.md

index.md

timeout-polling.md

tile.json