I would really like to use YAML config for Spring Boot, as I find it quite readable and useful to have a single file showing what properties are active in my different profiles. Unfortunately, I'm finding that setting properties in application.yml
can be rather fragile.
Things like using a tab instead of spaces will cause properties to not exist (without warnings as far as I can see), and all too often I find that my active profiles are not being set, due to some unknown issue with my YAML.
So I was wondering whether there are any hooks that would enable me to get hold of the currently active profiles and properties, so that I could log them.
Similarly, is there a way to cause start-up to fail if the application.yml
contains errors? Either that or a means for me to validate the YAML myself, so that I could kill the start-up process.
To make Spring Boot write its log to disk, set the path and filename. With this configuration, Spring Boot will write to the console and also to a log file called spring. log , at the path you specify.
By default Spring Boot does not output logs to any file. If you want to have logs written in a file (in addition to the console output) then you should use either of logging. file or logging. path properties (not both).
To see all properties in your Spring Boot application, enable the Actuator endpoint called env . This enables an HTTP endpoint which shows all the properties of your application's environment. You can do this by setting the property management.
Spring Boot lets you externalize your configuration so that you can work with the same application code in different environments. You can use properties files, YAML files, environment variables, and command-line arguments to externalize configuration.
In addition to other answers: logging active properties on context refreshed event.
Java 8
package mypackage; import lombok.extern.slf4j.Slf4j; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.EventListener; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collection; import java.util.List; @Slf4j @Component public class AppContextEventListener { @EventListener public void handleContextRefreshed(ContextRefreshedEvent event) { printActiveProperties((ConfigurableEnvironment) event.getApplicationContext().getEnvironment()); } private void printActiveProperties(ConfigurableEnvironment env) { System.out.println("************************* ACTIVE APP PROPERTIES ******************************"); List<MapPropertySource> propertySources = new ArrayList<>(); env.getPropertySources().forEach(it -> { if (it instanceof MapPropertySource && it.getName().contains("applicationConfig")) { propertySources.add((MapPropertySource) it); } }); propertySources.stream() .map(propertySource -> propertySource.getSource().keySet()) .flatMap(Collection::stream) .distinct() .sorted() .forEach(key -> { try { System.out.println(key + "=" + env.getProperty(key)); } catch (Exception e) { log.warn("{} -> {}", key, e.getMessage()); } }); System.out.println("******************************************************************************"); } }
Kotlin
package mypackage import mu.KLogging import org.springframework.context.event.ContextRefreshedEvent import org.springframework.context.event.EventListener import org.springframework.core.env.ConfigurableEnvironment import org.springframework.core.env.MapPropertySource import org.springframework.stereotype.Component @Component class AppContextEventListener { companion object : KLogging() @EventListener fun handleContextRefreshed(event: ContextRefreshedEvent) { printActiveProperties(event.applicationContext.environment as ConfigurableEnvironment) } fun printActiveProperties(env: ConfigurableEnvironment) { println("************************* ACTIVE APP PROPERTIES ******************************") env.propertySources .filter { it.name.contains("applicationConfig") } .map { it as EnumerablePropertySource<*> } .map { it -> it.propertyNames.toList() } .flatMap { it } .distinctBy { it } .sortedBy { it } .forEach { it -> try { println("$it=${env.getProperty(it)}") } catch (e: Exception) { logger.warn("$it -> ${e.message}") } } println("******************************************************************************") } }
Output like:
************************* ACTIVE APP PROPERTIES ****************************** server.port=3000 spring.application.name=my-app ... 2017-12-29 13:13:32.843 WARN 36252 --- [ main] m.AppContextEventListener : spring.boot.admin.client.service-url -> Could not resolve placeholder 'management.address' in value "http://${management.address}:${server.port}" ... spring.datasource.password= spring.datasource.url=jdbc:postgresql://localhost/my_db?currentSchema=public spring.datasource.username=db_user ... ******************************************************************************
I had the same problem, and wish there was a debug flag that would tell the profile processing system to spit out some useful logging. One possible way of doing it would be to register an event listener for your application context, and print out the profiles from the environment. I haven't tried doing it this way myself, so your mileage may vary. I think maybe something like what's outlined here:
How to add a hook to the application context initialization event?
Then you'd do something like this in your listener:
System.out.println("Active profiles: " + Arrays.toString(ctxt.getEnvironment().getActiveProfiles()));
Might be worth a try. Another way you could probably do it would be to declare the Environment to be injected in the code where you need to print the profiles. I.e.:
@Component public class SomeClass { @Autowired private Environment env; ... private void dumpProfiles() { // Print whatever needed from env here } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With