Spring Boot
System Properties
Configuration Files
Application Properties
Java Development

Can I define System Properties within Spring Boot configuration files?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Spring Boot configuration properties (application.properties / application.yml) are not Java system properties by default. They live in Spring's Environment abstraction and are accessible via @Value and @ConfigurationProperties, but System.getProperty() does not see them. To set actual JVM system properties, pass them as -D flags on the command line, use a @PostConstruct method to call System.setProperty(), or use SpringApplication.setDefaultProperties(). Some libraries read only from System.getProperty(), requiring you to bridge Spring properties into system properties.

Spring Properties vs System Properties

properties
# application.properties
app.name=MyApp
server.port=8080
java
1import org.springframework.beans.factory.annotation.Value;
2import org.springframework.stereotype.Component;
3
4@Component
5public class AppConfig {
6    @Value("${app.name}")
7    private String appName;  // Works — Spring resolves it
8
9    public void check() {
10        System.out.println(appName);                          // "MyApp"
11        System.out.println(System.getProperty("app.name"));   // null!
12    }
13}

Spring properties are not JVM system properties. @Value reads from Spring's Environment. System.getProperty() reads from the JVM's system properties map — a different store.

Setting System Properties via Command Line

bash
1# -D flags set JVM system properties before Spring starts
2java -Dapp.name=MyApp -Dserver.port=8080 -jar app.jar
3
4# These are available to both Spring AND System.getProperty()
java
System.getProperty("app.name");   // "MyApp"
// Also accessible via @Value("${app.name}")

JVM system properties set with -D are in both the JVM properties map and Spring's Environment (Spring reads system properties as a property source).

Bridging Spring Properties to System Properties

java
1import org.springframework.beans.factory.annotation.Value;
2import org.springframework.stereotype.Component;
3import javax.annotation.PostConstruct;
4
5@Component
6public class SystemPropertyBridge {
7
8    @Value("${javax.net.ssl.trustStore:}")
9    private String trustStore;
10
11    @Value("${javax.net.ssl.trustStorePassword:}")
12    private String trustStorePassword;
13
14    @PostConstruct
15    public void init() {
16        if (!trustStore.isEmpty()) {
17            System.setProperty("javax.net.ssl.trustStore", trustStore);
18        }
19        if (!trustStorePassword.isEmpty()) {
20            System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
21        }
22    }
23}
properties
# application.properties
javax.net.ssl.trustStore=/path/to/truststore.jks
javax.net.ssl.trustStorePassword=changeit

This pattern is useful when third-party libraries (like JDBC drivers or SSL subsystems) read configuration from System.getProperty() rather than Spring's Environment.

Using EnvironmentPostProcessor

For properties that must be set as system properties before any beans are created:

java
1import org.springframework.boot.SpringApplication;
2import org.springframework.boot.env.EnvironmentPostProcessor;
3import org.springframework.core.env.ConfigurableEnvironment;
4
5public class SystemPropertyPostProcessor implements EnvironmentPostProcessor {
6
7    private static final String[] PROPERTIES_TO_BRIDGE = {
8        "javax.net.ssl.trustStore",
9        "javax.net.ssl.trustStorePassword",
10        "com.sun.jndi.ldap.connect.timeout"
11    };
12
13    @Override
14    public void postProcessEnvironment(ConfigurableEnvironment environment,
15                                        SpringApplication application) {
16        for (String prop : PROPERTIES_TO_BRIDGE) {
17            String value = environment.getProperty(prop);
18            if (value != null) {
19                System.setProperty(prop, value);
20            }
21        }
22    }
23}
 
# META-INF/spring.factories
org.springframework.boot.env.EnvironmentPostProcessor=\
  com.example.SystemPropertyPostProcessor

Using SpringApplication.setDefaultProperties

java
1import org.springframework.boot.SpringApplication;
2import org.springframework.boot.autoconfigure.SpringBootApplication;
3import java.util.Map;
4
5@SpringBootApplication
6public class MyApp {
7    public static void main(String[] args) {
8        SpringApplication app = new SpringApplication(MyApp.class);
9        app.setDefaultProperties(Map.of(
10            "server.port", "9090",
11            "spring.jpa.open-in-view", "false"
12        ));
13        app.run(args);
14    }
15}

Default properties have the lowest precedence — command-line arguments and application.properties override them.

Property Source Precedence

 
1Spring Boot property source priority (highest to lowest):
21. Command line arguments (--server.port=8080)
32. JNDI attributes
43. Java System properties (-Dserver.port=8080)
54. OS environment variables (SERVER_PORT=8080)
65. Profile-specific properties (application-dev.properties)
76. application.properties / application.yml
87. @PropertySource annotations
98. SpringApplication.setDefaultProperties()
java
1// Check where a property comes from
2@Autowired
3private ConfigurableEnvironment env;
4
5public void debugProperty(String key) {
6    for (PropertySource<?> ps : env.getPropertySources()) {
7        if (ps.containsProperty(key)) {
8            System.out.printf("'%s' found in: %s = %s%n",
9                key, ps.getName(), ps.getProperty(key));
10        }
11    }
12}

Common Pitfalls

  • Expecting application.properties values to appear in System.getProperty(): Spring properties and JVM system properties are different stores. Properties defined in application.properties are only in Spring's Environment. Use @Value or Environment.getProperty() for Spring properties, or bridge them with System.setProperty() if a library requires JVM system properties.
  • Setting system properties too late for SSL/JNDI initialization: Some JVM subsystems (SSL, JNDI, security managers) read system properties during class loading, before Spring beans are created. A @PostConstruct bridge may be too late. Use an EnvironmentPostProcessor or set the properties in main() before calling SpringApplication.run().
  • Overriding system properties with application.properties unintentionally: If you set -Dserver.port=8080 on the command line and also have server.port=9090 in application.properties, the command-line value wins (higher precedence). But if you call System.setProperty() in @PostConstruct, it overwrites the JVM property regardless of precedence.
  • Relaxed binding not working with System.getProperty(): Spring's relaxed binding converts app-name to appName and APP_NAME. System.getProperty() does exact string matching — System.getProperty("app-name") returns null if the property was set as appName. Use the exact key string when reading from system properties.
  • Secrets appearing in /actuator/env: Spring Boot Actuator's /env endpoint displays all properties including those set via System.setProperty(). Sensitive values (passwords, API keys) are exposed unless you configure management.endpoint.env.keys-to-sanitize to mask them. Add patterns like .*password.*, .*secret.*, .*key.* to the sanitization list.

Summary

  • application.properties values are Spring Environment properties, not JVM system properties
  • Use -D flags for properties that must be both Spring and JVM system properties
  • Bridge Spring properties to system properties with System.setProperty() in @PostConstruct or EnvironmentPostProcessor
  • Use EnvironmentPostProcessor for properties needed before bean creation (SSL, JNDI)
  • Remember the property source precedence: command line > system properties > env vars > application.properties

Course illustration
Course illustration

All Rights Reserved.