0
# Development Mode
1
2
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.
3
4
## Core Imports
5
6
```java
7
// Development mode context and processing
8
import io.quarkus.deployment.dev.DevModeContext;
9
import io.quarkus.deployment.dev.RuntimeUpdatesProcessor;
10
import io.quarkus.deployment.dev.CompilationProvider;
11
import io.quarkus.deployment.dev.DevModeListener;
12
import io.quarkus.deployment.dev.ClassScanResult;
13
14
// File system watching and hot deployment
15
import io.quarkus.deployment.dev.filesystem.StaticFileSystemWatcher;
16
import io.quarkus.deployment.dev.filesystem.ReloadableFileSystemWatcher;
17
import io.quarkus.deployment.dev.HotDeploymentWatchedFileBuildStep;
18
19
// Development services
20
import io.quarkus.deployment.dev.devservices.DevServicesBuildItem;
21
import io.quarkus.deployment.dev.devservices.DevServicesConfig;
22
import io.quarkus.deployment.dev.devservices.DevServicesResultBuildItem;
23
24
// Remote development mode
25
import io.quarkus.deployment.dev.remote.RemoteDevClient;
26
import io.quarkus.deployment.dev.remote.RemoteDevConfig;
27
28
// Testing integration
29
import io.quarkus.deployment.dev.testing.TestSupport;
30
import io.quarkus.deployment.dev.testing.TestConfig;
31
import io.quarkus.deployment.dev.testing.TestRunResults;
32
33
// Console and IDE integration
34
import io.quarkus.deployment.console.ConsoleCommand;
35
import io.quarkus.deployment.console.ConsoleStateManager;
36
import io.quarkus.deployment.ide.EffectiveIdeBuildItem;
37
import io.quarkus.deployment.ide.IdeConfig;
38
```
39
40
## Runtime Updates Processing
41
42
### RuntimeUpdatesProcessor
43
44
Central processor for handling runtime updates and hot reloading.
45
46
```java { .api }
47
class RuntimeUpdatesProcessor {
48
/**
49
* Singleton instance for runtime updates processing
50
*/
51
static RuntimeUpdatesProcessor INSTANCE;
52
53
/**
54
* Scans for changes and triggers updates if necessary
55
*/
56
boolean doScan(boolean userInitiated, boolean forceRestart);
57
58
/**
59
* Adds a hot replacement setup handler
60
*/
61
void addHotReplacementSetup(HotReplacementSetup service);
62
63
/**
64
* Checks for changed classes since last scan
65
*/
66
ClassScanResult checkForChangedClasses();
67
68
/**
69
* Gets the current application context
70
*/
71
DevModeContext getContext();
72
73
/**
74
* Restarts the application completely
75
*/
76
void restart(boolean forceRestart);
77
78
/**
79
* Pauses file watching
80
*/
81
void pause();
82
83
/**
84
* Resumes file watching
85
*/
86
void resume();
87
88
/**
89
* Checks if currently in dev mode
90
*/
91
static boolean isDevMode();
92
}
93
```
94
95
### DevModeContext
96
97
Context object containing development mode configuration and module information.
98
99
```java { .api }
100
class DevModeContext {
101
/**
102
* Gets all modules in the development context
103
*/
104
List<ModuleInfo> getAllModules();
105
106
/**
107
* Gets the main application module
108
*/
109
ModuleInfo getApplicationRoot();
110
111
/**
112
* Gets command line arguments
113
*/
114
String[] getArgs();
115
116
/**
117
* Gets the launch mode
118
*/
119
LaunchMode getLaunchMode();
120
121
/**
122
* Gets the project directory
123
*/
124
Path getProjectDir();
125
126
/**
127
* Checks if this is a test
128
*/
129
boolean isTest();
130
131
/**
132
* Checks if local project dependencies should be disabled
133
*/
134
boolean isLocalProjectDiscovery();
135
136
/**
137
* Information about a module in the development context
138
*/
139
static class ModuleInfo {
140
String getArtifactKey();
141
String getName();
142
Path getProjectDirectory();
143
Path getSourceDirectory();
144
Path getClassesDirectory();
145
Path getResourceDirectory();
146
Set<String> getSourcePaths();
147
CompileClasspathManager getCompileClasspathManager();
148
}
149
}
150
```
151
152
**Usage Examples:**
153
154
```java
155
@BuildStep(onlyIf = IsDevelopment.class)
156
void setupHotReload(DevModeContext context,
157
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles) {
158
159
// Watch configuration files for changes
160
context.getAllModules().forEach(module -> {
161
Path resourceDir = module.getResourceDirectory();
162
if (Files.exists(resourceDir.resolve("application.properties"))) {
163
watchedFiles.produce(new HotDeploymentWatchedFileBuildItem(
164
resourceDir.resolve("application.properties").toString(),
165
true
166
));
167
}
168
});
169
}
170
171
@BuildStep
172
@Record(ExecutionTime.RUNTIME_INIT)
173
void initializeDevMode(DevModeRecorder recorder,
174
LaunchModeBuildItem launchMode,
175
DevModeContext context) {
176
if (launchMode.getLaunchMode() == LaunchMode.DEVELOPMENT) {
177
recorder.setupDevMode(context.getArgs(), context.getProjectDir());
178
}
179
}
180
```
181
182
## File System Watching and Hot Deployment
183
184
### File System Watchers
185
186
```java { .api }
187
class StaticFileSystemWatcher {
188
/**
189
* Watches static resources for changes
190
*/
191
StaticFileSystemWatcher(Path watchedPath,
192
Set<String> includedExtensions,
193
Consumer<Set<String>> changeCallback);
194
195
/**
196
* Starts watching for file changes
197
*/
198
void start();
199
200
/**
201
* Stops file watching
202
*/
203
void stop();
204
}
205
206
class ReloadableFileSystemWatcher {
207
/**
208
* Watches source files for changes requiring compilation
209
*/
210
void watchPath(Path path, String... extensions);
211
212
/**
213
* Gets changed files since last check
214
*/
215
Set<Path> getChangedPaths();
216
217
/**
218
* Resets the changed files tracking
219
*/
220
void reset();
221
}
222
```
223
224
### Hot Deployment Build Items
225
226
```java { .api }
227
class HotDeploymentWatchedFileBuildItem extends MultiBuildItem {
228
/**
229
* Creates a watched file item
230
*/
231
HotDeploymentWatchedFileBuildItem(String location);
232
233
/**
234
* Creates a watched file item with restart behavior
235
*/
236
HotDeploymentWatchedFileBuildItem(String location, boolean restartNeeded);
237
238
String getLocation();
239
boolean isRestartNeeded();
240
}
241
242
class ClassScanResult {
243
/**
244
* Classes that have been added
245
*/
246
Set<String> getAddedClasses();
247
248
/**
249
* Classes that have been modified
250
*/
251
Set<String> getChangedClasses();
252
253
/**
254
* Classes that have been deleted
255
*/
256
Set<String> getDeletedClasses();
257
258
/**
259
* Whether changes require a restart
260
*/
261
boolean isRestartNeeded();
262
}
263
```
264
265
**Usage Examples:**
266
267
```java
268
@BuildStep(onlyIf = IsDevelopment.class)
269
void setupFileWatching(ApplicationArchivesBuildItem archives,
270
BuildProducer<HotDeploymentWatchedFileBuildItem> watchedFiles) {
271
272
// Watch templates for changes
273
watchedFiles.produce(new HotDeploymentWatchedFileBuildItem("templates/", false));
274
275
// Watch configuration that requires restart
276
watchedFiles.produce(new HotDeploymentWatchedFileBuildItem("application.yaml", true));
277
278
// Watch web resources
279
watchedFiles.produce(new HotDeploymentWatchedFileBuildItem("META-INF/resources/", false));
280
}
281
282
public class HotReloadSetup implements HotReplacementSetup {
283
@Override
284
public void setupHotDeployment(HotReplacementContext context) {
285
context.consumeNoRestartChanges(changedResources -> {
286
// Handle resource changes that don't require restart
287
for (String resource : changedResources) {
288
if (resource.endsWith(".html") || resource.endsWith(".css")) {
289
// Refresh web resources
290
refreshWebResource(resource);
291
}
292
}
293
});
294
}
295
}
296
```
297
298
## Compilation Providers
299
300
### CompilationProvider Interface
301
302
Service provider interface for handling compilation of different file types in development mode.
303
304
```java { .api }
305
interface CompilationProvider {
306
/**
307
* File extensions this provider can handle
308
*/
309
Set<String> handledExtensions();
310
311
/**
312
* Compiles the specified files
313
*/
314
void compile(Set<File> filesToCompile, Context context);
315
316
/**
317
* Compilation context providing build information
318
*/
319
interface Context {
320
/**
321
* Source directory for compilation
322
*/
323
Path getSourceDirectory();
324
325
/**
326
* Output directory for compiled classes
327
*/
328
Path getOutputDirectory();
329
330
/**
331
* Classpath for compilation
332
*/
333
ClassLoader getClasspathClassLoader();
334
335
/**
336
* Gets the project directory
337
*/
338
Path getProjectDirectory();
339
340
/**
341
* Gets compiler arguments
342
*/
343
List<String> getCompilerOptions();
344
}
345
}
346
```
347
348
**Implementation Example:**
349
350
```java
351
public class KotlinCompilationProvider implements CompilationProvider {
352
353
@Override
354
public Set<String> handledExtensions() {
355
return Set.of(".kt", ".kts");
356
}
357
358
@Override
359
public void compile(Set<File> filesToCompile, Context context) {
360
if (filesToCompile.isEmpty()) {
361
return;
362
}
363
364
List<String> args = new ArrayList<>();
365
args.add("-cp");
366
args.add(buildClasspath(context));
367
args.add("-d");
368
args.add(context.getOutputDirectory().toString());
369
370
// Add Kotlin-specific options
371
args.addAll(context.getCompilerOptions());
372
373
// Add source files
374
filesToCompile.forEach(file -> args.add(file.getAbsolutePath()));
375
376
// Execute Kotlin compiler
377
KotlinCompiler.exec(args.toArray(new String[0]));
378
}
379
}
380
381
@BuildStep
382
void registerKotlinCompiler(BuildProducer<CompilationProviderBuildItem> providers) {
383
providers.produce(new CompilationProviderBuildItem(KotlinCompilationProvider.class));
384
}
385
```
386
387
## Development Services
388
389
### DevServices Infrastructure
390
391
Development services automatically start external services like databases, message brokers, etc., during development.
392
393
```java { .api }
394
class DevServicesConfig {
395
/**
396
* Whether dev services are enabled globally
397
*/
398
@WithDefault("true")
399
boolean enabled;
400
401
/**
402
* Timeout for starting services
403
*/
404
@WithDefault("60s")
405
Duration timeout;
406
407
/**
408
* Whether to share services between applications
409
*/
410
@WithDefault("true")
411
boolean shared;
412
}
413
414
class DevServicesBuildItem extends MultiBuildItem {
415
/**
416
* Creates a dev service build item
417
*/
418
DevServicesBuildItem(String name,
419
String containerImage,
420
Map<String, String> containerProperties,
421
Map<String, Object> configProperties);
422
423
String getName();
424
String getContainerImage();
425
Map<String, String> getContainerProperties();
426
Map<String, Object> getConfigProperties();
427
}
428
429
class DevServicesResultBuildItem extends SimpleBuildItem {
430
Map<String, String> getConfig();
431
Closeable getCloseable();
432
}
433
```
434
435
**Usage Examples:**
436
437
```java
438
@BuildStep(onlyIf = { IsDevelopment.class, DevServicesEnabled.class })
439
DevServicesBuildItem startDatabase(LaunchModeBuildItem launchMode,
440
DatabaseConfig config) {
441
442
if (config.devservices.enabled && config.url.isEmpty()) {
443
Map<String, String> containerProps = Map.of(
444
"POSTGRES_DB", "devdb",
445
"POSTGRES_USER", "dev",
446
"POSTGRES_PASSWORD", "dev"
447
);
448
449
Map<String, Object> configProps = Map.of(
450
"quarkus.datasource.jdbc.url", "jdbc:postgresql://localhost:5432/devdb",
451
"quarkus.datasource.username", "dev",
452
"quarkus.datasource.password", "dev"
453
);
454
455
return new DevServicesBuildItem(
456
"postgresql",
457
"postgres:13",
458
containerProps,
459
configProps
460
);
461
}
462
return null;
463
}
464
465
@BuildStep
466
DevServicesResultBuildItem configureDevServices(List<DevServicesBuildItem> devServices,
467
LaunchModeBuildItem launchMode) {
468
Map<String, String> combinedConfig = new HashMap<>();
469
List<Closeable> closeables = new ArrayList<>();
470
471
for (DevServicesBuildItem devService : devServices) {
472
// Start container and collect configuration
473
ContainerInfo container = startContainer(devService);
474
combinedConfig.putAll(container.getConfig());
475
closeables.add(container::stop);
476
}
477
478
return new DevServicesResultBuildItem(combinedConfig, () -> {
479
for (Closeable closeable : closeables) {
480
closeable.close();
481
}
482
});
483
}
484
```
485
486
## Console and Command Integration
487
488
### Console Commands
489
490
```java { .api }
491
interface ConsoleCommand {
492
/**
493
* Command name for console input
494
*/
495
String getCommand();
496
497
/**
498
* Description of the command
499
*/
500
String getDescription();
501
502
/**
503
* Executes the command
504
*/
505
void execute(String[] args, ConsoleContext context);
506
507
/**
508
* Whether command is available in current mode
509
*/
510
default boolean isAvailable() { return true; }
511
}
512
513
class ConsoleStateManager {
514
/**
515
* Registers a console command
516
*/
517
void addCommand(ConsoleCommand command);
518
519
/**
520
* Processes console input
521
*/
522
void handleInput(String input);
523
524
/**
525
* Sets up console reading thread
526
*/
527
void setupConsole();
528
}
529
```
530
531
**Implementation Example:**
532
533
```java
534
public class TestCommand implements ConsoleCommand {
535
536
@Override
537
public String getCommand() {
538
return "t";
539
}
540
541
@Override
542
public String getDescription() {
543
return "Run tests";
544
}
545
546
@Override
547
public void execute(String[] args, ConsoleContext context) {
548
TestSupport.runTests();
549
}
550
551
@Override
552
public boolean isAvailable() {
553
return LaunchMode.current() == LaunchMode.DEVELOPMENT;
554
}
555
}
556
557
@BuildStep(onlyIf = IsDevelopment.class)
558
void registerConsoleCommands(BuildProducer<ConsoleCommandBuildItem> commands) {
559
commands.produce(new ConsoleCommandBuildItem(new TestCommand()));
560
commands.produce(new ConsoleCommandBuildItem(new RestartCommand()));
561
commands.produce(new ConsoleCommandBuildItem(new HelpCommand()));
562
}
563
```
564
565
## Remote Development Mode
566
567
### Remote Development Client
568
569
```java { .api }
570
class RemoteDevClient {
571
/**
572
* Connects to remote development server
573
*/
574
static RemoteDevClient connect(RemoteDevConfig config);
575
576
/**
577
* Sends local changes to remote server
578
*/
579
void sendChanges(Set<Path> changedFiles);
580
581
/**
582
* Receives updates from remote server
583
*/
584
void receiveUpdates();
585
586
/**
587
* Disconnects from remote server
588
*/
589
void disconnect();
590
}
591
592
class RemoteDevConfig {
593
/**
594
* Remote server URL
595
*/
596
String url;
597
598
/**
599
* Authentication token
600
*/
601
Optional<String> password;
602
603
/**
604
* Connection timeout
605
*/
606
@WithDefault("30s")
607
Duration connectTimeout;
608
}
609
```
610
611
**Usage Example:**
612
613
```java
614
@BuildStep(onlyIf = { IsDevelopment.class, RemoteDevEnabled.class })
615
@Record(ExecutionTime.RUNTIME_INIT)
616
void setupRemoteDev(RemoteDevRecorder recorder,
617
RemoteDevConfig config,
618
DevModeContext context) {
619
620
recorder.setupRemoteDevClient(
621
config.url,
622
config.password.orElse(null),
623
context.getProjectDir()
624
);
625
}
626
```
627
628
## Testing Integration
629
630
### Development Mode Testing
631
632
```java { .api }
633
class TestSupport {
634
/**
635
* Runs all tests in development mode
636
*/
637
static TestRunResults runTests();
638
639
/**
640
* Runs specific test classes
641
*/
642
static TestRunResults runTests(Set<String> testClasses);
643
644
/**
645
* Checks if tests are currently running
646
*/
647
static boolean isRunning();
648
649
/**
650
* Gets the last test results
651
*/
652
static Optional<TestRunResults> getLastResults();
653
}
654
655
class TestRunResults {
656
long getTestsRun();
657
long getTestsSkipped();
658
long getTestsFailed();
659
Duration getDuration();
660
List<TestFailure> getFailures();
661
}
662
663
class TestConfig {
664
/**
665
* Whether to run tests automatically on changes
666
*/
667
@WithDefault("false")
668
boolean continuous;
669
670
/**
671
* Test framework to use
672
*/
673
@WithDefault("junit5")
674
TestFramework framework;
675
676
/**
677
* Include patterns for test discovery
678
*/
679
List<String> includePattern;
680
681
/**
682
* Exclude patterns for test discovery
683
*/
684
List<String> excludePattern;
685
}
686
```
687
688
**Usage Example:**
689
690
```java
691
@BuildStep(onlyIf = IsDevelopment.class)
692
@Record(ExecutionTime.RUNTIME_INIT)
693
void setupTestSupport(TestRecorder recorder,
694
TestConfig config,
695
ApplicationIndexBuildItem index) {
696
697
List<String> testClasses = index.getIndex()
698
.getAllKnownImplementors(DotName.createSimple("org.junit.jupiter.api.Test"))
699
.stream()
700
.map(classInfo -> classInfo.name().toString())
701
.collect(Collectors.toList());
702
703
recorder.setupTestSupport(testClasses, config.continuous);
704
}
705
```
706
707
## IDE Integration
708
709
### IDE Configuration and Support
710
711
```java { .api }
712
class IdeConfig {
713
/**
714
* Target IDE for integration
715
*/
716
Optional<IdeType> target;
717
718
/**
719
* Whether to open URLs in IDE
720
*/
721
@WithDefault("true")
722
boolean openUrls;
723
724
enum IdeType {
725
IDEA, ECLIPSE, VSCODE, NETBEANS
726
}
727
}
728
729
class EffectiveIdeBuildItem extends SimpleBuildItem {
730
Optional<IdeType> getIdeType();
731
boolean isIdePresent();
732
733
/**
734
* Opens a file in the IDE at specific line
735
*/
736
void openFile(Path file, int line);
737
738
/**
739
* Opens a URL in the IDE
740
*/
741
void openUrl(String url);
742
}
743
```
744
745
**Usage Example:**
746
747
```java
748
@BuildStep
749
EffectiveIdeBuildItem detectIde(IdeConfig config) {
750
// Detect IDE based on environment variables, system properties, etc.
751
Optional<IdeType> detectedIde = detectCurrentIde();
752
753
IdeType effectiveIde = config.target.orElse(detectedIde.orElse(null));
754
755
return new EffectiveIdeBuildItem(Optional.ofNullable(effectiveIde));
756
}
757
758
@BuildStep(onlyIf = IsDevelopment.class)
759
void setupIdeIntegration(EffectiveIdeBuildItem ide,
760
BuildProducer<ConsoleCommandBuildItem> commands) {
761
762
if (ide.isIdePresent()) {
763
commands.produce(new ConsoleCommandBuildItem(new OpenInIdeCommand(ide)));
764
}
765
}
766
```