środa, 17 września 2014

Spring Profiles

Kiedyś definiowałem ustawienia projektu z poziomu mavena. Wydawało się mi to oczywiste i działało tak jak się tego spodziewałem. Zresztą profile to bardzo fajny feature mavena.
Z wejściem bodajże Springa3 podobny mechanizm mamy dostępny już w kodzie javowym jak i w plikach xml.
Jest to bardzo wygodne bo można dodawać do kontekstu poszczególne bean'y co w przypadku mavena sprowadzało się jedynie do podmiany konfiguracji czy ustawień konfiguracyjnych.
Z nadejściem Springa 4 dostaliśmy coś co zwiększa jeszcze elastyczność oraz moc  @Profile czyli @Coditional

@Conditional pozwala na tworzenie bardziej dynamicznych mechanizmów niż tylko statyczne @Profile . Dzięki niemu możemy reagować na szerszy kontekst np beans, enviroment properties, szczególne klasy w classpath itd.

To on dał takiego kopa projektowi Spring Boot.


Jak to wyglądało w XMl ?
Kilka lat temu akurat jak wchodził mechanizm profili przeprowadzałem szkolenie ze Springa. Chodziło mi o to aby zaprezentować różnice w podejściu do persystencji :
 - hibernate
 - jpa
 - jdbc = spring jdbc template
 - Spring Data

Uczestnicy szkolenia pomimo, iż  obejmowało ono temat Spring-Hibernate szybko chcieli zmiany na Spring Data zamiast postawowego tematu jakim miał być Hibernate. Spowodowane to było magią Spring Data, ilością potrzebnego kodu jak oraz gotową funkcjonalnością (CRUD) jaką out-of-the-box oferuje Spring Data.

Jak ma się do profili ? -> aplikacja pozostała spójna.

Jedyna zmiana w konfiguracji znajdowała się w pliku spring_data.xml. Zmieniająć profil z poziomu danych testów, wczytywał się odpowiedni kontekst oraz wraz z nim odpowiednie bean'y.

Tip: Z poziomu testów ustawiaj profil przez :
@ActiveProfiles(value = {$profile_name})

Możesz też tworzyć swoje własne profile :

@PropertySource służy do wprowadzenia zmiennych do mechanizmu Spring Enviroment (<context:property-placeholder>)
Obowiązująca tutaj kolejność ładowania properties to : 
  - System properties for the running JVM
  - Environment variables
  - Zmienne zdefiniowane w aplikacji *.properies

tutaj również działa super mechanizm placeholdera:
@PropertySource("classpath:${my.placeholder:/etc/conf/}/server.properties"
W przypadku xml wygląda to tak :

Uwaga zastosowanie połączenia @PropertySource i @Value wymaga użycia : propertySourcesPlaceholderConfigurer


Ustawienie profili wiąże się z zarejestrowaniem tego w ramach kontekstu Springa. A ustawić profil można również tak jak poniżej w przykładzie, i tak naprawdę każde działanie jawnie czy niejawnie się do tego sprowadzi.

W przypadku Spring Boot'a
profile aktywuje poprzez :

application.properties:
 spring.profiles.active={profile_name}
np :
 spring.profiles.active=dev,cache

to samo moge odpalić z linii poleceń :

 --spring.profiles.active=dev,cache


jeśli korzystam z yaml sprawa wygląda identycznie

należy jednak pamięć o dodaniu zależności

Zaleźności możemy zmieniać wygodnie i dynamicznie przez linię poleceń i tak zapis w pliku properties :

Skutkuje wystartowaniem serwera na porcie 8091.
W przypadku dodania argumentu jak --server.port=9002 serwer wystartuje na porcie 9002.
 I|Http11NioProtocol |Starting ProtocolHandler ["http-nio-9002"]
Jest to wygodny feature szczególnie podczas fazy developmentu.


Spring Boot określa także porządek ustawiania properties :
  1. Linia komend
  2. Java system properties (System.getProperties)
  3. Properties z OS
  4. JNDI -> java:comp/env
  5. RandomValuePropertySource

  6. Properties z poza jara gdzieś na path : application.proprties
  7. Properties wewnątrz jara -> application.properties
  8. @PropertySource w klasie oznaczonej @Configuration
  9. Domyślne ustawienia -> SpringApplication.setDefaultProperties

Można tworzyć ustawienia względem danego profilu:

application-{profile}.properties

Analogicznie konfigurację multi-profilową możemy stworzyć korzystając z Yaml w następujący sposób jak w przykładzie z dokumentacji:
Fajna jest możliwość zwiększania poprawności typów w przypadku ładowania properties i też taką możliwość oferuje nam Spring : (przykład z dokumentacji Spring Boota)

zastosowanie mechanizmu w jakimś moim kodzie :

@ConfigurationProperties

Objaśnienia :
@ConfigurationProperties - określamy jaką część pliku/sekcje nasza klasa ma reprezentować

@EnableConfigurationProperties - mówi Springowi, że dana klasa ma być traktowana jako konsumer wiadomość

@EnableConfigurationProperties  <-  kolaboruje z -> @ConfigurationProperties
czyli obie klasy żyją w symbiozie.

Tip : W Spring Boot może być mylące lub wydawać się niejasne jak przekonfigurowywać np ds, jms, health indicator czy inne tego typu historie.
Ja robię to tak :
Kluczem jest element @ConfigurationProperties - dlatego bo określa kawałek mojego pliku z properties z którego to kawałka Spring ładuje sobie interesującego go parę (klucz-wartość).

Czyli na @ConfigurationProperties naciskam combo (Shift+Ctrl+G) i ujawniają mi się wszystkie pliki z konfiguracji, które są w ogóle w ten sposób konfigurowalne.
Ok przykład: Jest to bardzo ważne, bez tej wiedzy można się trochę bujać ...;)

Następny przykład użycia:
@Profile -> @Bean
Generalnie jak widać to w kodzie wyżej  profil w javie ustawia się przez dodanie adnotacji @Profile.

Tip: Jest możliwość również wykluczania danego profilu: @Profile({"dev","!cache"})


To tyle na dzisiaj.... ) Generalnie elastyczność jest ogromna. Prostota użycia również. Według mnie ewolucja i rozwój Springa sprzyja coraz to łatwiejszemu pisaniu aplikacji. @Profile ułatwiają konfigurację, utrzymanie i rozwój.
@Conditional dostarcza super fajną elastyczność i otwiera możliwości w Spring Boot.
Yaml jest bardziej zwięzły, ludzki i Json podobny niż można czy sądzić.
Użycie Yaml w Springu sprowadza się do w sumie do dodania odpowiedniej zależności - procesora.

Brak komentarzy:

Prześlij komentarz