Quarkus Topic
Configuration, Logging, and Profiles in Quarkus
1. Configuration Management
Configuration Sources Hierarchy
Quarkus follows this order (later sources override earlier ones):
-
application.propertiesinsrc/main/resources -
application.yamlinsrc/main/resources -
System properties
-
Environment variables
-
.envfile -
Kubernetes ConfigMaps and Secrets
2. Configuration Formats
application.properties (Traditional)
properties
# Application Configuration quarkus.application.name=quarkus-config-demo quarkus.application.version=1.0.0 # Server Configuration quarkus.http.port=8080 quarkus.http.host=0.0.0.0 quarkus.http.cors=true quarkus.http.cors.origins=http://localhost:3000,http://localhost:4200 # Database Configuration quarkus.datasource.db-kind=postgresql quarkus.datasource.username=quarkus_user quarkus.datasource.password=quarkus_pass quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/quarkusdb quarkus.datasource.jdbc.max-size=16 # Hibernate ORM quarkus.hibernate-orm.database.generation=update quarkus.hibernate-orm.log.sql=true quarkus.hibernate-orm.sql-load-script=import.sql # Custom Application Configuration app.name=Quarkus Config Demo app.version=1.0.0 app.feature.flags.enabled=true app.security.jwt.secret=my-secret-key app.security.jwt.expiration=3600 app.rate-limit.requests-per-minute=100 # External Services external.api.base-url=https://api.example.com external.api.timeout=5000 external.api.retry.max-attempts=3 external.api.retry.delay=1000 # Email Configuration app.email.smtp.host=smtp.gmail.com app.email.smtp.port=587 app.email.smtp.username=your-email@gmail.com app.email.smtp.password=your-app-password app.email.from=noreply@example.com # File Upload Configuration app.upload.max-file-size=10485760 app.upload.allowed-extensions=jpg,jpeg,png,pdf,doc,docx app.upload.storage-path=./uploads
application.yaml (Modern Approach)
yaml
# application.yaml
quarkus:
application:
name: "quarkus-config-demo"
version: "1.0.0"
http:
port: 8080
host: "0.0.0.0"
cors: true
cors:
origins: "http://localhost:3000,http://localhost:4200"
datasource:
db-kind: "postgresql"
username: "quarkus_user"
password: "quarkus_pass"
jdbc:
url: "jdbc:postgresql://localhost:5432/quarkusdb"
max-size: 16
hibernate-orm:
database:
generation: "update"
log:
sql: true
sql-load-script: "import.sql"
# Custom Application Configuration
app:
name: "Quarkus Config Demo"
version: "1.0.0"
feature:
flags:
enabled: true
security:
jwt:
secret: "my-secret-key"
expiration: 3600
rate-limit:
requests-per-minute: 100
upload:
max-file-size: 10485760
allowed-extensions: "jpg,jpeg,png,pdf,doc,docx"
storage-path: "./uploads"
email:
smtp:
host: "smtp.gmail.com"
port: 587
username: "your-email@gmail.com"
password: "your-app-password"
from: "noreply@example.com"
# External Services Configuration
external:
api:
base-url: "https://api.example.com"
timeout: 5000
retry:
max-attempts: 3
delay: 1000
# Feature Toggles
features:
new-ui: true
advanced-analytics: false
experimental-api: true
3. Environment Profiles
Profile-specific Configuration
properties
# application.properties - Common configuration
quarkus.application.name=quarkus-config-demo
app.version=1.0.0
# Development Profile (%dev)
%dev.quarkus.log.level=DEBUG
%dev.quarkus.log.console.enable=true
%dev.quarkus.datasource.db-kind=h2
%dev.quarkus.datasource.jdbc.url=jdbc:h2:mem:devdb
%dev.quarkus.hibernate-orm.database.generation=drop-and-create
%dev.quarkus.hibernate-orm.log.sql=true
%dev.app.feature.flags.enabled=true
%dev.app.security.jwt.secret=dev-secret-key-only
%dev.external.api.base-url=https://dev-api.example.com
# Test Profile (%test)
%test.quarkus.log.level=INFO
%test.quarkus.datasource.db-kind=h2
%test.quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb
%test.quarkus.hibernate-orm.database.generation=drop-and-create
%test.app.security.jwt.secret=test-secret-key-only
%test.external.api.base-url=https://test-api.example.com
# Production Profile (%prod)
%prod.quarkus.log.level=WARN
%prod.quarkus.datasource.db-kind=postgresql
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://prod-db:5432/quarkusdb
%prod.quarkus.hibernate-orm.database.generation=validate
%prod.quarkus.hibernate-orm.log.sql=false
%prod.app.feature.flags.enabled=false
%prod.app.security.jwt.secret=${JWT_SECRET:default-prod-secret}
%prod.external.api.base-url=https://api.example.com
# Staging Profile (%staging)
%staging.quarkus.log.level=INFO
%staging.quarkus.datasource.db-kind=postgresql
%staging.quarkus.datasource.jdbc.url=jdbc:postgresql://staging-db:5432/quarkusdb
%staging.quarkus.hibernate-orm.database.generation=update
%staging.app.security.jwt.secret=${JWT_SECRET:staging-secret}
%staging.external.api.base-url=https://staging-api.example.com
YAML with Profiles
yaml
# application.yaml
quarkus:
application:
name: "quarkus-config-demo"
version: "1.0.0"
app:
name: "Quarkus Config Demo"
security:
jwt:
expiration: 3600
# Development Profile
"%dev":
quarkus:
log:
level: "DEBUG"
console:
enable: true
datasource:
db-kind: "h2"
jdbc:
url: "jdbc:h2:mem:devdb"
hibernate-orm:
database:
generation: "drop-and-create"
log:
sql: true
app:
feature:
flags:
enabled: true
security:
jwt:
secret: "dev-secret-key-only"
external:
api:
base-url: "https://dev-api.example.com"
# Test Profile
"%test":
quarkus:
log:
level: "INFO"
datasource:
db-kind: "h2"
jdbc:
url: "jdbc:h2:mem:testdb"
hibernate-orm:
database:
generation: "drop-and-create"
app:
security:
jwt:
secret: "test-secret-key-only"
external:
api:
base-url: "https://test-api.example.com"
# Production Profile
"%prod":
quarkus:
log:
level: "WARN"
datasource:
db-kind: "postgresql"
jdbc:
url: "jdbc:postgresql://prod-db:5432/quarkusdb"
hibernate-orm:
database:
generation: "validate"
log:
sql: false
app:
feature:
flags:
enabled: false
security:
jwt:
secret: "${JWT_SECRET:default-prod-secret}"
external:
api:
base-url: "https://api.example.com"
4. Type-Safe Configuration with @ConfigMapping
Configuration Classes
java
package com.example.config;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithName;
import java.util.List;
import java.util.Optional;
@ConfigMapping(prefix = "app")
public interface AppConfig {
String name();
String version();
SecurityConfig security();
DatabaseConfig database();
ExternalApiConfig external();
FeatureFlags features();
UploadConfig upload();
EmailConfig email();
interface SecurityConfig {
JwtConfig jwt();
OAuthConfig oauth();
CorsConfig cors();
interface JwtConfig {
String secret();
@WithDefault("3600")
long expiration();
@WithDefault("HS256")
String algorithm();
}
interface OAuthConfig {
String clientId();
String clientSecret();
String redirectUri();
}
interface CorsConfig {
@WithDefault("http://localhost:3000")
List<String> allowedOrigins();
@WithDefault("GET,POST,PUT,DELETE,OPTIONS")
List<String> allowedMethods();
}
}
interface DatabaseConfig {
@WithName("max-connections")
@WithDefault("10")
int maxConnections();
@WithDefault("30000")
long connectionTimeout();
PoolConfig pool();
interface PoolConfig {
@WithDefault("5")
int minSize();
@WithDefault("20")
int maxSize();
}
}
interface ExternalApiConfig {
String baseUrl();
@WithDefault("5000")
int timeout();
RetryConfig retry();
interface RetryConfig {
@WithName("max-attempts")
@WithDefault("3")
int maxAttempts();
@WithDefault("1000")
long delay();
@WithDefault("2.0")
double multiplier();
}
}
interface FeatureFlags {
@WithDefault("false")
boolean newDashboard();
@WithDefault("true")
boolean advancedSearch();
@WithDefault("false")
boolean experimentalFeatures();
Optional<Boolean> darkMode(); // Optional feature
}
interface UploadConfig {
@WithName("max-file-size")
@WithDefault("10485760") // 10MB
long maxFileSize();
@WithName("allowed-extensions")
List<String> allowedExtensions();
@WithName("storage-path")
@WithDefault("./uploads")
String storagePath();
}
interface EmailConfig {
SmtpConfig smtp();
String from();
TemplatesConfig templates();
interface SmtpConfig {
String host();
int port();
String username();
String password();
@WithDefault("true")
boolean auth();
@WithDefault("true")
boolean starttls();
}
interface TemplatesConfig {
String welcome();
String passwordReset();
String notification();
}
}
}
Using Configuration in Services
java
package com.example.service;
import com.example.config.AppConfig;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.util.List;
@ApplicationScoped
public class ConfigurationService {
@Inject
AppConfig appConfig;
// Alternative: Direct property injection
@ConfigProperty(name = "app.name")
String appName;
@ConfigProperty(name = "app.security.jwt.secret")
String jwtSecret;
@ConfigProperty(name = "app.feature.flags.new-dashboard", defaultValue = "false")
boolean newDashboardEnabled;
public void printConfiguration() {
System.out.println("=== Application Configuration ===");
System.out.println("App Name: " + appConfig.name());
System.out.println("Version: " + appConfig.version());
// Security config
System.out.println("JWT Secret: " + appConfig.security().jwt().secret());
System.out.println("JWT Expiration: " + appConfig.security().jwt().expiration());
// Database config
System.out.println("Max Connections: " + appConfig.database().maxConnections());
// External API config
System.out.println("API Base URL: " + appConfig.external().baseUrl());
System.out.println("API Timeout: " + appConfig.external().timeout());
System.out.println("Retry Max Attempts: " + appConfig.external().retry().maxAttempts());
// Feature flags
System.out.println("New Dashboard: " + appConfig.features().newDashboard());
System.out.println("Advanced Search: " + appConfig.features().advancedSearch());
// Upload config
System.out.println("Max File Size: " + appConfig.upload().maxFileSize());
System.out.println("Allowed Extensions: " + appConfig.upload().allowedExtensions());
}
public boolean isFeatureEnabled(String featureName) {
switch (featureName) {
case "new-dashboard":
return appConfig.features().newDashboard();
case "advanced-search":
return appConfig.features().advancedSearch();
case "experimental-features":
return appConfig.features().experimentalFeatures();
default:
return false;
}
}
public List<String> getAllowedFileExtensions() {
return appConfig.upload().allowedExtensions();
}
public long getMaxFileSizeBytes() {
return appConfig.upload().maxFileSize();
}
}
// Service using external API configuration
package com.example.service;
import com.example.config.AppConfig;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
@ApplicationScoped
public class ExternalApiService {
@Inject
AppConfig appConfig;
private final HttpClient httpClient;
public ExternalApiService() {
this.httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofMillis(appConfig.external().timeout()))
.build();
}
public String callExternalApi(String endpoint) {
try {
String url = appConfig.external().baseUrl() + endpoint;
HttpRequest request = HttpRequest.newBuilder()
.uri(java.net.URI.create(url))
.timeout(Duration.ofMillis(appConfig.external().timeout()))
.GET()
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return response.body();
} else {
throw new RuntimeException("API call failed with status: " + response.statusCode());
}
} catch (Exception e) {
// Implement retry logic based on configuration
return handleApiErrorWithRetry(endpoint, e);
}
}
private String handleApiErrorWithRetry(String endpoint, Exception originalError) {
int maxAttempts = appConfig.external().retry().maxAttempts();
long delay = appConfig.external().retry().delay();
double multiplier = appConfig.external().retry().multiplier();
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
try {
Thread.sleep((long) (delay * Math.pow(multiplier, attempt - 1)));
return callExternalApi(endpoint); // Recursive retry
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Retry interrupted", ie);
} catch (Exception e) {
if (attempt == maxAttempts) {
throw new RuntimeException("All retry attempts failed", e);
}
// Continue to next retry attempt
}
}
throw new RuntimeException("All retry attempts failed", originalError);
}
}
5. Logging Configuration
Basic Logging Configuration
properties
# Logging Levels
quarkus.log.level=INFO
quarkus.log.category."com.example".level=DEBUG
quarkus.log.category."org.hibernate".level=WARN
quarkus.log.category."io.quarkus".level=INFO
# Console Logging
quarkus.log.console.enable=true
quarkus.log.console.level=INFO
quarkus.log.console.format=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n
quarkus.log.console.color=true
# File Logging
quarkus.log.file.enable=true
quarkus.log.file.path=logs/application.log
quarkus.log.file.level=DEBUG
quarkus.log.file.format=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n
quarkus.log.file.rotation.max-file-size=10M
quarkus.log.file.rotation.max-backup-index=10
# Syslog Configuration
quarkus.log.syslog.enable=false
quarkus.log.syslog.endpoint=localhost:514
quarkus.log.syslog.protocol=TCP
quarkus.log.syslog.app-name=quarkus-app
JSON Logging (Structured Logging)
properties
# JSON Logging Configuration quarkus.log.console.json=true quarkus.log.console.json.excluded-keys=hostName,processName quarkus.log.console.json.pretty-print=false # Custom JSON Fields quarkus.log.console.json.keys.timestamp=@timestamp quarkus.log.console.json.keys.logger=logger_name quarkus.log.console.json.keys.level=severity quarkus.log.console.json.keys.message=message # Additional MDC Fields quarkus.log.console.json.include-mdc=true quarkus.log.console.json.mdc-key-prefix=mdc. # Custom JSON Format quarkus.log.console.json.date-format=yyyy-MM-dd'T'HH:mm:ss.SSSZ quarkus.log.console.json.exception-output-type=detailed_and_formatted quarkus.log.console.json.print-details=true
GELF Logging (Graylog Extended Log Format)
properties
# GELF Logging Configuration quarkus.log.handler.gelf.enabled=true quarkus.log.handler.gelf.host=udp:localhost quarkus.log.handler.gelf.port=12201 quarkus.log.handler.gelf.version=1.1 # GELF Additional Fields quarkus.log.handler.gelf.include-full-mdc=true quarkus.log.handler.gelf.include-log-message=true quarkus.log.handler.gelf.include-message-parameters=true quarkus.log.handler.gelf.include-stack-trace=true # GELF Custom Fields quarkus.log.handler.gelf.additional-field.app-name.value=quarkus-app quarkus.log.handler.gelf.additional-field.environment.value=development quarkus.log.handler.gelf.additional-field.version.value=1.0.0 # GELF Network Configuration quarkus.log.handler.gelf.tcp-keep-alive=true quarkus.log.handler.gelf.connect-timeout=1000 quarkus.log.handler.gelf.reconnect-delay=500 quarkus.log.handler.gelf.retry-count=3
Profile-specific Logging
properties
# Development Logging
%dev.quarkus.log.level=DEBUG
%dev.quarkus.log.console.level=DEBUG
%dev.quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %s%e%n
%dev.quarkus.log.console.color=true
%dev.quarkus.log.file.enable=false
%dev.quarkus.log.handler.gelf.enabled=false
# Test Logging
%test.quarkus.log.level=INFO
%test.quarkus.log.console.level=INFO
%test.quarkus.log.file.enable=true
%test.quarkus.log.file.path=build/logs/test.log
%test.quarkus.log.handler.gelf.enabled=false
# Production Logging
%prod.quarkus.log.level=WARN
%prod.quarkus.log.console.level=WARN
%prod.quarkus.log.console.json=true
%prod.quarkus.log.file.enable=true
%prod.quarkus.log.file.path=/var/log/quarkus/app.log
%prod.quarkus.log.file.rotation.max-file-size=100M
%prod.quarkus.log.file.rotation.max-backup-index=50
%prod.quarkus.log.handler.gelf.enabled=true
Custom Logger Implementation
java
package com.example.logging;
import org.jboss.logging.Logger;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.util.HashMap;
import java.util.Map;
@ApplicationScoped
public class ApplicationLogger {
private final Logger logger;
@Inject
public ApplicationLogger() {
this.logger = Logger.getLogger(ApplicationLogger.class);
}
public void debug(String message) {
logger.debug(message);
}
public void info(String message) {
logger.info(message);
}
public void warn(String message) {
logger.warn(message);
}
public void error(String message) {
logger.error(message);
}
public void error(String message, Throwable throwable) {
logger.error(message, throwable);
}
// Structured logging methods
public void infoWithContext(String message, Map<String, Object> context) {
try (org.jboss.logging.MDCCloseable mdc = org.jboss.logging.MDC.putCloseable("context", context.toString())) {
logger.info(message);
}
}
public void auditLog(String action, String resource, String userId, Map<String, Object> details) {
Map<String, Object> auditContext = new HashMap<>();
auditContext.put("action", action);
auditContext.put("resource", resource);
auditContext.put("userId", userId);
auditContext.put("timestamp", java.time.Instant.now().toString());
auditContext.putAll(details);
try (org.jboss.logging.MDCCloseable mdc = org.jboss.logging.MDC.putCloseable("audit", auditContext.toString())) {
logger.infof("AUDIT: %s on %s by %s", action, resource, userId);
}
}
// Performance logging
public void logPerformance(String operation, long durationMs, Map<String, Object> metadata) {
Map<String, Object> perfContext = new HashMap<>();
perfContext.put("operation", operation);
perfContext.put("duration_ms", durationMs);
perfContext.put("threshold_warn", 1000); // 1 second
perfContext.put("threshold_error", 5000); // 5 seconds
perfContext.putAll(metadata);
try (org.jboss.logging.MDCCloseable mdc = org.jboss.logging.MDC.putCloseable("performance", perfContext.toString())) {
if (durationMs > 5000) {
logger.errorf("PERFORMANCE ERROR: %s took %d ms", operation, durationMs);
} else if (durationMs > 1000) {
logger.warnf("PERFORMANCE WARN: %s took %d ms", operation, durationMs);
} else {
logger.infof("PERFORMANCE: %s took %d ms", operation, durationMs);
}
}
}
}
// Usage in services
package com.example.service;
import com.example.logging.ApplicationLogger;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.util.HashMap;
import java.util.Map;
@ApplicationScoped
public class UserService {
@Inject
ApplicationLogger logger;
public void createUser(String username, String email) {
long startTime = System.currentTimeMillis();
try {
logger.info("Starting user creation");
Map<String, Object> context = new HashMap<>();
context.put("username", username);
context.put("email", email);
context.put("operation", "createUser");
logger.infoWithContext("Creating user", context);
// Business logic here
// ...
// Audit log
Map<String, Object> auditDetails = new HashMap<>();
auditDetails.put("email", email);
auditDetails.put("source", "web");
logger.auditLog("CREATE", "USER", "system", auditDetails);
} catch (Exception e) {
logger.error("Failed to create user: " + username, e);
throw e;
} finally {
long duration = System.currentTimeMillis() - startTime;
Map<String, Object> perfMetadata = new HashMap<>();
perfMetadata.put("username", username);
logger.logPerformance("createUser", duration, perfMetadata);
}
}
}
6. Secrets and Externalized Configuration
Environment Variables
properties
# Using environment variables in configuration
quarkus.datasource.username=${DB_USERNAME:quarkus_user}
quarkus.datasource.password=${DB_PASSWORD:quarkus_pass}
quarkus.datasource.jdbc.url=${DB_URL:jdbc:postgresql://localhost:5432/quarkusdb}
# JWT Secret from environment
app.security.jwt.secret=${JWT_SECRET:default-dev-secret}
# External API configuration
external.api.base-url=${API_BASE_URL:https://dev-api.example.com}
external.api.key=${API_KEY:dev-key}
# Feature flags from environment
app.feature.flags.new-dashboard=${FEATURE_NEW_DASHBOARD:false}
app.feature.flags.experimental-features=${FEATURE_EXPERIMENTAL:false}
.env File Support
bash
# .env file in project root DB_USERNAME=production_user DB_PASSWORD=super_secure_password DB_URL=jdbc:postgresql://prod-db:5432/production_db JWT_SECRET=very-long-and-secure-jwt-secret-key-here API_BASE_URL=https://api.production.com API_KEY=prod-api-key-12345 FEATURE_NEW_DASHBOARD=true FEATURE_EXPERIMENTAL=false LOG_LEVEL=WARN GRAYLOG_HOST=graylog.production.com
Kubernetes Secrets and ConfigMaps
properties
# Kubernetes configuration
quarkus.kubernetes-config.enabled=true
quarkus.kubernetes-config.config-maps=app-config
quarkus.kubernetes-config.secrets=app-secrets
quarkus.kubernetes-config.namespace=default
# Fallback to environment variables if not in Kubernetes
quarkus.datasource.username=${DB_USERNAME:${postgres.username:quarkus_user}}
quarkus.datasource.password=${DB_PASSWORD:${postgres.password:quarkus_pass}}
Vault Integration
properties
# HashiCorp Vault Configuration
quarkus.vault.url=https://vault.example.com:8200
quarkus.vault.authentication.client-token=${VAULT_TOKEN}
quarkus.vault.kv-secret-engine-mount-path=secret
quarkus.vault.kv-secret-engine-version=2
# Read secrets from Vault
quarkus.datasource.password=${vault:secret/data/database#data.password}
app.security.jwt.secret=${vault:secret/data/app#data.jwt_secret}
external.api.key=${vault:secret/data/external-api#data.api_key}
7. Runtime Configuration Updates
Dynamic Configuration
java
package com.example.config;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@ConfigMapping(prefix = "app")
public interface DynamicConfig {
FeatureFlags features();
interface FeatureFlags {
AtomicReference<Boolean> newDashboard();
AtomicReference<Boolean> advancedSearch();
AtomicReference<List<String>> enabledModules();
}
}
// Configuration Update Service
package com.example.service;
import com.example.config.DynamicConfig;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
import java.util.HashMap;
import java.util.Map;
@ApplicationScoped
public class DynamicConfigService {
@Inject
DynamicConfig dynamicConfig;
private final Config config = ConfigProvider.getConfig();
public void enableFeature(String featureName) {
switch (featureName) {
case "new-dashboard":
dynamicConfig.features().newDashboard().set(true);
break;
case "advanced-search":
dynamicConfig.features().advancedSearch().set(true);
break;
default:
throw new IllegalArgumentException("Unknown feature: " + featureName);
}
}
public void disableFeature(String featureName) {
switch (featureName) {
case "new-dashboard":
dynamicConfig.features().newDashboard().set(false);
break;
case "advanced-search":
dynamicConfig.features().advancedSearch().set(false);
break;
default:
throw new IllegalArgumentException("Unknown feature: " + featureName);
}
}
public Map<String, Object> getCurrentConfig() {
Map<String, Object> configMap = new HashMap<>();
configMap.put("new-dashboard", dynamicConfig.features().newDashboard().get());
configMap.put("advanced-search", dynamicConfig.features().advancedSearch().get());
configMap.put("enabled-modules", dynamicConfig.features().enabledModules().get());
// Add some static config values
configMap.put("app-name", config.getValue("app.name", String.class));
configMap.put("app-version", config.getValue("app.version", String.class));
return configMap;
}
}
8. Complete Configuration Example
Final application.properties
properties
# ===== APPLICATION CONFIGURATION =====
quarkus.application.name=quarkus-config-demo
quarkus.application.version=1.0.0
# ===== SERVER CONFIGURATION =====
quarkus.http.port=8080
quarkus.http.host=0.0.0.0
quarkus.http.ssl-port=8443
quarkus.http.cors=true
# ===== DATABASE CONFIGURATION =====
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=${DB_USERNAME:quarkus_user}
quarkus.datasource.password=${DB_PASSWORD:quarkus_pass}
quarkus.datasource.jdbc.url=${DB_URL:jdbc:postgresql://localhost:5432/quarkusdb}
quarkus.datasource.jdbc.max-size=20
quarkus.datasource.jdbc.min-size=5
quarkus.hibernate-orm.database.generation=update
quarkus.hibernate-orm.log.sql=true
# ===== LOGGING CONFIGURATION =====
quarkus.log.level=INFO
quarkus.log.console.enable=true
quarkus.log.console.format=%d{yyyy-MM-dd HH:mm:ss} %-5p [%c{3.}] (%t) %s%e%n
quarkus.log.file.enable=true
quarkus.log.file.path=logs/app.log
# ===== CUSTOM APPLICATION CONFIG =====
app.name=Quarkus Configuration Demo
app.version=1.0.0
app.security.jwt.secret=${JWT_SECRET:dev-secret-key}
app.security.jwt.expiration=3600
app.upload.max-file-size=10485760
app.upload.allowed-extensions=jpg,jpeg,png,pdf
app.external.api.base-url=${API_BASE_URL:https://dev-api.example.com}
app.external.api.timeout=5000
# ===== PROFILE CONFIGURATIONS =====
# Development Profile
%dev.quarkus.log.level=DEBUG
%dev.quarkus.datasource.db-kind=h2
%dev.quarkus.datasource.jdbc.url=jdbc:h2:mem:devdb
%dev.quarkus.hibernate-orm.database.generation=drop-and-create
%dev.app.security.jwt.secret=dev-only-secret-key
# Test Profile
%test.quarkus.log.level=INFO
%test.quarkus.datasource.db-kind=h2
%test.quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb
%test.quarkus.hibernate-orm.database.generation=drop-and-create
# Production Profile
%prod.quarkus.log.level=WARN
%prod.quarkus.log.console.json=true
%prod.quarkus.log.handler.gelf.enabled=true
%prod.quarkus.log.handler.gelf.host=graylog.prod.com
%prod.app.security.jwt.secret=${JWT_SECRET}
# Staging Profile
%staging.quarkus.log.level=INFO
%staging.quarkus.log.console.json=true
%staging.app.security.jwt.secret=${JWT_SECRET:staging-secret}
This extensive guide covers all aspects of configuration, logging, and profiles in Quarkus, providing you with the tools to manage your application's configuration effectively across different environments while maintaining security and best practices.
Comments (0)
No comments yet. Be the first to comment!