application.properties and application.yaml

Where Spring Boot looks for its settings file, how properties and YAML map to the same keys, and which format to pick.

Syntax# application.properties key.sub-key=value # application.yaml key: sub-key: value

Every Spring Boot application reads a settings file at startup. By default it is src/main/resources/application.properties, which ends up at the root of the classpath inside your JAR. Starters read their settings from it (server.port, spring.datasource.url) and your own code can read keys you invent, such as app.orders.page-size.

Two formats, one set of keys

A .properties file is a flat list of key=value lines. A .yaml (or .yml) file expresses the same keys as nested maps. Both end up as the same flat names in the Environment, so server.port=8081 and the YAML below are interchangeable:

server:
  port: 8081

Pick one format per project and stick to it. If both files sit in the same location, Boot loads both and the .properties values win, which makes a setting look ignored when it is really being overridden by the other file.

Where Boot looks

Boot checks four places, and later ones override earlier ones: the classpath root, a config/ package on the classpath, the current working directory, and a config/ folder in the working directory (plus its immediate subfolders). That last pair is what makes the packaged defaults overridable on a server: drop an application.properties next to the JAR and its values replace the ones inside it, with no rebuild.

Choosing between them

  • Properties are hard to get wrong. Every line is self-contained and a search for spring.datasource.url finds it.
  • YAML reads better once keys are deeply nested or you have lists, and it can hold several documents in one file separated by ---. Indentation is meaningful: two spaces too many silently moves a key under a different parent.

YAML has two quirks worth knowing. Unquoted values such as on, off, yes and no may be read as booleans, so a String field ends up holding true. Quote any value that is meant to be a string. Also, @PropertySource cannot load YAML files; it only reads properties files.

Mistakes that cost time

Putting the file in src/main/java instead of src/main/resources means it never reaches the classpath. Typing application.yaml as applicaton.yaml fails silently, because a missing file is not an error. When a value does not take effect, check the /actuator/env endpoint (if you expose it) to see which source a value actually came from.

Use kebab-case for your own keys (page-size, not pageSize). It is the canonical form Spring Boot documents, it binds to camelCase fields, and it is the form that maps cleanly to environment variables later.

Example

Example · properties
# src/main/resources/application.properties
spring.application.name=orders-api
server.port=8080
server.servlet.context-path=/api

spring.datasource.url=jdbc:postgresql://localhost:5432/orders
spring.datasource.username=orders
spring.datasource.password=${DB_PASSWORD}
spring.jpa.open-in-view=false

logging.level.root=INFO
logging.level.com.example.orders=DEBUG

# Keys you define yourself live under your own prefix.
app.orders.page-size=50
app.orders.max-items-per-order=100

When to use it

  • Setting the server port, context path and application name for a new REST API in one file checked into the repository.
  • Keeping a team's database URL and logging levels for local development in the packaged file while operations override them with a file next to the JAR.
  • Converting a long, deeply nested properties file to YAML so related settings for the datasource, JPA and caching sit together.

More examples

The same settings in YAML

Each nesting level adds one segment to the key, so `spring:` / `datasource:` / `url:` becomes `spring.datasource.url`. Logger names under `logging.level` keep their dots as a single key. The `${DB_PASSWORD}` placeholder is resolved from the environment at startup, so the password is never in the file. Choose this format when the file grows past a screenful and the nesting helps people find related settings.

Example · yaml
# src/main/resources/application.yaml
spring:
  application:
    name: orders-api
  datasource:
    url: jdbc:postgresql://localhost:5432/orders
    username: orders
    password: ${DB_PASSWORD}
  jpa:
    open-in-view: false

server:
  port: 8080
  servlet:
    context-path: /api

logging:
  level:
    root: INFO
    com.example.orders: DEBUG

app:
  orders:
    page-size: 50
    max-items-per-order: 100

Reading a value from the Environment

`Environment` is the merged view of every property source Boot loaded, whichever file format it came from. `getRequiredProperty` throws `IllegalStateException` when the key is missing, which is better than a null discovered at the first request. For anything beyond one or two keys, prefer `@ConfigurationProperties`, covered later in this category; reading the `Environment` directly is mostly for framework code and one-off checks.

Example · java
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
public class StartupSummary {

    private final String appName;
    private final int pageSize;

    public StartupSummary(Environment env) {
        // Fails fast with a clear message if the key is missing.
        this.appName = env.getRequiredProperty("spring.application.name");
        // Falls back to 20 if the key is absent; converts the String to an int.
        this.pageSize = env.getProperty("app.orders.page-size", Integer.class, 20);
    }

    public String describe() {
        return appName + " serving pages of " + pageSize;
    }
}

Overriding the packaged file on a server

Boot resolves `config/` relative to the working directory, not to the JAR, so `cd` into the folder first or the override file is never found. `spring.config.additional-location` adds a location on top of the defaults; `spring.config.location` replaces the defaults entirely, which is a common way to lose every packaged setting by accident.

Example · bash
# Layout on the server
#   /opt/orders/orders-api.jar          (contains application.properties)
#   /opt/orders/config/application.properties   (only the values that differ)

cat /opt/orders/config/application.properties
# server.port=9090
# logging.level.root=WARN

cd /opt/orders
java -jar orders-api.jar
# Starts on 9090: ./config/application.properties overrides the copy inside the JAR.

# Point at a file somewhere else, keeping the defaults as well
java -jar orders-api.jar --spring.config.additional-location=file:/etc/orders/

Discussion

  • Be the first to comment on this lesson.