Skip to main content

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):

  1. file:./config/application.properties
  2. file:./config/application.yml
  3. file:./application.properties
  4. file:./application.yml
  5. classpath:/config/application.properties
  6. classpath:/config/application.yml
  7. classpath:/application.properties
  8. classpath:/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​

Criterionpropertiesyml
Readability⭐⭐⭐⭐⭐⭐⭐⭐
Simplicity⭐⭐⭐⭐⭐⭐⭐⭐
StructureFlatHierarchical
RepetitionHighLow
ListsDifficultEasy
CompatibilityUniversalRequires parser
ErrorsRareIndentation

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:

ValueDescriptionUsage
noneNo actionProduction
validateValidate schema onlyProduction
updateUpdate schemaDevelopment
createCreate schema at startupTests
create-dropCreate then dropTests

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:

  1. Create a Spring Boot project
  2. In application.properties, configure:
    • Port: 8081
    • Name: "My Greeting App"
  3. Start the application
  4. 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:

  1. Add to application.yml:
    app:
    welcome-message: Welcome!
    max-users: 100
  2. Create a controller that displays these values
  3. Test

Exercise 4: Profiles​

Objective: Create dev and prod profiles

Instructions:

  1. Create application-dev.yml:
    • Port: 8080
    • Logs: DEBUG
  2. Create application-prod.yml:
    • Port: 80
    • Logs: WARN
  3. Test activating each profile

Review Questions​

  1. What is the difference between application.properties and application.yml?

  2. How do you activate a Spring Boot profile?

  3. What is the priority order of configuration files?

  4. How do you inject a custom property into a class?

  5. Which annotation is used for a configuration class with multiple properties?

  6. How do you use an environment variable in application.yml?

  7. What are the possible values for spring.jpa.hibernate.ddl-auto?

  8. Why should you never commit passwords in application.properties?


Chapter Summary​

Key Points​

  • Spring Boot supports .properties and .yml
  • .yml is more readable for complex structures
  • Profiles allow for environment-specific configurations
  • @Value for one property, @ConfigurationProperties for 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:

Chapter 4: Basic Annotations

  • @SpringBootApplication
  • @RestController vs @Controller
  • @GetMapping, @PostMapping, etc.
  • @Autowired and dependency injection
  • @Component, @Service, @Repository

Back to Module 2