CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-quarkus--quarkus-core

Quarkus core components - runtime library for the Cloud Native, Container First Java framework

Pending
Overview
Eval results
Files

runtime-context.mddocs/

Runtime Context and Threading

The Runtime Context and Threading capability provides execution mode detection, launch mode management, and threading control for optimal performance in Quarkus applications.

Launch Mode Management

Launch Mode Detection

public enum LaunchMode {
    /**
     * Production mode - optimized for performance.
     */
    NORMAL,
    
    /**
     * Development mode - hot reload and dev services enabled.
     */
    DEVELOPMENT,
    
    /**
     * Test mode - running in test environment.
     */
    TEST;
    
    /**
     * Check if current mode is development or test.
     * @return true if development or test mode
     */
    public boolean isDevOrTest();
    
    /**
     * Get the default configuration profile for this launch mode.
     * @return Profile name ("prod", "dev", or "test")
     */
    public String getDefaultProfile();
    
    /**
     * Get the current launch mode.
     * @return Current launch mode
     */
    public static LaunchMode current();
    
    /**
     * Check if running in development mode.
     * @return true if development mode
     */
    public static boolean isDev();
    
    /**
     * Check if running in remote development mode.
     * @return true if remote development mode
     */
    public static boolean isRemoteDev();
}

Execution Mode Detection

Execution Phases

public enum ExecutionMode {
    /**
     * Static initialization phase - executed at build time.
     */
    STATIC_INIT,
    
    /**
     * Runtime initialization phase - executed at startup.
     */
    RUNTIME_INIT,
    
    /**
     * Application running phase - normal operation.
     */
    RUNNING,
    
    /**
     * Uninitialized state.
     */
    UNSET;
    
    /**
     * Get the current execution mode.
     * @return Current execution mode
     */
    public static ExecutionMode current();
}

Threading Control

Blocking Operation Control

public final class BlockingOperationControl {
    /**
     * Check if blocking operations are allowed on current thread.
     * @return true if blocking operations are allowed
     */
    public static boolean isBlockingAllowed();
    
    /**
     * Configure IO thread detectors.
     * @param detectors Array of IO thread detectors
     */
    public static void setIoThreadDetector(IOThreadDetector... detectors);
}

IO Thread Detection

public interface IOThreadDetector {
    /**
     * Check if the current thread is an IO thread.
     * IO threads should not perform blocking operations.
     * @return true if current thread is an IO thread
     */
    boolean isInIOThread();
}

Blocking Operation Exception

public class BlockingOperationNotAllowedException extends IllegalStateException {
    /**
     * Create exception for blocking operation attempt on IO thread.
     * @param message Error message
     */
    public BlockingOperationNotAllowedException(String message);
    
    /**
     * Create exception with message and cause.
     * @param message Error message
     * @param cause Root cause
     */
    public BlockingOperationNotAllowedException(String message, Throwable cause);
}

Usage Examples

Launch Mode Detection

import io.quarkus.runtime.LaunchMode;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class EnvironmentService {
    
    public void configureEnvironment() {
        LaunchMode mode = LaunchMode.current();
        
        switch (mode) {
            case DEVELOPMENT:
                configureDevelopmentMode();
                break;
            case TEST:
                configureTestMode();
                break;
            case NORMAL:
                configureProductionMode();
                break;
        }
        
        // Check if dev or test
        if (mode.isDevOrTest()) {
            enableDebugLogging();
        }
        
        // Get associated profile
        String profile = mode.getDefaultProfile();
        System.out.println("Running with profile: " + profile);
    }
    
    private void configureDevelopmentMode() {
        System.out.println("Development mode: Hot reload enabled");
        // Enable dev services, hot reload, etc.
    }
    
    private void configureTestMode() {
        System.out.println("Test mode: Test containers starting");
        // Configure test environment
    }
    
    private void configureProductionMode() {
        System.out.println("Production mode: Performance optimizations enabled");
        // Configure for production
    }
    
    private void enableDebugLogging() {
        System.out.println("Debug logging enabled for dev/test mode");
    }
}

Execution Mode Tracking

import io.quarkus.runtime.ExecutionMode;
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.runtime.annotations.StaticInit;
import io.quarkus.runtime.annotations.RuntimeInit;

@Recorder
public class InitializationRecorder {
    
    @StaticInit
    public void staticInitialization() {
        ExecutionMode mode = ExecutionMode.current();
        System.out.println("Current execution mode: " + mode);
        
        if (mode == ExecutionMode.STATIC_INIT) {
            System.out.println("Performing static initialization");
            // Build-time initialization logic
            initializeStaticResources();
        }
    }
    
    @RuntimeInit
    public void runtimeInitialization() {
        ExecutionMode mode = ExecutionMode.current();
        
        if (mode == ExecutionMode.RUNTIME_INIT) {
            System.out.println("Performing runtime initialization");
            // Runtime initialization logic
            initializeRuntimeResources();
        }
    }
    
    public void applicationRunning() {
        ExecutionMode mode = ExecutionMode.current();
        
        if (mode == ExecutionMode.RUNNING) {
            System.out.println("Application is now running");
            // Normal operation logic
        }
    }
    
    private void initializeStaticResources() {
        // Static initialization logic
    }
    
    private void initializeRuntimeResources() {
        // Runtime initialization logic
    }
}

IO Thread Detection and Blocking Control

import io.quarkus.runtime.BlockingOperationControl;
import io.quarkus.runtime.IOThreadDetector;
import io.quarkus.runtime.BlockingOperationNotAllowedException;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class ThreadingService {
    
    public void performPotentiallyBlockingOperation() {
        // Check if blocking operations are allowed
        if (!BlockingOperationControl.isBlockingAllowed()) {
            throw new BlockingOperationNotAllowedException(
                "Blocking operation attempted on IO thread"
            );
        }
        
        // Safe to perform blocking operation
        performBlockingIO();
    }
    
    public void safeBlockingOperation() {
        try {
            // This will automatically check and throw if on IO thread
            performBlockingIO();
        } catch (BlockingOperationNotAllowedException e) {
            // Handle the case where we're on an IO thread
            System.err.println("Cannot perform blocking operation: " + e.getMessage());
            
            // Alternative: schedule on blocking thread pool
            scheduleOnBlockingThread(this::performBlockingIO);
        }
    }
    
    private void performBlockingIO() {
        try {
            // Simulated blocking operation
            Thread.sleep(1000);
            System.out.println("Blocking operation completed");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    private void scheduleOnBlockingThread(Runnable task) {
        // Schedule task on blocking thread pool
        // Implementation depends on your threading model
        CompletableFuture.runAsync(task);
    }
}

Custom IO Thread Detector

import io.quarkus.runtime.IOThreadDetector;
import io.quarkus.runtime.BlockingOperationControl;

public class CustomIOThreadDetector implements IOThreadDetector {
    
    @Override
    public boolean isInIOThread() {
        Thread currentThread = Thread.currentThread();
        String threadName = currentThread.getName();
        
        // Detect Vert.x event loop threads
        if (threadName.contains("vert.x-eventloop")) {
            return true;
        }
        
        // Detect Netty IO threads
        if (threadName.contains("netty-io")) {
            return true;
        }
        
        // Add other IO thread detection logic
        return false;
    }
}

// Register the custom detector
public class ThreadDetectionSetup {
    
    public void setupDetectors() {
        IOThreadDetector customDetector = new CustomIOThreadDetector();
        BlockingOperationControl.setIoThreadDetector(customDetector);
    }
}

Conditional Logic Based on Context

import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.ExecutionMode;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.annotation.PostConstruct;

@ApplicationScoped
public class ContextAwareService {
    
    @PostConstruct
    public void initialize() {
        LaunchMode launchMode = LaunchMode.current();
        ExecutionMode executionMode = ExecutionMode.current();
        
        System.out.println("Launch Mode: " + launchMode);
        System.out.println("Execution Mode: " + executionMode);
        
        // Configure based on context
        configureForContext(launchMode, executionMode);
    }
    
    private void configureForContext(LaunchMode launchMode, ExecutionMode executionMode) {
        // Development-specific configuration
        if (launchMode == LaunchMode.DEVELOPMENT) {
            if (executionMode == ExecutionMode.RUNTIME_INIT) {
                setupDevelopmentTools();
            }
            enableHotReload();
        }
        
        // Test-specific configuration
        if (launchMode == LaunchMode.TEST) {
            setupTestEnvironment();
        }
        
        // Production optimizations
        if (launchMode == LaunchMode.NORMAL) {
            enableProductionOptimizations();
        }
        
        // Runtime vs static initialization
        switch (executionMode) {
            case STATIC_INIT:
                performStaticSetup();
                break;
            case RUNTIME_INIT:
                performRuntimeSetup();
                break;
            case RUNNING:
                startNormalOperation();
                break;
            case UNSET:
                System.out.println("Execution mode not yet determined");
                break;
        }
    }
    
    private void setupDevelopmentTools() {
        System.out.println("Setting up development tools");
    }
    
    private void enableHotReload() {
        System.out.println("Hot reload enabled");
    }
    
    private void setupTestEnvironment() {
        System.out.println("Setting up test environment");
    }
    
    private void enableProductionOptimizations() {
        System.out.println("Production optimizations enabled");
    }
    
    private void performStaticSetup() {
        System.out.println("Performing static setup");
    }
    
    private void performRuntimeSetup() {
        System.out.println("Performing runtime setup");
    }
    
    private void startNormalOperation() {
        System.out.println("Starting normal operation");
    }
}

Thread-Safe Operations

import io.quarkus.runtime.BlockingOperationControl;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

public class ThreadSafeOperations {
    
    private final Executor blockingExecutor;
    
    public ThreadSafeOperations(Executor blockingExecutor) {
        this.blockingExecutor = blockingExecutor;
    }
    
    public CompletableFuture<String> performAsyncOperation() {
        if (BlockingOperationControl.isBlockingAllowed()) {
            // We're on a blocking thread, safe to do blocking operations
            return CompletableFuture.completedFuture(performSynchronousOperation());
        } else {
            // We're on an IO thread, delegate to blocking executor
            return CompletableFuture.supplyAsync(
                this::performSynchronousOperation, 
                blockingExecutor
            );
        }
    }
    
    private String performSynchronousOperation() {
        // This method performs blocking operations
        try {
            Thread.sleep(100); // Simulated blocking operation
            return "Operation completed";
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return "Operation interrupted";
        }
    }
    
    public void smartBlocking() {
        if (BlockingOperationControl.isBlockingAllowed()) {
            // Direct execution on current thread
            System.out.println("Executing on blocking thread");
            performSynchronousOperation();
        } else {
            // Schedule on blocking thread and wait
            System.out.println("Scheduling on blocking thread from IO thread");
            CompletableFuture<String> future = CompletableFuture.supplyAsync(
                this::performSynchronousOperation,
                blockingExecutor
            );
            
            // Note: This join() could still block the IO thread
            // In practice, you'd want to return the CompletableFuture
            // or use reactive patterns
            String result = future.join();
            System.out.println("Result: " + result);
        }
    }
}

Best Practices

Thread Safety

  1. Always check BlockingOperationControl.isBlockingAllowed() before blocking operations
  2. Use CompletableFuture or reactive patterns when on IO threads
  3. Configure custom IO thread detectors for specific threading models
  4. Handle BlockingOperationNotAllowedException gracefully

Context Awareness

  1. Use LaunchMode to conditionally enable development features
  2. Use ExecutionMode to determine initialization phase
  3. Configure differently for dev/test vs production environments
  4. Leverage profiles associated with launch modes

Performance Optimization

  1. Avoid blocking operations on IO threads
  2. Use appropriate thread pools for different operation types
  3. Configure thread detectors to match your application's threading model
  4. Monitor thread usage in production environments

Install with Tessl CLI

npx tessl i tessl/maven-io-quarkus--quarkus-core

docs

application-lifecycle.md

build-time.md

configuration.md

index.md

logging.md

native-image.md

runtime-context.md

tile.json