jest to narzędzie wspomagające budowanie projektów. W odróżnieniu od znacznie starszego już Ant’a, Maven przedkłada konwencję ponad konfigurację. Czyli im bardziej projekt pasuje do założonej struktury, tym mniej Maven wymaga konfiguracji do poprawnego działania.

 Większość osób kojarzy na pewno komendę:

mvn clean install

Powyższa komenda usuwa zbudowane wcześniej artefakty oraz buduje nowe i instaluje je w lokalnym repozytorium Maven’a. W tym wpisie nie będę opisywać podstawowych funkcji działania Maven’a.  Chciałbym skoncentrować się na innych, mniej typowych funkcjonalnościach, których czasem używam.

Drzewo zależności

dependency:tree

Polecenie to jest szczególnie przydatne gdy mamy problem z kompatybilnością naszych zależności. Przykładowo nasz moduł ma ustawioną zależność do poprawnej wersji jakieś biblioteki. Jednak po zbudowaniu paczki okazuje się, że w środku mamy zaimportowaną inną wersję tej biblioteki. Może się tak zdarzyć jeśli dodaliśmy zależność, która również korzysta z tej samej biblioteki, ale w innej wersji. W związku z tym, że nie importujemy tej zależności bezpośrednio, jest to tzw. zależność przechodnia. W celu znalezienia źródła takiej niechcianej zależności w projekcie możemy wyświetlić pełne drzewo zależności za pomocą poniższej komendy:

mvn dependency:tree                                                                            
[INFO] Scanning for projects...                                                                  
[INFO]                                                                                           
[INFO] ------------------< com.michaladamski.my-application >---------------                  
[INFO] Building my-application 1.0-SNAPSHOT                                                          
[INFO] --------------------------------[ war ]---------------------------------                  
[INFO]                                                                                           
[INFO] --- maven-dependency-plugin:3.0.2:tree (default-cli) @ booking-be ---                     
[INFO] com.michaladamski:my-application:war:1.0-SNAPSHOT                                         
[INFO] +- org.javassist:javassist:jar:3.23.1-GA:compile                                          
[INFO] +- org.glassfish.jaxb:jaxb-runtime:jar:2.4.0-b180830.0438:compile                         
[INFO] |  +- javax.xml.bind:jaxb-api:jar:2.3.0:compile                                           
[INFO] |  +- org.glassfish.jaxb:txw2:jar:2.4.0-b180830.0438:compile                              
[INFO] |  +- com.sun.istack:istack-commons-runtime:jar:3.0.7:compile                             
[INFO] |  +- org.jvnet.staxex:stax-ex:jar:1.8:compile                                            
[INFO] |  +- com.sun.xml.fastinfoset:FastInfoset:jar:1.2.15:compile                              
[INFO] |  \- javax.activation:javax.activation-api:jar:1.2.0:compile                             
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.0.1.RELEASE:compile             
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.0.1.RELEASE:compile              
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.0.1.RELEASE:compile                   
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.0.1.RELEASE:compile     
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.0.1.RELEASE:compile   
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.10.0:compile                    
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.10.0:compile                      
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.25:compile                                     
[INFO] |  |  \- javax.annotation:javax.annotation-api:jar:1.3.2:compile                          
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.0.1.RELEASE:compile         
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.9.5:compile           
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.9.5:compile         
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.9.5:compile    
[INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.0.1.RELEASE:compile       
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.29:compile                     
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.29:compile                       
[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.29:compile                
[INFO] |  +- org.hibernate.validator:hibernate-validator:jar:6.0.9.Final:compile                 
[INFO] |  |  +- javax.validation:validation-api:jar:2.0.1.Final:compile                          
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.3.2.Final:compile                          
[INFO] |  |  \- com.fasterxml:classmate:jar:1.3.4:compile                                        
[INFO] |  +- org.springframework:spring-web:jar:5.0.5.RELEASE:compile                            
[INFO] |  |  \- org.springframework:spring-beans:jar:5.0.5.RELEASE:compile                       
[INFO] |  \- org.springframework:spring-webmvc:jar:5.0.5.RELEASE:compile                         
[INFO] |     \- org.springframework:spring-expression:jar:5.0.5.RELEASE:compile                  
[INFO] +- org.springframework.boot:spring-boot-starter-data-jpa:jar:2.0.1.RELEASE:compile        
[INFO] |  +- org.springframework.boot:spring-boot-starter-aop:jar:2.0.1.RELEASE:compile          
[INFO] |  |  \- org.aspectj:aspectjweaver:jar:1.8.13:compile                                     
[INFO] |  +- org.springframework.boot:spring-boot-starter-jdbc:jar:2.0.1.RELEASE:compile      
...   

Spójrzmy przykładowo na przedostatnią zależność (linia 47): org.aspectj:aspectjweaver:jar:1.8.13 jest ona importowana przez następującą zależność w naszym projekcie (linia 45): org.springframework.boot:spring-boot-starter-data-jpa. Jeśli dodaliśmy bibliotekę aspectjweaver w naszym projekcie w innej wersji, np. 2.0.0 to możemy w zależności spring-boot-starter wykluczyć importowanie biblioteki aspectjweaver w następujący sposób:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.aspectj:aspectjweaver</groupId>
            <artifactId>1.8.3</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Dzięki temu, po ponownym wygenerowaniu drzewa zależności widzimy, że wyłączona biblioteka nie została już zaimportowana

[INFO] |     \- org.springframework:spring-expression:jar:5.0.5.RELEASE:compile
[INFO] +- org.springframework.boot:spring-boot-starter-data-jpa:jar:2.0.1.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-aop:jar:2.0.1.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-jdbc:jar:2.0.1.RELEASE:compile
[INFO] |  |  +- com.zaxxer:HikariCP:jar:2.7.8:compile
[INFO] |  |  \- org.springframework:spring-jdbc:jar:5.0.5.RELEASE:compile

Drzewo zależności możemy zapisać do pliku w celu na przykład łatwiejszego wyszukiwania zależności. W tym celu wystarczy na końcu komendy dopisać znak „>” oraz nazwę pliku, np.:

mvn dependency:tree > project-dependencies.txt

Zmiana wersji w (całym) projekcie

Załóżmy, że mamy projekt składający się z wielu modułów. Na przykład taki jak na poniższym obrazie.

Jeśli chcielibyśmy podbić wersję we wszystkich modułach projektu, możemy do tego wykorzystać następujące polecenie:

mvn versions:set -DnewVersion=1.1.0 -DautoVersionSubmodules=true

Dzięki temu nie musimy nawigować po folderach i aktualizować wszystkich plików pom.xml. Wystarczy jedno, powyższe polecenie.

Pomijanie testów

Przy dużych projektach czas wykonania testów może znacząco wpływać na całkowity czas budowania projektu. Jeśli chcemy pominąć tę fazę możemy użyć polecenia z flagą skipTests

mvn clean install -DskipTests

Niektórzy kojarzą także inną komendę, mniej używaną gdyż trudniej ją zapamiętać

mvn clean install -Dmaven.test.skip=true

Warto czasem użyć właśnie tej, gdy zależy nam na szybszym skompilowaniu projektu. Ta komenda różni się tym od poprzedniej, że nie tylko nie wykonuje testów, ale nawet nie kompiluje klas testów. W związku z tym cała kompilacja przebiega szybciej. Łatwiej będzie Ci zapamiętać tę właściwość gdy skojarzysz, że poszczególne części podajemy od tych najbardziej generalnych do najbardziej specyficznych:

  1. maven (odnosi się do narzędzia – najbardziej ogólna)
  2. test (odnosi się do testów – bardziej specyficzna)
  3. skip (odnosi się do konkretnej czynności – najbardziej specyficzna)

Podsumowanie

Część z opisanych funkcjonalności jest tak naprawdę realizowanych przez instalowane w locie wtyczki (plugins). Jednak celem artykułu nie było dokładne przedstawienie narzędzia, tylko praktyczne wykorzystanie niektórych mniej znanych możliwości.

Jeśli znasz jakieś inne przydatne funkcje Maven’a podziel się tym w komentarzu.

Maven: przydatne funkcje

Dodaj komentarz

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