CtrlK
BlogDocsLog inGet started
Tessl Logo

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

Core deployment-time APIs and infrastructure for building Quarkus applications with native image support and development-time features

Pending
Overview
Eval results
Files

dev-mode.mddocs/

Development Mode

Quarkus development mode provides hot reloading, live coding, development services, and enhanced debugging capabilities to create a seamless developer experience. The development mode infrastructure handles file watching, incremental compilation, and runtime updates without requiring application restarts.

Core Imports

// Development mode context and processing  
import io.quarkus.deployment.dev.DevModeContext;
import io.quarkus.deployment.dev.RuntimeUpdatesProcessor;
import io.quarkus.deployment.dev.CompilationProvider;
import io.quarkus.deployment.dev.DevModeListener;
import io.quarkus.deployment.dev.ClassScanResult;

// File system watching and hot deployment
import io.quarkus.deployment.dev.filesystem.StaticFileSystemWatcher;
import io.quarkus.deployment.dev.filesystem.ReloadableFileSystemWatcher;
import io.quarkus.deployment.dev.HotDeploymentWatchedFileBuildStep;

// Development services
import io.quarkus.deployment.dev.devservices.DevServicesBuildItem;
import io.quarkus.deployment.dev.devservices.DevServicesConfig;
import io.quarkus.deployment.dev.devservices.DevServicesResultBuildItem;

// Remote development mode
import io.quarkus.deployment.dev.remote.RemoteDevClient;
import io.quarkus.deployment.dev.remote.RemoteDevConfig;

// Testing integration
import io.quarkus.deployment.dev.testing.TestSupport;
import io.quarkus.deployment.dev.testing.TestConfig;
import io.quarkus.deployment.dev.testing.TestRunResults;

// Console and IDE integration
import io.quarkus.deployment.console.ConsoleCommand;
import io.quarkus.deployment.console.ConsoleStateManager;
import io.quarkus.deployment.ide.EffectiveIdeBuildItem;
import io.quarkus.deployment.ide.IdeConfig;

Runtime Updates Processing

RuntimeUpdatesProcessor

Central processor for handling runtime updates and hot reloading.

class RuntimeUpdatesProcessor {
    /**
     * Singleton instance for runtime updates processing
     */
    static RuntimeUpdatesProcessor INSTANCE;
    
    /**
     * Scans for changes and triggers updates if necessary
     */
    boolean doScan(boolean userInitiated, boolean forceRestart);
    
    /**
     * Adds a hot replacement setup handler
     */
    void addHotReplacementSetup(HotReplacementSetup service);
    
    /**
     * Checks for changed classes since last scan
     */
    ClassScanResult checkForChangedClasses();
    
    /**
     * Gets the current application context
     */
    DevModeContext getContext();
    
    /**
     * Restarts the application completely
     */
    void restart(boolean forceRestart);
    
    /**
     * Pauses file watching
     */
    void pause();
    
    /**
     * Resumes file watching
     */
    void resume();
    
    /**
     * Checks if currently in dev mode
     */
    static boolean isDevMode();
}

DevModeContext

Context object containing development mode configuration and module information.

class DevModeContext {
    /**
     * Gets all modules in the development context
     */
    List<ModuleInfo> getAllModules();
    
    /**
     * Gets the main application module
     */
    ModuleInfo getApplicationRoot();
    
    /**
     * Gets command line arguments
     */
    String[] getArgs();
    
    /**
     * Gets the launch mode
     */
    LaunchMode getLaunchMode();
    
    /**
     * Gets the project directory
     */
    Path getProjectDir();
    
    /**
     * Checks if this is a test
     */
    boolean isTest();
    
    /**
     * Checks if local project dependencies should be disabled
     */
    boolean isLocalProjectDiscovery();
    
    /**
     * Information about a module in the development context
     */
    static class ModuleInfo {
        String getArtifactKey();
        String getName();
        Path getProjectDirectory();
        Path getSourceDirectory();
        Path getClassesDirectory();
        Path getResourceDirectory();
        Set<String> getSourcePaths();
        CompileClasspathManager getCompileClasspathManager();
    }
}

Usage Examples:

@BuildStep(onlyIf = IsDevelopment.class)
void setupHotReload(DevModeContext context,
                   BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles) {
    
    // Watch configuration files for changes
    context.getAllModules().forEach(module -> {
        Path resourceDir = module.getResourceDirectory();
        if (Files.exists(resourceDir.resolve("application.properties"))) {
            watchedFiles.produce(new HotDeploymentWatchedFileBuildItem(
                resourceDir.resolve("application.properties").toString(), 
                true
            ));
        }
    });
}

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
void initializeDevMode(DevModeRecorder recorder,
                      LaunchModeBuildItem launchMode,
                      DevModeContext context) {
    if (launchMode.getLaunchMode() == LaunchMode.DEVELOPMENT) {
        recorder.setupDevMode(context.getArgs(), context.getProjectDir());
    }
}

File System Watching and Hot Deployment

File System Watchers

class StaticFileSystemWatcher {
    /**
     * Watches static resources for changes
     */
    StaticFileSystemWatcher(Path watchedPath, 
                           Set<String> includedExtensions,
                           Consumer<Set<String>> changeCallback);
    
    /**
     * Starts watching for file changes
     */
    void start();
    
    /**
     * Stops file watching
     */
    void stop();
}

class ReloadableFileSystemWatcher {
    /**
     * Watches source files for changes requiring compilation
     */
    void watchPath(Path path, String... extensions);
    
    /**
     * Gets changed files since last check
     */
    Set<Path> getChangedPaths();
    
    /**
     * Resets the changed files tracking
     */
    void reset();
}

Hot Deployment Build Items

class HotDeploymentWatchedFileBuildItem extends MultiBuildItem {
    /**
     * Creates a watched file item
     */
    HotDeploymentWatchedFileBuildItem(String location);
    
    /**
     * Creates a watched file item with restart behavior
     */
    HotDeploymentWatchedFileBuildItem(String location, boolean restartNeeded);
    
    String getLocation();
    boolean isRestartNeeded();
}

class ClassScanResult {
    /**
     * Classes that have been added
     */
    Set<String> getAddedClasses();
    
    /**
     * Classes that have been modified
     */
    Set<String> getChangedClasses();
    
    /**
     * Classes that have been deleted
     */
    Set<String> getDeletedClasses();
    
    /**
     * Whether changes require a restart
     */
    boolean isRestartNeeded();
}

Usage Examples:

@BuildStep(onlyIf = IsDevelopment.class)
void setupFileWatching(ApplicationArchivesBuildItem archives,
                      BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles) {
    
    // Watch templates for changes
    watchedFiles.produce(new HotDeploymentWatchedFileBuildItem("templates/", false));
    
    // Watch configuration that requires restart
    watchedFiles.produce(new HotDeploymentWatchedFileBuildItem("application.yaml", true));
    
    // Watch web resources
    watchedFiles.produce(new HotDeploymentWatchedFileBuildItem("META-INF/resources/", false));
}

public class HotReloadSetup implements HotReplacementSetup {
    @Override
    public void setupHotDeployment(HotReplacementContext context) {
        context.consumeNoRestartChanges(changedResources -> {
            // Handle resource changes that don't require restart
            for (String resource : changedResources) {
                if (resource.endsWith(".html") || resource.endsWith(".css")) {
                    // Refresh web resources
                    refreshWebResource(resource);
                }
            }
        });
    }
}

Compilation Providers

CompilationProvider Interface

Service provider interface for handling compilation of different file types in development mode.

interface CompilationProvider {
    /**
     * File extensions this provider can handle
     */
    Set<String> handledExtensions();
    
    /**
     * Compiles the specified files
     */
    void compile(Set<File> filesToCompile, Context context);
    
    /**
     * Compilation context providing build information
     */
    interface Context {
        /**
         * Source directory for compilation
         */
        Path getSourceDirectory();
        
        /**
         * Output directory for compiled classes
         */
        Path getOutputDirectory();
        
        /**
         * Classpath for compilation
         */
        ClassLoader getClasspathClassLoader();
        
        /**
         * Gets the project directory
         */
        Path getProjectDirectory();
        
        /**
         * Gets compiler arguments
         */
        List<String> getCompilerOptions();
    }
}

Implementation Example:

public class KotlinCompilationProvider implements CompilationProvider {
    
    @Override
    public Set<String> handledExtensions() {
        return Set.of(".kt", ".kts");
    }
    
    @Override
    public void compile(Set<File> filesToCompile, Context context) {
        if (filesToCompile.isEmpty()) {
            return;
        }
        
        List<String> args = new ArrayList<>();
        args.add("-cp");
        args.add(buildClasspath(context));
        args.add("-d");
        args.add(context.getOutputDirectory().toString());
        
        // Add Kotlin-specific options
        args.addAll(context.getCompilerOptions());
        
        // Add source files
        filesToCompile.forEach(file -> args.add(file.getAbsolutePath()));
        
        // Execute Kotlin compiler
        KotlinCompiler.exec(args.toArray(new String[0]));
    }
}

@BuildStep
void registerKotlinCompiler(BuildProducer<CompilationProviderBuildItem> providers) {
    providers.produce(new CompilationProviderBuildItem(KotlinCompilationProvider.class));
}

Development Services

DevServices Infrastructure

Development services automatically start external services like databases, message brokers, etc., during development.

class DevServicesConfig {
    /**
     * Whether dev services are enabled globally
     */
    @WithDefault("true")
    boolean enabled;
    
    /**
     * Timeout for starting services
     */
    @WithDefault("60s")
    Duration timeout;
    
    /**
     * Whether to share services between applications
     */
    @WithDefault("true") 
    boolean shared;
}

class DevServicesBuildItem extends MultiBuildItem {
    /**
     * Creates a dev service build item
     */
    DevServicesBuildItem(String name, 
                        String containerImage,
                        Map<String, String> containerProperties,
                        Map<String, Object> configProperties);
    
    String getName();
    String getContainerImage();
    Map<String, String> getContainerProperties();
    Map<String, Object> getConfigProperties();
}

class DevServicesResultBuildItem extends SimpleBuildItem {
    Map<String, String> getConfig();
    Closeable getCloseable();
}

Usage Examples:

@BuildStep(onlyIf = { IsDevelopment.class, DevServicesEnabled.class })
DevServicesBuildItem startDatabase(LaunchModeBuildItem launchMode,
                                  DatabaseConfig config) {
    
    if (config.devservices.enabled && config.url.isEmpty()) {
        Map<String, String> containerProps = Map.of(
            "POSTGRES_DB", "devdb",
            "POSTGRES_USER", "dev",
            "POSTGRES_PASSWORD", "dev"
        );
        
        Map<String, Object> configProps = Map.of(
            "quarkus.datasource.jdbc.url", "jdbc:postgresql://localhost:5432/devdb",
            "quarkus.datasource.username", "dev",
            "quarkus.datasource.password", "dev"
        );
        
        return new DevServicesBuildItem(
            "postgresql",
            "postgres:13",
            containerProps,
            configProps
        );
    }
    return null;
}

@BuildStep
DevServicesResultBuildItem configureDevServices(List<DevServicesBuildItem> devServices,
                                               LaunchModeBuildItem launchMode) {
    Map<String, String> combinedConfig = new HashMap<>();
    List<Closeable> closeables = new ArrayList<>();
    
    for (DevServicesBuildItem devService : devServices) {
        // Start container and collect configuration
        ContainerInfo container = startContainer(devService);
        combinedConfig.putAll(container.getConfig());
        closeables.add(container::stop);
    }
    
    return new DevServicesResultBuildItem(combinedConfig, () -> {
        for (Closeable closeable : closeables) {
            closeable.close();
        }
    });
}

Console and Command Integration

Console Commands

interface ConsoleCommand {
    /**
     * Command name for console input
     */
    String getCommand();
    
    /**
     * Description of the command
     */
    String getDescription();
    
    /**
     * Executes the command
     */
    void execute(String[] args, ConsoleContext context);
    
    /**
     * Whether command is available in current mode
     */
    default boolean isAvailable() { return true; }
}

class ConsoleStateManager {
    /**
     * Registers a console command
     */
    void addCommand(ConsoleCommand command);
    
    /**
     * Processes console input
     */
    void handleInput(String input);
    
    /**
     * Sets up console reading thread
     */
    void setupConsole();
}

Implementation Example:

public class TestCommand implements ConsoleCommand {
    
    @Override
    public String getCommand() {
        return "t";
    }
    
    @Override
    public String getDescription() {
        return "Run tests";
    }
    
    @Override
    public void execute(String[] args, ConsoleContext context) {
        TestSupport.runTests();
    }
    
    @Override
    public boolean isAvailable() {
        return LaunchMode.current() == LaunchMode.DEVELOPMENT;
    }
}

@BuildStep(onlyIf = IsDevelopment.class)
void registerConsoleCommands(BuildProducer<ConsoleCommandBuildItem> commands) {
    commands.produce(new ConsoleCommandBuildItem(new TestCommand()));
    commands.produce(new ConsoleCommandBuildItem(new RestartCommand()));
    commands.produce(new ConsoleCommandBuildItem(new HelpCommand()));
}

Remote Development Mode

Remote Development Client

class RemoteDevClient {
    /**
     * Connects to remote development server
     */
    static RemoteDevClient connect(RemoteDevConfig config);
    
    /**
     * Sends local changes to remote server
     */
    void sendChanges(Set<Path> changedFiles);
    
    /**
     * Receives updates from remote server
     */
    void receiveUpdates();
    
    /**
     * Disconnects from remote server
     */
    void disconnect();
}

class RemoteDevConfig {
    /**
     * Remote server URL
     */
    String url;
    
    /**
     * Authentication token
     */
    Optional<String> password;
    
    /**
     * Connection timeout
     */
    @WithDefault("30s")
    Duration connectTimeout;
}

Usage Example:

@BuildStep(onlyIf = { IsDevelopment.class, RemoteDevEnabled.class })
@Record(ExecutionTime.RUNTIME_INIT)
void setupRemoteDev(RemoteDevRecorder recorder,
                   RemoteDevConfig config,
                   DevModeContext context) {
    
    recorder.setupRemoteDevClient(
        config.url, 
        config.password.orElse(null),
        context.getProjectDir()
    );
}

Testing Integration

Development Mode Testing

class TestSupport {
    /**
     * Runs all tests in development mode
     */
    static TestRunResults runTests();
    
    /**
     * Runs specific test classes
     */
    static TestRunResults runTests(Set<String> testClasses);
    
    /**
     * Checks if tests are currently running
     */
    static boolean isRunning();
    
    /**
     * Gets the last test results
     */
    static Optional<TestRunResults> getLastResults();
}

class TestRunResults {
    long getTestsRun();
    long getTestsSkipped();
    long getTestsFailed();
    Duration getDuration();
    List<TestFailure> getFailures();
}

class TestConfig {
    /**
     * Whether to run tests automatically on changes
     */
    @WithDefault("false")
    boolean continuous;
    
    /**
     * Test framework to use
     */
    @WithDefault("junit5")
    TestFramework framework;
    
    /**
     * Include patterns for test discovery
     */
    List<String> includePattern;
    
    /**
     * Exclude patterns for test discovery
     */
    List<String> excludePattern;
}

Usage Example:

@BuildStep(onlyIf = IsDevelopment.class)
@Record(ExecutionTime.RUNTIME_INIT)
void setupTestSupport(TestRecorder recorder,
                     TestConfig config,
                     ApplicationIndexBuildItem index) {
    
    List<String> testClasses = index.getIndex()
        .getAllKnownImplementors(DotName.createSimple("org.junit.jupiter.api.Test"))
        .stream()
        .map(classInfo -> classInfo.name().toString())
        .collect(Collectors.toList());
    
    recorder.setupTestSupport(testClasses, config.continuous);
}

IDE Integration

IDE Configuration and Support

class IdeConfig {
    /**
     * Target IDE for integration
     */
    Optional<IdeType> target;
    
    /**
     * Whether to open URLs in IDE
     */
    @WithDefault("true")
    boolean openUrls;
    
    enum IdeType {
        IDEA, ECLIPSE, VSCODE, NETBEANS
    }
}

class EffectiveIdeBuildItem extends SimpleBuildItem {
    Optional<IdeType> getIdeType();
    boolean isIdePresent();
    
    /**
     * Opens a file in the IDE at specific line
     */
    void openFile(Path file, int line);
    
    /**
     * Opens a URL in the IDE
     */
    void openUrl(String url);
}

Usage Example:

@BuildStep
EffectiveIdeBuildItem detectIde(IdeConfig config) {
    // Detect IDE based on environment variables, system properties, etc.
    Optional<IdeType> detectedIde = detectCurrentIde();
    
    IdeType effectiveIde = config.target.orElse(detectedIde.orElse(null));
    
    return new EffectiveIdeBuildItem(Optional.ofNullable(effectiveIde));
}

@BuildStep(onlyIf = IsDevelopment.class)
void setupIdeIntegration(EffectiveIdeBuildItem ide,
                        BuildProducer<ConsoleCommandBuildItem> commands) {
    
    if (ide.isIdePresent()) {
        commands.produce(new ConsoleCommandBuildItem(new OpenInIdeCommand(ide)));
    }
}

Install with Tessl CLI

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

docs

build-system.md

configuration.md

dev-mode.md

index.md

packaging.md

utilities.md

tile.json