2014-06-27 6 views
10

Bardzo chciałbym użyć konfiguracji YAML do Spring Boot, ponieważ uważam ją za całkiem czytelną i użyteczną, aby mieć pojedynczy plik pokazujący, które właściwości są aktywne w moich różnych profilach. Niestety, stwierdzam, że właściwości ustawień w application.yml mogą być raczej kruche.Jak zalogować aktywną konfigurację w aplikacji Spring Boot?

Rzeczy takie jak użycie tabulatora zamiast spacji spowodują, że właściwości nie istnieją (bez ostrzeżenia o ile widzę) i zbyt często stwierdzam, że moje aktywne profile nie są ustawione, z powodu jakiegoś nieznanego problemu z mój YAML.

Więc zastanawiałem się, czy są jakieś haki, które pozwoliłyby mi uzyskać dostęp do aktualnie aktywnych profili i właściwości, dzięki czemu mogłem je rejestrować.

Czy istnieje sposób, aby spowodować niepowodzenie rozruchu, jeśli błąd zawiera błędy application.yml? Albo to, albo sposób, aby samemu sprawdzić walidację YAML, aby móc zabić proces rozruchu.

Odpowiedz

4

Miałem ten sam problem i żałowałem, że nie ma flagi debugowania, która wskazywałaby systemowi przetwarzania profilu, aby wypluł pewne przydatne rejestrowanie. Jednym z możliwych sposobów jest zarejestrowanie detektora zdarzeń dla kontekstu aplikacji i wydrukowanie profili ze środowiska. Nie próbowałem robić tego w ten sposób, więc twój przebieg może się różnić. Myślę, że coś, co opisano tutaj:

How to add a hook to the application context initialization event?

Potem można zrobić coś takiego w swoim słuchacza:

System.out.println("Active profiles: " + Arrays.toString(ctxt.getEnvironment().getActiveProfiles())); 

Może warto spróbować. Innym sposobem, w jaki mógłbyś to zrobić, byłoby zadeklarowanie środowiska, które ma zostać wstrzyknięte w kod, w którym chcesz wydrukować profile. Np .:

@Component 
public class SomeClass { 
    @Autowired 
    private Environment env; 
    ... 
    private void dumpProfiles() { 
    // Print whatever needed from env here 
    } 
} 
+0

I przyjął podejście zalogowaniu wyniki 'getEnvironment() getActiveProfiles()', jak część logowania startowego w mojej aplikacji 'główna' metoda. – Steve

2

Jeśli application.yml zawiera błędy, spowoduje to awarię podczas uruchamiania. Myślę, że to zależy od tego, co masz na myśli przez "błąd". Z pewnością zawiedzie, jeśli YAML nie jest dobrze uformowany. Również jeśli ustawisz @ConfigurationProperties, które są na przykład oznaczone jako ignoreInvalidFields=true lub jeśli ustawisz wartość, której nie można przekonwertować. To dość szeroka gama błędów.

aktywne profile prawdopodobnie będzie zalogowany na starcie przez wdrożenie Environment (ale w każdym razie jest to łatwe, aby chwycić, że i zalogować go w kodzie wyrzutni - w toString() teh Environment będą listy aktywnych profili myślę) . Aktywne profile (i więcej) są również dostępne w punkcie końcowym/env, jeśli dodasz Actuator.

5

Usługa aktuator/env wyświetla właściwości, ale nie wyświetla rzeczywistej wartości właściwości. Bardzo często może chcesz nadpisać swoje właściwości aplikacji z

  • profilu specyficzne właściwości aplikacyjnych
  • argumenty wiersza poleceń
  • zmienne środowiskowe OS

ten sposób mają te same właściwości i różne wartości w kilku źródłach.

urywek mieszkowe druki aktywne właściwości aplikacyjne wartości, na starcie:

@Configuration 
public class PropertiesLogger { 
    private static final Logger log = LoggerFactory.getLogger(PropertiesLogger.class); 

    @Autowired 
    private AbstractEnvironment environment; 

    @PostConstruct 
    public void printProperties() { 

     log.info("**** APPLICATION PROPERTIES SOURCES ****"); 

     Set<String> properties = new TreeSet<>(); 
     for (PropertiesPropertySource p : findPropertiesPropertySources()) { 
      log.info(p.toString()); 
      properties.addAll(Arrays.asList(p.getPropertyNames())); 
     } 

     log.info("**** APPLICATION PROPERTIES VALUES ****"); 
     print(properties); 

    } 

    private List<PropertiesPropertySource> findPropertiesPropertySources() { 
     List<PropertiesPropertySource> propertiesPropertySources = new LinkedList<>(); 
     for (PropertySource<?> propertySource : environment.getPropertySources()) { 
      if (propertySource instanceof PropertiesPropertySource) { 
       propertiesPropertySources.add((PropertiesPropertySource) propertySource); 
      } 
     } 
     return propertiesPropertySources; 
    } 

    private void print(Set<String> properties) { 
     for (String propertyName : properties) { 
      log.info("{}={}", propertyName, environment.getProperty(propertyName)); 
     } 
    } 

} 
+0

To nic nie wydrukowano. – pacoverflow

+0

Nic? Czy masz na myśli, że nawet "**** WŁAŚCIWOŚCI WŁASNOŚCI APLIKACJI ****" jest wydrukowane na @PostConstruct? Najpierw upewnię się, że obiekt PropertiesLogger jest w ogóle tworzony w aplikacji. Być może pomocne może być zagłębienie się w @EnableAutoConfiguration. –

+1

Mam na myśli to, że wydrukowano "**** WŁAŚCIWOŚCI ZASTOSOWANIA ****, a następnie nic" "**** WARTOŚCI WŁAŚCIWOŚCI APLIKACJI ****", a następnie nic. – pacoverflow

0

W przypadku, gdy chcesz uzyskać aktywnych profili przed inicjalizacji fasoli/aplikacji, jedynym sposobem znalazłem się rejestracji niestandardowego Baner w SpringApplication/Budowniczy.

0

Oprócz innych odpowiedzi: rejestrowanie aktywnych właściwości w kontekście odświeżonego zdarzenia.

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 is MapPropertySource } 
       .map { it as MapPropertySource } 
       .filter { it.name.contains("applicationConfig") } 
       .map { it -> it.source.keys } 
       .flatMap { it } 
       .distinctBy { it } 
       .sortedBy { it } 
       .forEach { it -> 
        try { 
         println("$it=${env.getProperty(it)}") 
        } catch (e: Exception) { 
         logger.warn("$it -> ${e.message}") 
        } 
       } 
     println("******************************************************************************") 
    } 
} 

wyjścia jak:.

************************* 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 
... 
******************************************************************************