0
# Build Property Conditional Beans
1
2
Enable beans based on build-time configuration properties, allowing feature toggles and environment-specific configurations. These annotations evaluate property values during the build process to determine bean inclusion.
3
4
## Capabilities
5
6
### IfBuildProperty Annotation
7
8
Enables beans when build-time properties match specified values.
9
10
```java { .api }
11
/**
12
* When applied to a bean class or producer method (or field), the bean will only be enabled
13
* if the Quarkus build time property matches the provided value.
14
* By default, the bean is not enabled when the build time property is not defined at all,
15
* but this behavior is configurable via the enableIfMissing property.
16
* This annotation is repeatable. A bean will only be enabled if all the conditions
17
* defined by the IfBuildProperty annotations are satisfied.
18
*/
19
@Repeatable(IfBuildProperty.List.class)
20
@Retention(RetentionPolicy.RUNTIME)
21
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
22
public @interface IfBuildProperty {
23
/**
24
* Name of the build time property to check
25
*/
26
String name();
27
28
/**
29
* Expected String value of the build time property (specified by name) if the bean is to be enabled
30
*/
31
String stringValue();
32
33
/**
34
* Determines if the bean is to be enabled when the property name specified by name has not been specified at all
35
*/
36
boolean enableIfMissing() default false;
37
38
@Retention(RetentionPolicy.RUNTIME)
39
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
40
@interface List {
41
IfBuildProperty[] value();
42
}
43
}
44
```
45
46
**Usage Examples:**
47
48
```java
49
import jakarta.enterprise.context.ApplicationScoped;
50
import io.quarkus.arc.properties.IfBuildProperty;
51
52
// Enabled when feature.analytics property is set to "true"
53
@ApplicationScoped
54
@IfBuildProperty(name = "feature.analytics", stringValue = "true")
55
public class AnalyticsService {
56
public void trackEvent(String event) {
57
// Analytics implementation
58
}
59
}
60
61
// Enabled when property is missing (not defined)
62
@ApplicationScoped
63
@IfBuildProperty(name = "feature.experimental", stringValue = "enabled", enableIfMissing = true)
64
public class ExperimentalFeature {
65
public void experimentalOperation() {
66
// Experimental feature enabled by default
67
}
68
}
69
70
// Multiple conditions - both properties must match
71
@ApplicationScoped
72
@IfBuildProperty(name = "database.type", stringValue = "postgresql")
73
@IfBuildProperty(name = "database.ssl", stringValue = "true")
74
public class SecurePostgreSQLService {
75
public void connectToSecureDatabase() {
76
// PostgreSQL with SSL implementation
77
}
78
}
79
```
80
81
### UnlessBuildProperty Annotation
82
83
Enables beans when build-time properties do NOT match specified values (inverse of IfBuildProperty).
84
85
```java { .api }
86
/**
87
* When applied to a bean class or producer method (or field), the bean will only be enabled
88
* if the Quarkus build time property does not match the provided value.
89
* By default, the bean is not enabled when the build time property is not defined at all,
90
* but this behavior is configurable via the enableIfMissing property.
91
* This annotation is repeatable. A bean will only be enabled if all the conditions
92
* defined by the UnlessBuildProperty annotations are satisfied.
93
*/
94
@Repeatable(UnlessBuildProperty.List.class)
95
@Retention(RetentionPolicy.RUNTIME)
96
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
97
public @interface UnlessBuildProperty {
98
/**
99
* Name of the build time property to check
100
*/
101
String name();
102
103
/**
104
* The bean is enabled if the build time property (specified by name) does not match this value.
105
*/
106
String stringValue();
107
108
/**
109
* Determines if the bean is enabled when the property name specified by name has not been specified at all
110
*/
111
boolean enableIfMissing() default false;
112
113
@Retention(RetentionPolicy.RUNTIME)
114
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
115
@interface List {
116
UnlessBuildProperty[] value();
117
}
118
}
119
```
120
121
**Usage Examples:**
122
123
```java
124
import jakarta.enterprise.context.ApplicationScoped;
125
import io.quarkus.arc.properties.UnlessBuildProperty;
126
127
// Enabled when cache.enabled property is NOT set to "false"
128
@ApplicationScoped
129
@UnlessBuildProperty(name = "cache.enabled", stringValue = "false")
130
public class CacheService {
131
public void cache(String key, Object value) {
132
// Caching implementation
133
}
134
}
135
136
// Enabled when debug.mode property is NOT set to "true"
137
@ApplicationScoped
138
@UnlessBuildProperty(name = "debug.mode", stringValue = "true")
139
public class ProductionOptimizedService {
140
public void performOptimizedOperation() {
141
// Production-optimized implementation
142
}
143
}
144
145
// Enabled when missing property should enable the bean
146
@ApplicationScoped
147
@UnlessBuildProperty(name = "feature.disabled", stringValue = "true", enableIfMissing = true)
148
public class DefaultEnabledFeature {
149
public void defaultBehavior() {
150
// Enabled unless explicitly disabled
151
}
152
}
153
```
154
155
### Producer Method Usage
156
157
Both annotations work with producer methods for conditional bean creation.
158
159
```java
160
import jakarta.enterprise.context.ApplicationScoped;
161
import jakarta.enterprise.inject.Produces;
162
import io.quarkus.arc.properties.IfBuildProperty;
163
import io.quarkus.arc.properties.UnlessBuildProperty;
164
165
@ApplicationScoped
166
public class StorageConfigProducer {
167
168
@Produces
169
@IfBuildProperty(name = "storage.type", stringValue = "s3")
170
public StorageProvider s3StorageProvider() {
171
return new S3StorageProvider();
172
}
173
174
@Produces
175
@IfBuildProperty(name = "storage.type", stringValue = "local")
176
public StorageProvider localStorageProvider() {
177
return new LocalStorageProvider();
178
}
179
180
@Produces
181
@UnlessBuildProperty(name = "storage.type", stringValue = "s3")
182
@UnlessBuildProperty(name = "storage.type", stringValue = "local")
183
public StorageProvider defaultStorageProvider() {
184
return new DefaultStorageProvider();
185
}
186
}
187
188
interface StorageProvider {
189
void store(String key, byte[] data);
190
}
191
192
class S3StorageProvider implements StorageProvider {
193
public void store(String key, byte[] data) {
194
// S3 implementation
195
}
196
}
197
198
class LocalStorageProvider implements StorageProvider {
199
public void store(String key, byte[] data) {
200
// Local file system implementation
201
}
202
}
203
204
class DefaultStorageProvider implements StorageProvider {
205
public void store(String key, byte[] data) {
206
// Default implementation
207
}
208
}
209
```
210
211
### Complex Conditional Logic
212
213
Combine multiple conditions for sophisticated bean activation rules.
214
215
```java
216
import jakarta.enterprise.context.ApplicationScoped;
217
import io.quarkus.arc.properties.IfBuildProperty;
218
import io.quarkus.arc.properties.UnlessBuildProperty;
219
220
// Complex service that requires multiple conditions
221
@ApplicationScoped
222
@IfBuildProperty(name = "payment.provider", stringValue = "stripe")
223
@IfBuildProperty(name = "payment.webhooks", stringValue = "true")
224
@UnlessBuildProperty(name = "payment.test-mode", stringValue = "true")
225
public class ProductionStripeWebhookHandler {
226
227
public void handleWebhook(String payload) {
228
// Production Stripe webhook handling
229
}
230
}
231
232
// Alternative implementation for different conditions
233
@ApplicationScoped
234
@IfBuildProperty(name = "payment.provider", stringValue = "stripe")
235
@IfBuildProperty(name = "payment.test-mode", stringValue = "true")
236
public class TestStripeWebhookHandler {
237
238
public void handleWebhook(String payload) {
239
// Test mode Stripe webhook handling
240
}
241
}
242
```
243
244
## Property Configuration
245
246
Build properties are configured through various sources:
247
248
### Application Properties
249
250
```properties
251
# application.properties
252
feature.analytics=true
253
database.type=postgresql
254
database.ssl=true
255
cache.enabled=true
256
storage.type=s3
257
payment.provider=stripe
258
payment.webhooks=true
259
payment.test-mode=false
260
```
261
262
### Environment-Specific Properties
263
264
```properties
265
# application-dev.properties
266
debug.mode=true
267
feature.experimental=enabled
268
payment.test-mode=true
269
270
# application-prod.properties
271
debug.mode=false
272
cache.enabled=true
273
payment.test-mode=false
274
```
275
276
### System Properties and Environment Variables
277
278
```bash
279
# System properties
280
java -Dfeature.analytics=true -jar application.jar
281
282
# Environment variables
283
export FEATURE_ANALYTICS=true
284
export DATABASE_TYPE=postgresql
285
```
286
287
## Common Patterns
288
289
### Feature Flags
290
291
```java
292
// Feature flag implementation
293
@ApplicationScoped
294
@IfBuildProperty(name = "features.new-ui", stringValue = "enabled")
295
public class NewUIRenderer implements UIRenderer {
296
public String render() {
297
return "New UI implementation";
298
}
299
}
300
301
@ApplicationScoped
302
@UnlessBuildProperty(name = "features.new-ui", stringValue = "enabled")
303
public class LegacyUIRenderer implements UIRenderer {
304
public String render() {
305
return "Legacy UI implementation";
306
}
307
}
308
```
309
310
### Database Provider Selection
311
312
```java
313
// Database-specific implementations
314
@ApplicationScoped
315
@IfBuildProperty(name = "quarkus.datasource.db-kind", stringValue = "postgresql")
316
public class PostgreSQLSpecificService {
317
public void usePostgreSQLFeatures() {
318
// PostgreSQL-specific functionality
319
}
320
}
321
322
@ApplicationScoped
323
@IfBuildProperty(name = "quarkus.datasource.db-kind", stringValue = "mysql")
324
public class MySQLSpecificService {
325
public void useMySQLFeatures() {
326
// MySQL-specific functionality
327
}
328
}
329
```
330
331
### Integration Toggle
332
333
```java
334
// External service integration toggle
335
@ApplicationScoped
336
@IfBuildProperty(name = "integrations.slack", stringValue = "true")
337
public class SlackNotificationService implements NotificationService {
338
public void notify(String message) {
339
// Slack integration
340
}
341
}
342
343
@ApplicationScoped
344
@IfBuildProperty(name = "integrations.email", stringValue = "true")
345
public class EmailNotificationService implements NotificationService {
346
public void notify(String message) {
347
// Email integration
348
}
349
}
350
351
@ApplicationScoped
352
@UnlessBuildProperty(name = "integrations.slack", stringValue = "true")
353
@UnlessBuildProperty(name = "integrations.email", stringValue = "true")
354
public class LoggingNotificationService implements NotificationService {
355
public void notify(String message) {
356
// Fallback logging implementation
357
}
358
}
359
```