0
# Bean Container Management
1
2
Programmatic access to the CDI bean container for runtime bean resolution, context management, and lifecycle control. The BeanContainer interface provides the primary API for interacting with Arc's runtime container.
3
4
## Capabilities
5
6
### BeanContainer Interface
7
8
Main interface for programmatic bean container access and manipulation.
9
10
```java { .api }
11
/**
12
* Represents a CDI bean container.
13
* Extensions using this API can also leverage arbitrary methods from running ArcContainer
14
* which can be obtained by invoking a static method Arc.container().
15
*/
16
public interface BeanContainer {
17
/**
18
* Resolves a bean instance for given bean type and qualifiers.
19
* Performs standard CDI resolution meaning it either returns a bean instance or throws a corresponding exception
20
* if the dependency is either unsatisfied or ambiguous.
21
*
22
* @param beanType type of the bean
23
* @param beanQualifiers bean qualifiers
24
* @return a bean instance; never null
25
*/
26
<T> T beanInstance(Class<T> beanType, Annotation... beanQualifiers);
27
28
/**
29
* Returns an instance factory for given bean type and qualifiers.
30
* This method performs CDI ambiguous dependency resolution and throws and exception if there are two or more beans
31
* with given type and qualifiers.
32
* If no matching bean is found, uses a default fallback factory that will attempt to instantiate a non-CDI object
33
* of the given class via no-args constructor.
34
*
35
* @param type bean type
36
* @param qualifiers bean qualifiers
37
* @return a bean instance factory, never null
38
*/
39
<T> Factory<T> beanInstanceFactory(Class<T> type, Annotation... qualifiers);
40
41
/**
42
* Returns an instance factory for given bean type and qualifiers.
43
* This method performs CDI ambiguous dependency resolution and throws and exception if there are two or more beans
44
* with given type and qualifiers.
45
* If no matching bean is found, delegates all calls to the supplied factory fallback.
46
*
47
* @param fallbackSupplier supplier to delegate to if there is no bean
48
* @param type bean type
49
* @param qualifiers bean qualifiers
50
* @return a bean instance factory, never null
51
*/
52
<T> Factory<T> beanInstanceFactory(
53
Supplier<Factory<T>> fallbackSupplier,
54
Class<T> type,
55
Annotation... qualifiers
56
);
57
58
/**
59
* Returns the context for RequestScoped beans.
60
* @return the context for jakarta.enterprise.context.RequestScoped
61
* @throws IllegalStateException If the container is not running
62
*/
63
ManagedContext requestContext();
64
65
interface Factory<T> {
66
Factory<Object> EMPTY = new Factory<Object>() {
67
@Override
68
public Instance<Object> create() {
69
return null;
70
}
71
};
72
73
/**
74
* @return a bean instance or null if no matching bean is found
75
*/
76
Instance<T> create();
77
}
78
79
interface Instance<T> extends AutoCloseable {
80
/**
81
* @return the underlying instance
82
*/
83
T get();
84
85
/**
86
* releases the underlying instance
87
*/
88
default void close();
89
}
90
}
91
```
92
93
**Usage Examples:**
94
95
```java
96
import jakarta.enterprise.context.ApplicationScoped;
97
import jakarta.inject.Inject;
98
import io.quarkus.arc.runtime.BeanContainer;
99
import io.quarkus.arc.Arc;
100
101
@ApplicationScoped
102
public class ContainerService {
103
104
@Inject
105
BeanContainer container;
106
107
public void demonstrateBasicUsage() {
108
// Direct bean instance resolution
109
UserService userService = container.beanInstance(UserService.class);
110
userService.processUser("john");
111
112
// Bean resolution with qualifiers
113
PaymentService premiumPayment = container.beanInstance(
114
PaymentService.class,
115
new PremiumQualifier.Literal()
116
);
117
premiumPayment.processPayment(100.0);
118
}
119
120
public void demonstrateFactoryUsage() {
121
// Create a factory for repeated bean creation
122
BeanContainer.Factory<NotificationService> factory =
123
container.beanInstanceFactory(NotificationService.class);
124
125
// Use the factory multiple times
126
for (int i = 0; i < 5; i++) {
127
try (BeanContainer.Instance<NotificationService> instance = factory.create()) {
128
instance.get().send("Message " + i);
129
} // Automatic cleanup with try-with-resources
130
}
131
}
132
133
public void demonstrateContextManagement() {
134
ManagedContext requestContext = container.requestContext();
135
136
if (requestContext.isActive()) {
137
// Request context is already active
138
performRequestScopedOperation();
139
} else {
140
// Manually activate request context
141
try {
142
requestContext.activate();
143
performRequestScopedOperation();
144
} finally {
145
requestContext.terminate();
146
}
147
}
148
}
149
150
private void performRequestScopedOperation() {
151
// Operations that require request context
152
RequestScopedService service = container.beanInstance(RequestScopedService.class);
153
service.handleRequest();
154
}
155
}
156
```
157
158
### BeanContainerListener Interface
159
160
Listener interface for bean container lifecycle events, allowing configuration immediately after container creation.
161
162
```java { .api }
163
/**
164
* An interface that can be used to configure beans immediately after the BeanContainer has been
165
* created. The container is passed to the interface and beans can be obtained and be modified.
166
* This provides a convenient way to pass configuration from the deployment processors into runtime beans.
167
*/
168
public interface BeanContainerListener {
169
void created(BeanContainer container);
170
}
171
```
172
173
**Usage Examples:**
174
175
```java
176
import io.quarkus.arc.runtime.BeanContainer;
177
import io.quarkus.arc.runtime.BeanContainerListener;
178
179
public class DatabaseConfigurationListener implements BeanContainerListener {
180
181
private final String databaseUrl;
182
private final String username;
183
private final String password;
184
185
public DatabaseConfigurationListener(String databaseUrl, String username, String password) {
186
this.databaseUrl = databaseUrl;
187
this.username = username;
188
this.password = password;
189
}
190
191
@Override
192
public void created(BeanContainer container) {
193
// Configure database service after container creation
194
DatabaseService dbService = container.beanInstance(DatabaseService.class);
195
dbService.configure(databaseUrl, username, password);
196
197
// Initialize connection pool
198
ConnectionPoolManager poolManager = container.beanInstance(ConnectionPoolManager.class);
199
poolManager.initializePool();
200
201
// Setup cache if available
202
BeanContainer.Factory<CacheService> cacheFactory =
203
container.beanInstanceFactory(CacheService.class);
204
205
try (BeanContainer.Instance<CacheService> cacheInstance = cacheFactory.create()) {
206
if (cacheInstance != null) {
207
cacheInstance.get().initialize();
208
}
209
}
210
}
211
}
212
213
// Usage in configuration
214
public class AppInitializer {
215
216
public void setupApplication() {
217
// Register listener to be called when container is created
218
BeanContainerListener listener = new DatabaseConfigurationListener(
219
"jdbc:postgresql://localhost:5432/mydb",
220
"user",
221
"password"
222
);
223
224
// The listener will be called automatically by the framework
225
// (actual registration mechanism depends on the framework integration)
226
}
227
}
228
```
229
230
### Advanced Container Operations
231
232
Complex container manipulation patterns for sophisticated use cases.
233
234
```java
235
import jakarta.enterprise.context.ApplicationScoped;
236
import jakarta.enterprise.util.AnnotationLiteral;
237
import jakarta.inject.Qualifier;
238
import io.quarkus.arc.runtime.BeanContainer;
239
import io.quarkus.arc.Arc;
240
import java.lang.annotation.Retention;
241
import java.lang.annotation.RetentionPolicy;
242
import java.util.function.Supplier;
243
244
@ApplicationScoped
245
public class AdvancedContainerService {
246
247
public void demonstrateFactoryWithFallback() {
248
BeanContainer container = Arc.container();
249
250
// Create factory with custom fallback
251
Supplier<BeanContainer.Factory<ExternalService>> fallbackSupplier = () ->
252
() -> () -> new MockExternalService(); // Triple lambda for Factory<Instance<T>>
253
254
BeanContainer.Factory<ExternalService> factory = container.beanInstanceFactory(
255
fallbackSupplier,
256
ExternalService.class
257
);
258
259
try (BeanContainer.Instance<ExternalService> instance = factory.create()) {
260
ExternalService service = instance.get();
261
service.performOperation();
262
}
263
}
264
265
public void demonstrateQualifiedBeanResolution() {
266
BeanContainer container = Arc.container();
267
268
// Resolution with multiple qualifiers
269
PaymentProcessor processor = container.beanInstance(
270
PaymentProcessor.class,
271
new PaymentProvider.Literal("stripe"),
272
new Environment.Literal("production")
273
);
274
275
processor.processPayment(250.0);
276
}
277
278
public <T> void demonstrateGenericBeanManagement(Class<T> beanType) {
279
BeanContainer container = Arc.container();
280
281
// Generic bean factory creation
282
BeanContainer.Factory<T> factory = container.beanInstanceFactory(beanType);
283
284
// Create and manage multiple instances
285
for (int i = 0; i < 3; i++) {
286
try (BeanContainer.Instance<T> instance = factory.create()) {
287
T bean = instance.get();
288
if (bean instanceof Processable) {
289
((Processable) bean).process("Item " + i);
290
}
291
}
292
}
293
}
294
295
public void demonstrateContextLifecycleManagement() {
296
BeanContainer container = Arc.container();
297
ManagedContext requestContext = container.requestContext();
298
299
// Complex context management
300
boolean wasActive = requestContext.isActive();
301
302
if (!wasActive) {
303
requestContext.activate();
304
}
305
306
try {
307
// Perform operations requiring request context
308
RequestScopedDataHolder dataHolder =
309
container.beanInstance(RequestScopedDataHolder.class);
310
dataHolder.storeData("key", "value");
311
312
// Process with request-scoped beans
313
RequestProcessor processor =
314
container.beanInstance(RequestProcessor.class);
315
processor.processRequest();
316
317
} finally {
318
if (!wasActive) {
319
requestContext.terminate();
320
}
321
}
322
}
323
}
324
325
// Supporting interfaces and classes
326
interface ExternalService {
327
void performOperation();
328
}
329
330
class MockExternalService implements ExternalService {
331
public void performOperation() {
332
System.out.println("Mock external service operation");
333
}
334
}
335
336
interface PaymentProcessor {
337
void processPayment(double amount);
338
}
339
340
interface Processable {
341
void process(String item);
342
}
343
344
@Qualifier
345
@Retention(RetentionPolicy.RUNTIME)
346
@interface PaymentProvider {
347
String value();
348
349
class Literal extends AnnotationLiteral<PaymentProvider> implements PaymentProvider {
350
private final String value;
351
public Literal(String value) { this.value = value; }
352
public String value() { return value; }
353
}
354
}
355
356
@Qualifier
357
@Retention(RetentionPolicy.RUNTIME)
358
@interface Environment {
359
String value();
360
361
class Literal extends AnnotationLiteral<Environment> implements Environment {
362
private final String value;
363
public Literal(String value) { this.value = value; }
364
public String value() { return value; }
365
}
366
}
367
368
@ApplicationScoped
369
class RequestScopedDataHolder {
370
public void storeData(String key, String value) {
371
// Store data in request scope
372
}
373
}
374
375
@ApplicationScoped
376
class RequestProcessor {
377
public void processRequest() {
378
// Process request
379
}
380
}
381
```
382
383
### Container Integration Patterns
384
385
Common patterns for integrating container management with application architecture.
386
387
```java
388
import jakarta.enterprise.context.ApplicationScoped;
389
import jakarta.enterprise.event.Observes;
390
import io.quarkus.runtime.StartupEvent;
391
import io.quarkus.arc.runtime.BeanContainer;
392
import io.quarkus.arc.Arc;
393
394
@ApplicationScoped
395
public class ApplicationLifecycleManager {
396
397
public void onStartup(@Observes StartupEvent event) {
398
BeanContainer container = Arc.container();
399
400
// Initialize critical services
401
initializeCriticalServices(container);
402
403
// Setup scheduled tasks
404
setupScheduledTasks(container);
405
406
// Warm up caches
407
warmupCaches(container);
408
}
409
410
private void initializeCriticalServices(BeanContainer container) {
411
// Initialize database connections
412
DatabaseConnectionManager dbManager =
413
container.beanInstance(DatabaseConnectionManager.class);
414
dbManager.initialize();
415
416
// Setup security services
417
SecurityManager securityManager =
418
container.beanInstance(SecurityManager.class);
419
securityManager.initialize();
420
}
421
422
private void setupScheduledTasks(BeanContainer container) {
423
// Create factory for task services
424
BeanContainer.Factory<TaskScheduler> schedulerFactory =
425
container.beanInstanceFactory(TaskScheduler.class);
426
427
try (BeanContainer.Instance<TaskScheduler> schedulerInstance = schedulerFactory.create()) {
428
TaskScheduler scheduler = schedulerInstance.get();
429
scheduler.scheduleRecurringTasks();
430
}
431
}
432
433
private void warmupCaches(BeanContainer container) {
434
// Warmup various cache services
435
String[] cacheTypes = {"user", "product", "configuration"};
436
437
for (String cacheType : cacheTypes) {
438
try {
439
CacheService cache = container.beanInstance(
440
CacheService.class,
441
new CacheType.Literal(cacheType)
442
);
443
cache.warmup();
444
} catch (Exception e) {
445
// Log warning but continue with other caches
446
System.err.println("Failed to warmup cache: " + cacheType);
447
}
448
}
449
}
450
}
451
452
// Service discovery pattern
453
@ApplicationScoped
454
public class ServiceDiscovery {
455
456
public <T> List<T> findAllServices(Class<T> serviceType) {
457
BeanContainer container = Arc.container();
458
459
// This is a simplified example - real implementation would need
460
// to use Arc's internal APIs for bean discovery
461
List<T> services = new ArrayList<>();
462
463
try {
464
T service = container.beanInstance(serviceType);
465
services.add(service);
466
} catch (Exception e) {
467
// No bean found or ambiguous resolution
468
}
469
470
return services;
471
}
472
473
public <T> Optional<T> findService(Class<T> serviceType, Annotation... qualifiers) {
474
BeanContainer container = Arc.container();
475
476
try {
477
T service = container.beanInstance(serviceType, qualifiers);
478
return Optional.of(service);
479
} catch (Exception e) {
480
return Optional.empty();
481
}
482
}
483
}
484
485
// Supporting classes
486
interface DatabaseConnectionManager {
487
void initialize();
488
}
489
490
interface SecurityManager {
491
void initialize();
492
}
493
494
interface TaskScheduler {
495
void scheduleRecurringTasks();
496
}
497
498
interface CacheService {
499
void warmup();
500
}
501
502
@Qualifier
503
@Retention(RetentionPolicy.RUNTIME)
504
@interface CacheType {
505
String value();
506
507
class Literal extends AnnotationLiteral<CacheType> implements CacheType {
508
private final String value;
509
public Literal(String value) { this.value = value; }
510
public String value() { return value; }
511
}
512
}
513
```
514
515
## Container Access Methods
516
517
### Direct Arc Container Access
518
519
```java
520
import io.quarkus.arc.Arc;
521
import io.quarkus.arc.ArcContainer;
522
523
public class DirectContainerAccess {
524
525
public void useArcContainer() {
526
// Access Arc container directly
527
ArcContainer arcContainer = Arc.container();
528
529
// Arc container provides additional methods beyond BeanContainer
530
UserService userService = arcContainer.instance(UserService.class).get();
531
userService.processUser("jane");
532
533
// Check if container is running
534
if (arcContainer.isRunning()) {
535
// Container operations
536
}
537
}
538
}
539
```
540
541
### Injection-Based Access
542
543
```java
544
import jakarta.enterprise.context.ApplicationScoped;
545
import jakarta.inject.Inject;
546
import io.quarkus.arc.runtime.BeanContainer;
547
548
@ApplicationScoped
549
public class InjectionBasedAccess {
550
551
@Inject
552
BeanContainer container;
553
554
public void useBeanContainer() {
555
// Use injected container
556
SomeService service = container.beanInstance(SomeService.class);
557
service.performAction();
558
}
559
}
560
```
561
562
## Error Handling and Best Practices
563
564
### Exception Handling
565
566
```java
567
import jakarta.enterprise.inject.UnsatisfiedResolutionException;
568
import jakarta.enterprise.inject.AmbiguousResolutionException;
569
570
@ApplicationScoped
571
public class SafeContainerUsage {
572
573
@Inject
574
BeanContainer container;
575
576
public void safelyResolveBean() {
577
try {
578
PaymentService paymentService = container.beanInstance(PaymentService.class);
579
paymentService.processPayment(100.0);
580
} catch (UnsatisfiedResolutionException e) {
581
// No bean found
582
System.err.println("No PaymentService implementation found");
583
} catch (AmbiguousResolutionException e) {
584
// Multiple beans found without qualifiers
585
System.err.println("Multiple PaymentService implementations found, use qualifiers");
586
}
587
}
588
589
public void safelyUseFactory() {
590
BeanContainer.Factory<OptionalService> factory =
591
container.beanInstanceFactory(OptionalService.class);
592
593
try (BeanContainer.Instance<OptionalService> instance = factory.create()) {
594
if (instance != null) {
595
OptionalService service = instance.get();
596
service.performOptionalOperation();
597
} else {
598
// Handle case where no bean was found
599
System.out.println("Optional service not available");
600
}
601
}
602
}
603
}
604
```
605
606
### Resource Management
607
608
```java
609
@ApplicationScoped
610
public class ResourceManagement {
611
612
@Inject
613
BeanContainer container;
614
615
public void properResourceHandling() {
616
// Always use try-with-resources for Instance objects
617
BeanContainer.Factory<ResourceIntensiveService> factory =
618
container.beanInstanceFactory(ResourceIntensiveService.class);
619
620
try (BeanContainer.Instance<ResourceIntensiveService> instance = factory.create()) {
621
ResourceIntensiveService service = instance.get();
622
service.performHeavyOperation();
623
} // Automatic resource cleanup
624
}
625
}
626
```