Chapter 3: Configuration with application.properties and application.yml
Introduction
Configuration is a fundamental aspect of any application. Spring Boot offers a powerful and flexible configuration system that allows you to customize the application's behavior without modifying the code.
Chapter Objectives
By the end of this chapter, you will be able to:
- Configure an application with application.properties and application.yml
- Use predefined Spring Boot properties
- Create custom properties
- Manage different environments with profiles
- Externalize configuration
Configuration Files
Location
Spring Boot searches for configuration files in this order:
Priority order (from highest to lowest):
file:./config/application.propertiesfile:./config/application.ymlfile:./application.propertiesfile:./application.ymlclasspath:/config/application.propertiesclasspath:/config/application.ymlclasspath:/application.propertiesclasspath:/application.yml
In practice: Place your files in src/main/resources/
application.properties Format
Basic Syntax
Format:
key=value
Characteristics:
- Simple key-value format
- No indentation
- Comments with
# - Repetition of prefixes
Complete Example
# Server configuration
server.port=8080
server.servlet.context-path=/api
# Application name
spring.application.name=greeting-app
# Database configuration
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=postgres
spring.datasource.password=secret
spring.datasource.driver-class-name=org.postgresql.Driver
# JPA configuration
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
# Logging configuration
logging.level.root=INFO
logging.level.com.example=DEBUG
logging.level.org.springframework.web=DEBUG
logging.file.name=logs/application.log
# Jackson configuration (JSON)
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=America/Montreal
spring.jackson.serialization.indent-output=true
Advantages and Disadvantages
Advantages:
- Simple and widely known format
- Compatible with Java Properties
- No external dependency
Disadvantages:
- Repetitive for hierarchical structures
- Less readable for complex configurations
application.yml Format
Basic Syntax
Format: YAML (YAML Ain't Markup Language)
Characteristics:
- Hierarchical format with indentation
- Indentation = 2 or 4 spaces (NO tabs)
- Tree structure
- More concise
Complete Example
# Server configuration
server:
port: 8080
servlet:
context-path: /api
# Application name
spring:
application:
name: greeting-app
# Database configuration
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: postgres
password: secret
driver-class-name: org.postgresql.Driver
# JPA configuration
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.PostgreSQLDialect
# Jackson configuration
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: America/Montreal
serialization:
indent-output: true
# Logging configuration
logging:
level:
root: INFO
com.example: DEBUG
org.springframework.web: DEBUG
file:
name: logs/application.log
Advantages and Disadvantages
Advantages:
- More readable for complex structures
- Less repetition
- Support for lists and maps
- Modern format
Disadvantages:
- Sensitive to indentation
- More frequent syntax errors
- Requires SnakeYAML dependency (included by default)
properties vs yml Comparison
Same Configuration in Both Formats
application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=postgres
spring.datasource.password=secret
application.yml:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: postgres
password: secret
Comparison Table
| Criterion | properties | yml |
|---|---|---|
| Readability | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Simplicity | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| Structure | Flat | Hierarchical |
| Repetition | High | Low |
| Lists | Difficult | Easy |
| Compatibility | Universal | Requires parser |
| Errors | Rare | Indentation |
Recommendation: Use .yml for complex configurations, .properties for simple configurations.
Common Spring Boot Properties
1. Server Configuration
server:
port: 8080 # Server port
servlet:
context-path: /api # Base path
compression:
enabled: true # GZIP compression
error:
include-message: always # Include error messages
2. Database Configuration
PostgreSQL
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: postgres
password: secret
driver-class-name: org.postgresql.Driver
MySQL
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: secret
driver-class-name: com.mysql.cj.jdbc.Driver
H2 (In-memory Database - Tests)
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
h2:
console:
enabled: true # H2 console accessible
path: /h2-console
3. JPA/Hibernate Configuration
spring:
jpa:
hibernate:
ddl-auto: update # none, validate, update, create, create-drop
show-sql: true # Show SQL queries
properties:
hibernate:
format_sql: true # Format queries
dialect: org.hibernate.dialect.PostgreSQLDialect
use_sql_comments: true # Comment queries
ddl-auto Values:
| Value | Description | Usage |
|---|---|---|
| none | No action | Production |
| validate | Validate schema only | Production |
| update | Update schema | Development |
| create | Create schema at startup | Tests |
| create-drop | Create then drop | Tests |
4. Logging Configuration
logging:
level:
root: INFO # Global level
com.example: DEBUG # Your application
org.springframework.web: DEBUG # Spring Web
org.hibernate.SQL: DEBUG # SQL queries
org.hibernate.type: TRACE # SQL parameters
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss} - %msg%n'
file:
name: logs/application.log # Log file
max-size: 10MB # Max size per file
Log Levels:
TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
5. Jackson Configuration (JSON)
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: America/Montreal
serialization:
indent-output: true # Indented JSON
write-dates-as-timestamps: false
deserialization:
fail-on-unknown-properties: false
6. DevTools Configuration
spring:
devtools:
restart:
enabled: true # Automatic restart
livereload:
enabled: true # Browser reload
Custom Properties
Creating Custom Properties
application.yml:
app:
name: Greeting Application
version: 1.0.0
admin:
email: admin@example.com
phone: +1-514-123-4567
security:
jwt-secret: mySecretKey123
jwt-expiration: 86400000 # 24 hours in ms
Injection with @Value
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class AppConfig {
@Value("${app.name}")
private String appName;
@Value("${app.version}")
private String appVersion;
@Value("${app.admin.email}")
private String adminEmail;
public void printConfig() {
System.out.println("Application: " + appName);
System.out.println("Version: " + appVersion);
System.out.println("Admin Email: " + adminEmail);
}
}
Configuration Class with @ConfigurationProperties
Recommended approach for multiple properties:
application.yml:
app:
security:
jwt-secret: mySecretKey123
jwt-expiration: 86400000
allowed-origins:
- http://localhost:3000
- http://localhost:4200
Configuration class:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@ConfigurationProperties(prefix = "app.security")
public class SecurityProperties {
private String jwtSecret;
private Long jwtExpiration;
private List<String> allowedOrigins;
// Getters and Setters
public String getJwtSecret() {
return jwtSecret;
}
public void setJwtSecret(String jwtSecret) {
this.jwtSecret = jwtSecret;
}
public Long getJwtExpiration() {
return jwtExpiration;
}
public void setJwtExpiration(Long jwtExpiration) {
this.jwtExpiration = jwtExpiration;
}
public List<String> getAllowedOrigins() {
return allowedOrigins;
}
public void setAllowedOrigins(List<String> allowedOrigins) {
this.allowedOrigins = allowedOrigins;
}
}
Usage:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AuthService {
@Autowired
private SecurityProperties securityProperties;
public void generateToken() {
String secret = securityProperties.getJwtSecret();
Long expiration = securityProperties.getJwtExpiration();
// Token generation logic
}
}
Profile Management
Profile Concept
Profiles allow for different configurations depending on the environment.
Creating Profiles
File structure:
src/main/resources/
├── application.yml # Common configuration
├── application-dev.yml # Development
├── application-test.yml # Tests
└── application-prod.yml # Production
Profile Configuration
application.yml (common):
spring:
application:
name: greeting-app
app:
name: Greeting Application
application-dev.yml:
server:
port: 8080
spring:
datasource:
url: jdbc:h2:mem:testdb
h2:
console:
enabled: true
logging:
level:
root: DEBUG
application-test.yml:
server:
port: 8081
spring:
datasource:
url: jdbc:h2:mem:testdb
logging:
level:
root: INFO
application-prod.yml:
server:
port: 80
spring:
datasource:
url: jdbc:postgresql://prod-db.example.com:5432/mydb
username: ${DB_USERNAME} # Environment variable
password: ${DB_PASSWORD}
logging:
level:
root: WARN
file:
name: /var/log/app/application.log
Activating a Profile
Method 1: In application.yml
spring:
profiles:
active: dev
Method 2: Command line
java -jar app.jar --spring.profiles.active=prod
Method 3: Environment variable
export SPRING_PROFILES_ACTIVE=prod
java -jar app.jar
Method 4: In the IDE
VS Code (launch.json):
{
"configurations": [
{
"type": "java",
"name": "Spring Boot App",
"request": "launch",
"mainClass": "com.example.greeting.GreetingApplication",
"args": "--spring.profiles.active=dev"
}
]
}
Multiple Profiles
You can activate multiple profiles:
java -jar app.jar --spring.profiles.active=dev,local
Priority order: The last profile has priority
Environment Variables
Usage
Spring Boot can read environment variables:
application.yml:
spring:
datasource:
url: ${DATABASE_URL:jdbc:postgresql://localhost:5432/mydb}
username: ${DATABASE_USER:postgres}
password: ${DATABASE_PASSWORD:secret}
Syntax: ${VARIABLE_NAME:default_value}
Setting Variables
Windows (CMD):
set DATABASE_URL=jdbc:postgresql://prod-server:5432/mydb
set DATABASE_USER=admin
set DATABASE_PASSWORD=supersecret
java -jar app.jar
Windows (PowerShell):
$env:DATABASE_URL="jdbc:postgresql://prod-server:5432/mydb"
$env:DATABASE_USER="admin"
$env:DATABASE_PASSWORD="supersecret"
java -jar app.jar
Linux/macOS:
export DATABASE_URL=jdbc:postgresql://prod-server:5432/mydb
export DATABASE_USER=admin
export DATABASE_PASSWORD=supersecret
java -jar app.jar
Externalized Configuration
External Configuration File
Spring Boot can load external configuration files:
Structure:
/opt/app/
├── app.jar
└── config/
└── application.yml
Launch:
java -jar /opt/app/app.jar
Spring Boot will automatically find /opt/app/config/application.yml
Specifying a File
java -jar app.jar --spring.config.location=file:/path/to/config/
Sensitive Properties
Securing Passwords
Bad practice:
spring:
datasource:
password: supersecret123 # ❌ Plain text password
Best practices:
1. Environment variables:
spring:
datasource:
password: ${DATABASE_PASSWORD} # ✅ Environment variable
2. Spring Cloud Config Server:
- Centralize configuration
- Encrypt sensitive properties
3. HashiCorp Vault:
- Professional secret management
4. .env files (development only):
DATABASE_PASSWORD=secret
Important: NEVER commit passwords to Git!
Practical Exercises
Exercise 1: Basic Configuration
Objective: Configure the port and application name
Instructions:
- Create a Spring Boot project
- In
application.properties, configure:- Port: 8081
- Name: "My Greeting App"
- Start the application
- Verify that the server starts on port 8081
Exercise 2: Convert properties → yml
Objective: Convert a properties file to yml
Given properties file:
server.port=8080
spring.application.name=user-service
spring.datasource.url=jdbc:postgresql://localhost:5432/users
spring.datasource.username=admin
spring.jpa.show-sql=true
Task: Convert to YAML format
Exercise 3: Custom Properties
Objective: Create and use custom properties
Instructions:
- Add to
application.yml:app:
welcome-message: Welcome!
max-users: 100 - Create a controller that displays these values
- Test
Exercise 4: Profiles
Objective: Create dev and prod profiles
Instructions:
- Create
application-dev.yml:- Port: 8080
- Logs: DEBUG
- Create
application-prod.yml:- Port: 80
- Logs: WARN
- Test activating each profile
Review Questions
-
What is the difference between application.properties and application.yml?
-
How do you activate a Spring Boot profile?
-
What is the priority order of configuration files?
-
How do you inject a custom property into a class?
-
Which annotation is used for a configuration class with multiple properties?
-
How do you use an environment variable in application.yml?
-
What are the possible values for
spring.jpa.hibernate.ddl-auto? -
Why should you never commit passwords in application.properties?
Chapter Summary
Key Points
- Spring Boot supports
.propertiesand.yml .ymlis more readable for complex structures- Profiles allow for environment-specific configurations
@Valuefor one property,@ConfigurationPropertiesfor multiple- Use environment variables for sensitive data
- Never commit passwords
Best Practices
- Use profiles for each environment
- Externalize sensitive configurations
- Document custom properties
- Provide default values
- Use descriptive property names
- Separate common and specific configuration
Next Steps
In the next chapter, we will study:
- @SpringBootApplication
- @RestController vs @Controller
- @GetMapping, @PostMapping, etc.
- @Autowired and dependency injection
- @Component, @Service, @Repository