Využití Mavenu pro CzechIdM
Pro efektivnější vývoj našeho Identity Manageru CzechIdM bylo třeba vytvořit nástroj, který provede automatické sestavení („build“) aplikace ze zdrojových kódů nezávisle na vývojovém prostředí Eclipse. Za tímto účelem jsme použili nástroj Apache Maven. Základní vlastnosti, přednosti a nevýhody Mavenu nyní shrneme v tomto článku. Zmíníme také některé záludnosti, na které je třeba dávat pozor při práci s projektem vytvořeným JBoss Seam frameworkem.
Co je Maven?
Apache Maven je moderní open source technologie pro správu a řízení buildu Java aplikací. Maven pracuje s projekty, které dodržují jistou univerzální strukturu, a díky tomu může nabídnout zjednodušení celého build procesu. Vychází z myšlenky, že build proces všech „rozumných“ aplikací vyžaduje tytéž kroky, které se tím pádem mohou standardizovat. Není třeba se starat o detaily (např. sestavení Classpath a spuštění kompilátoru), dokud skutečně nepotřebujeme nějakou větší odchylku od obvyklého postupu.
Výstupem build procesu je Java archiv zvoleného typu, obsahující zkompilované třídy, použité knihovny a případně další zdroje. Je také možné spustit jen některé fáze buildu.
Maven vs. Ant
Alternativou k Mavenu, nad kterou jsme uvažovali, byla technologie Apache Ant, starší a oblíbený build nástroj pro Java aplikace. Mezi Mavenem a Antem je rozdíl už v základním principu jejich fungování. Chceme-li použít Ant, musíme napsat tzv. Ant skript. V Ant skriptu musíme stanovit cíle (target) obsahující kompletní příkazy, které se pro splnění daného cíle mají při buildu spustit. Naopak Maven má jednotlivé fáze buildu předdefinované (např. fáze compile, test, package), takže nám zbývá pouze doplnit informace o struktuře a závislostech našeho projektu pomocí tzv. POM.
V Antu jsou tedy lépe vidět detaily build procesu a snáze se implementují nestandardní kroky, na druhou stranu to s sebou nese riziko, že pro větší projekty přestanou být Ant skripty srozumitelné. Také se objevuje názor, že udržovat Ant skript funkční pro dlouhodobě se vyvíjející projekt je příliš náročné, obzvlášť mění-li se struktura projektu nebo používané knihovny.
POM (Project Object Model)
Hlavní práce při použití Mavenu spočívá ve vytvoření souboru pom.xml, v němž dodáváme Mavenu veškeré potřebné informace o struktuře projektu, použitých knihovnách a našich preferencích při buildu.
POM předně obsahuje jednoznačnou identifikaci sestavené aplikace pomocí:
- groupID – identifikuje organizaci či skupinu pro zařazení projektu, například eu.bcvsolutions.BCV_IdM
- artifactID – identifikuje projekt v rámci skupiny, například BCV_IdM-ejb
- version
- packaging – typ výstupu (jar, war, ear nebo jiné). Tato volba zároveň určuje fáze, které Maven zařadí do build procesu.
Změna výchozího nastavení buildu se provádí v sekci <build>. Nepoužíváme-li standardní mavenovské rozvržení adresářů, musíme správně nastavit položky <sourceDirectory> a <resources>. Chceme-li upravit průběh buildu, musíme změnit sekci <plugins>, protože právě pluginy jsou to, co v Mavenu opravdu provádí nějakou činnost. Maven poskytuje pro předdefinované fáze defaultní pluginy, jejichž konfiguraci lze měnit, případně můžeme přidávat další pluginy z bohaté nabídky.
Dependencies čili závislosti projektu
Nedílnou součástí POM je sekce <dependencies> popisující, na jakých knihovnách projekt závisí. Zacházení se závislostmi je v Mavenu klíčové a nesprávný přístup vede k mnoha potížím, proto se jim budeme věnovat detailněji.
Pokud například potřebujeme pro správnou kompilaci a běh aplikace knihovnu jboss-seam.jar, musíme do POM přidat následující kus kódu, který zajistí, že se jboss-seam-2.2.0.GA.jar do sestaveného balíku nakopíruje:
<dependency> <groupId>org.jboss.seam</groupId> <artifactId>jboss-seam</artifactId> <version>2.2.0.GA</version> <packaging>jar</packaging> <scope>compile</scope> </dependency>
Atribut <scope> určuje, pro které fáze buildu je uvedená knihovna potřeba. Kromě možnosti “compile” (všechny fáze) se dá použít například “runtime” (nutný pouze pro běh aplikace, ne pro kompilaci). Zvláštním případem je možnost “provided”, která značí, že knihovna je potřebná při kompilaci i běhu, ale nemá se přidávat do sestaveného balíku.
Správa závislostí je jeden z důležitých znaků Mavenu. Každá závislost se vyhledá v centrálním úložišti Mavenu, případně v dalších vzdálených úložištích, a instaluje se spolu se svým POM do lokálního úložiště uživatele (~/.m2/repository). Lokální kopie se pak použije při každém dalším buildu. Navíc Maven z POM stažené knihovny okamžitě přečte její vlastní závislosti, které taktéž stáhne. Postupně se tedy vyhledají všechny knihovny, na kterých by mohla naše aplikace tranzitivně záviset, a navíc ve správných verzích.
Záludné problémy
Po teoretickém úvodu nyní můžeme představit některé problémy, které se v průběhu vývoje našeho Maven build nástroje objevily.
Dependencies:
- Několik knihoven se nenacházelo v žádném vzdáleném úložišti. Maven projekt však může záviset pouze na knihovnách, k nimž existuje POM. Pomocí pluginu “maven-install-plugin” jsme chybějící POM ke knihovně rychle vytvořili a knihovnu si mohli instalovat do lokálního úložiště.
- Některé závislosti (např. hibernate-entitymanager.jar) způsobovaly výjimky při běhu aplikace, pokud se jim nenastavil <scope>provided.
- Kvůli tranzitivnímu stahování závislostí se do sestaveného balíku přidalo navíc několik knihoven, které v sobě obsahovaly tytéž třídy jako již zahrnuté knihovny. Řešením bylo vynechat problematické závislosti pomocí atributu <exclusions> uvnitř příslušné <dependency>.
JBoss Seam framework:
- Knihovna jboss-seam.jar se musí nacházet v sestaveném EAR balíku pouze jednou, jinak se objeví chyby při nasazení na aplikační server. Toho jsme dosáhli nastavením <scope>provided u EJB a WAR modulu naší aplikace.
- Každý modul aplikace, který používá nějaké Seam komponenty, musí obsahovat soubor seam.properties, třeba i prázdný.
Závěr
V tomto článku jsme představili technologii Apache Maven a její použití pro automatický build Java aplikace. Pro urychlení vývoje našeho Identity Manageru CzechIdM chceme v budoucnu zprovoznit Jenkins, server pro průběžnou integraci (Continuous Integration). Jenkins umožňuje po každé změně v projektu automaticky provést build a na jeho výsledek spustit automatické testování. První fázi již tedy umíme díky Mavenu provést a zbývá nám spuštění automatického testování, kterému se budeme věnovat zase někdy příště.
Máte-li jakékoliv dotazy k článku, Mavenu či CzechIdM, neváhejte se na mě obrátit na adrese info@bcvsolutions.eu!