https://pixabay.com/pl/ikona-klucz-orzech%C3%B3w-p%C5%82aski-2174755/

Come back! Maven i zarządzanie profilami

Cześć!

Niestety moja ostatnia aktywność na blogu nie jest imponująca, ostatni wpis pojawił się 4 lipca, czyli ponad 6 (!) (słownie sześć) miesięcy temu. Jednak to nie znaczy, że całkowicie porzuciłem ten projekt. Niedługo będę musiał opłacić domenę i hosting, a to z pewnością zmotywuje mnie i w pewnym sensie zobowiąże do większego działania:) Tak jak patrzę z perspektywy czasu, dwa posty w tygodniu to jest całkiem niezły wyczyn i podziwiam tych, co mają taką lub lepszą częstotliwość publikowania na blogu. Trafił się mniej intensywny weekend, więc postanowiłem wrócić z krótką notką na temat związany po trochu z Mavenem i plikami z właściwościami, o których zdarzyło mi się już wcześniej napisać parę zdań. Z pewnością nie jest to „rocket science”, ale i tak warto zrobić notkę, tym bardziej, że już mi się zdarzyło szukać czegoś u siebie na blogu, jak robiłem coś podobnego i chciałem odświeżyć sobie temat.

Z uwagi na to, że jesteś na blogu, więc zanim przejdę do właściwego tematu wpisu, pozwolę sobie na trochę osobistych przemyśleń. Jeśli nie interesuje Cię to, pomiń trzy kolejne akapity:)

Co się u mnie zmieniło przez te kilka miesięcy? Przede wszystkim zmieniłem pracę. Od sierpnia jestem w nowej firmie, na stanowisku Młodszego Programisty Java. Udało mi się osiągnąć cel, jakim było przebranżowienie. Na początku było trochę stresu, ale ogólnie nie jest źle i chwalę sobie zmianę. Tyle w skrócie, ponieważ jest to w zasadzie temat na oddzielny wpis, bo jak obserwuję blogosferę, przebranżowienie i rady dla Junior Developerów są teraz w modzie. Cała ta sytuacja ma dla mnie takie konsekwencje, że z mniejszą chęcią siadam wieczorem przed klawiaturą komputera, przecież trzeba też od tego odpocząć, skoro w pracy większość czasu spędzam w trybie siedząco-czytająco-piszącym.

Mimo wszystko, w trakcie tych sześciu miesięcy trochę czasu udało się zagospodarować na rozwój, własny i projektów. Głównie działam w temacie Sterownika Domowego. Dla przypomnienia, jest to projekt aplikacji do zarządzania „inteligentnym domem”, coś na wzór Domoticza. Może „inteligentnym” to za dużo powiedziane, bo jak mówią, nie ma takich – są po prostu aplikacje z dużą ilością „if-ów” i „elsów” (zasłyszane w internecie). Projekt zdecydowanie nie jest skończony, ale pojawiło się w nim trochę nowych rzeczy. Niebawem planuję wypuścić oddzielny wpis na ten temat, mam nadzieję, że uda się go wyprodukować jeszcze w styczniu (będzie dużo zrzutów ekranu!).

Co nowego na blogu? Po dłuższym czasie nieobecności wyczyściłem spam w komentarzach, bo trochę się tego nagromadziło. Trzeba przyznać, że plugin którego używam, całkiem nieźle sobie z tym radzi. Zrobiłem aktualizację WordPressa i uruchomiłem mechanizm CAPTCHA podczas dodawania komentarzy. Przy okazji zablokowałem dostęp do xmlrpc.php, bo przeglądając logi znalazłem sporo siłowych prób dostępu do tego miejsca.

Wracając do meritum, temat jest niezwykle prosty, aczkolwiek warty zanotowania. Warunki początkowe są takie, że mam utworzoną pustą aplikację Java, z podłączonym plikiem pom.xml (projekt Mavenowy). Nie ma znaczenia jaka jest konkretna tematyka tego projektu, jakie są użyte technologie, itp. – robimy duże uproszczenie. Niewątpliwie dobrą praktyką jest testowanie aplikacji w izolacji od środowiska produkcyjnego. Idąc dalej w założeniach przyjmijmy, że konfiguracja aplikacji jest odmienna dla środowiska testowego i produkcyjnego. Co prawda to może mieć również negatywne skutki – w testach może być wszystko w porządku, natomiast w docelowym rozwiązaniu może nie zadziałać. Przykładowym uzasadnieniem stosowania różnych ustawień może być testowanie aplikacji, która wysyła powiadomienia e-maila. Z reguły nie jest pożądane dostarczanie próbnych wiadomości do docelowego adresata (np. klienta), warto więc mieć dwie oddzielne konfiguracje zawierające odmienne adresy.

Przykładowe pliki z ustawieniami dla konfiguracji testowej oraz produkcyjnej mogą wyglądać jak poniżej.

app.properties (dev):

message=Hello world at development environment
port=8080
mail=mail_2@test.pl
project_name=${name} (dev)
my_variable=${my.variable} (dev)

app.properties (prod):

message=Hello world at production environment
port=443
mail=mail_1@company.pl
project_name=${name} (prod)
my_variable=${my.variable} (prod)

Zdublowane właściwości zostały umieszczone w plikach o takiej samej nazwie, lecz znajdujących się w różnych podfolderach projektu (/src/properties/development oraz /src/properties/production). Dodatkowo w każdym z tych katalogów umieściłem pusty plik test.properties – o nim na koniec. Cała struktura plików w projekcie przedstawia się jak na załączonym poniżej fragmencie zrzutu ekranu.

Struktura projektu
Struktura projektu z plikami właściwości

W kolejnym kroku należy umieścić w pliku pom.xml odpowiednie wpisy konfiguracyjne w znaczniku <profiles>. Definiuję tu dwie konfiguracje – testową (dev) oraz produkcyjną (prod), podając lokalizację zasobów, które mają być uwzględnione podczas budowania aplikacji (znacznik <resources>). W tym miejscu można również inaczej zdefiniować pluginy dla różnych profili, przykładowo budować wynikowy plik jar/war o odmiennych nazwach dla produkcji i developmentu.

<project>
    <strong><name>kodowaniedoszuflady.pl</name></strong>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <my.variable>2017-01-07</my.variable>
    </properties>
    <build>
        <plugins>
            <!-- Plugins, for example maven-assembly-plugin in my case -->
        </plugins>
    </build>
 
    <profiles>
        <profile>
            <id><strong>dev</strong></id>
            <build>
                <resources>
                    <resource>
                        <directory>src/properties/development</directory>
                    </resource>
                </resources>
            </build>
        </profile>
        <profile>
            <id><strong>prod</strong></id>
            <activation>
                <activeByDefault>true</activeByDefault>
                <!--
                <jdk>[1.7,1.9)</jdk>
                <os>
                    <family>Windows</family>
                </os>
                -->
            </activation>
            <build>
                <resources>
                    <resource>
                        <directory>src/properties/production</directory>
                        <filtering>true</filtering>
                        <excludes>
                            <exclude>test.properties</exclude>
                        </excludes>
                    </resource>
                </resources>
            </build>
        </profile>
    </profiles>
</project>

W przypadku konfiguracji produkcyjnej, ustawiłem dodatkowe parametry w znaczniku <activation>. Przede wszystkim określiłem, że jest to konfiguracja domyślna. Poprzez wykonanie polecenia mvn help:active-profiles można zweryfikować, który wariant jest wybrany. W moim przypadku dostaję poniższą informację.

Active Profiles for Project 'pl.stepniak.maciej:TestMavenProject:jar:1.0-SNAPSHOT': 
 
The following profiles are active:
 
 - prod (source: pl.stepniak.maciej:TestMavenProject:1.0-SNAPSHOT)

Mechanizm ten oferuje szersze możliwości konfiguracji. Przykładowo wybrany profil może być aktywowany w zależności od systemu operacyjnego lub wersji JDK na maszynie (w zakomentowanym fragmencie – wersje 1.7 oraz 1.8).

Wybór profilu
Wybór profilu w Netbeans 8.2

Po zapisaniu pliku pom.xml Netbeans umożliwia wybór aktywnego profilu. Wybranie opcji prod lub <default config> uwzględni wybór pliku app.properties z katalogu src/properties/production, natomiast opcji dev – z katalogu src/properties/development

W metodzie main() wstawiłem prosty fragment kodu pobierającego wartości wybranych właściwości. Będą one różne dla innych wybranych profili.

public class PropertiesTester {
 
    public static void main(String args[]) throws IOException {
        Properties properties = new Properties();
        properties.load(PropertiesTester.class.getResourceAsStream(File.separator + "app.properties"));
 
        String message = (String) properties.get("message");
        String port = (String) properties.get("port");
        String email = (String) properties.get("mail");
        String projectName = (String) properties.get("project_name");
        String myVariable = (String)properties.get("my_variable");
 
        System.out.println("Project name: " + projectName);
        System.out.println("Message: " + message);
        System.out.println("Port: " + port);
        System.out.println("My POM variable: " + myVariable);
        System.out.println("Sending e-mail to: " + email);
    }
}

Wydruk w konsoli dla profilu produkcyjnego:

Project name: kodowaniedoszuflady.pl (prod)
Message: Hello world at production environment
Port: 443
My POM variable: 2017-01-07 (prod)
Sending e-mail to: mail_1@company.pl

Wydruk w konsoli dla profilu testowego:

Project name: ${name} (dev)
Message: Hello world at development environment
Port: 8080
My POM variable: ${my.variable} (dev)
Sending e-mail to: mail_2@test.pl

W profilu produkcyjnym została poprawnie pobrana nazwa projektu ze znacznika <name> pliku pom.xml. Zadziało się tak dzięki ustawieniu wartości true w węźle <filtering>.

Na koniec warto spojrzeć do znalazło się w folderze wyjściowym (target) projektu, czy głębiej w zbudowanym pliku *.jar. Wyszukamy tam tylko jeden plik app.properties, z właściwościami odpowiednimi dla wybranego profilu. Wspominałem wcześniej o pliku test.properties, przyszła pora na wyjaśnienie po co był potrzebny. Celem było sprawdzenie wyłączenia wybranych plików z kopiowania do folderu wyjściowego. Plik ten znajdzie się jedynie w przypadku wybrania profilu dev. Konfiguracja tego zachowania znajduje się w znaczniku <excludes> w profilu prod. Analogicznie można wykonać operację odwrotną, za pomocą umieszczenia pozycji w elemencie <includes>.

To z pewnością są podstawowe informacje na temat budowania profili, po więcej szczegółów odsyłam w jedno słuszne miejsce – do dokumentacji. 🙂

Dla zainteresowanym tematem Sterownika domowego, najbliższy wpis planuję przygotować właśnie w tym temacie. Keep in touch!

Literatura obowiązkowa:

Maven – Introduction to Build Profiles
Apache Maven Resources Plugin

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *