Seriál: Modulární systémy ve Spring Frameworku

Ve chvíli, kdy začnete používat při vývoji masivněji Spring Framework a začnete vytvářet znovupoužitelné knihovny postavené nad tímto frameworkem, začnete řešit jak z těchto knihoven co nejlépe složit výslednou aplikaci. První myšlenky povedou pravděpodobně těmito cestami:

  1. konfigurační soubory jednotlivých knihoven sloučit v jednom velkém aplikačním kontextu
  2. držet jednotlivé knihovny odděleně - nechat jim jejich vlastní aplikační kontexty a k těmto kontextům se dostávat programovým způsobem

Obě cesty však mají svá úskalí.

ad 1)

Ta první s sebou nese řadu problémů týkající se porušením zapouzdření konkrétních knihoven. Např. budete řešit problémy s konflikty názvů bean (stanovení jmenných konvencí je možná cesta, ale velmi trnitá). Bude se vám špatně definovat rozhraní jednotlivých knihoven. Ve společném kontextu budou mít všechny beany přístup ke všem ostatním beanám v něm. Aplikační události budou všem knihovnám společné - takže může docházet k interferencím. Prostě se vám bude špatně odhadovat co se stane, když zkombinujete konfiguraci knihovny A s konfigurací knihovny B. A to ani nemluvě o některých vlastnostech Springu, které by vám spojení některých knihoven mohly ošklivě zkomplikovat (např. pokud by každá knihovna potřebovala svůj vlastní speciální Multicaster, jste v koncích).

ad 2)

Druhá cesta má také své problémy. Každou knihovnu musíte konfigurovat zvlášť a to i v případě bean, které by se vám hodily sdílet - typicky beany DataSource a TransactionManager, které zajišťují spojení s databází. Často máte jen jedinou databázi a při deploymenu je opravdovou výhodou, pokud máte konfiguraci jen jednou. Nemluvím jen konfiguraci url, username a pwd, ale třeba i nastavení connection poolu apod. - vždy je lepší mít pouze jediný connection pool pro aplikaci, než aby si každá knihovna řešila to samé znovu (ano na aplikačním serveru, toto není tak velký problém, protože toto můžete řešit mimo vaší aplikaci a dostate se přes JNDI k hotovému, ale ne vždy to můžete chtít nebo mít tu možnost). Dalším problémem jsou transakce - nad oddělenými aplikačními kontexty budete problematicky definovat sdílenou transakci.

Dost se nadřete - nemůžete využít vlastností Springu pro sestavení celé aplikace. Spring vám sestaví pouze jednotlivé moduly, ale propojení mezi nimi si už musíte řešit sami. Pravděpodobně bude mít každá knihovna nějakou speciální fasádu, přes kterou budete volat metody rozhraní této knihovny (fasáda si pak uvnitř získá inicializované beany ze aplikačního kontextu pomocí metody getBean(String beanName)). A to nemluvím o tom, že si to každá knihovna může řešit tak trochu po svém.

Kudy z toho ven?

Modulární systémy

Spring Framework připravuje podporu pro technologi OSGi, která právě řeší způsob jak vyvíjet a integrovat znovupoužitelné moduly. OSGi jako takové má za sebou poměrně dlouhou historii a v současné době se jedná o sofistikovaný a propracovaný způsob práce s moduly. OSGi ve Springu bude nabízet například následující vlastnosti:

  • oddělení aplikační logiky do modulů
  • schopnost současně provozovat modul v různých verzích
  • možnosti dynamicky vyhledávat a používat služby nabízené ostatními moduly systému
  • možnost instalovat, aktualizovat a odinstalovávat moduly za běhu
  • nechat Spring Framework instanciovat, konfigurovat, skládat a dekorovat komponenty v a i nad jednotlivými moduly
  • jednoduchý a známý programovací model pro enterprise developry využívat vlastnosti OSGi platformy

Mezi dalšími vlastnostmi, které vývojáři slibují je i podpora pro JMX, vlastní životní cykl jednotlivých modulů apod. Podrobněji se o OSGI rozepsal Dagi na svém blogu.

ALE

Jenže podpora OSGi ve Springu je stále ve stádiu přípravy (o tom mluví i číslo současné verze - 0.7) a tudíž se může rozhraní a způsob použití ještě měnit a řada věcí může být poměrně nevyladěných. Celý systém na první pohled nevypadá tak jednoduše, jak je deklarováno a řadu věcí pro menší aplikace možná ani nevyžadujeme.

V současné chvíli ve většině projektů, kterých se účastním, potřebuji jen následující vlastnosti:

  • mít možnost vyvíjet knihovny samostatně bez ohledu na to jak budou ve výsledku do systému zapojeny
  • v aplikačních knihovnách mít možnost bez obavy využít veškerých možností Springu, bez obavy, že tím ovlivním ostatní součásti systému
  • sdílet společné části výsledné aplikace skrze moduly - typicky beany zapouzdřující připojení k databázi, mail serveru, ldap atp. - tzn. mít fyzicky v celé aplikaci pouze jedinou intanci beany daného druhu
  • jasně definovat rozhraní modulu - tedy aby se okolní moduly aplikace dostaly jen k těm beanám mého modulu, která já určím jako veřejné (těch bude v modulu typicky jen pár)
  • zajistit funkčnost Observer patternu (aplikační eventy / listenery) nad všemi moduly - ovšem pouze selektivně, tedy mít veřejné události jednotlivých modulů, na které mohou reagovat moduly ostatní
  • mít možnost refreshnout aplikaci za běhu (bez nutnosti restartu web kontextu v kontejneru)
  • mít možnost jednoduše nadefinovat sdílenou transakci nad voláním různých modulů standardním Spring (tím myslím AOP) způsobem

Jsou vlastnosti, které nabízí zmíněné OSGi a které typicky k životu nepotřebuji:

  • schopnost současně provozovat modul v různých verzích (tohle je ovšem potřeba jen opravdu ve velkých systémech, kde řadu věcí nemáte tak úplně pod kontrolou - zatím jsem podobnou věc nikdy nepotřeboval)
  • dynamicky vyhledávat služby ostatních modulů (když tvořím aplikaci určuji, které moduly budu potřebovat a které ne)
  • instalovat, aktualizovat a odinstalovávat moduly za běhu (mě stačí jednou za čas provést redeploy aplikace u zákazníka - nevadí mi, když se kvůli tomu systém na pár minut odstaví)
  • řešit lifecycle modulů zvlášť (mě stačí lifecycle, který definuje samotný Spring)

Jednoduše řečeno pro mé potřeby se mi zdá OSGi technologie jako kanón na vrabce. Vždyť já toho k životu zase až tak moc nepotřebuji, chci jen rozumně vyvíjet aplikace, složené ze znovupoužitelných modulů založených na Springu. OSGi má řadu enterprise fíčur, které nikdy nevyužiji.

Pokud sdílíte můj názor, máte podobné problémy a hledáte nějaké jednoduché řešení, je tento můj seriál určen právě pro vás. Nečekejte žádné enterprise řešení plné buzzwordů a super reklamních fíčur. Jen jednoduchý kód, který vám pořeší problémy, které jsem zmínil. Budeme k tomu potřebovat jen pár dobře umístěných tříd a využití vlastností Springu, které v něm už léta jsou.

Pokud hledáte robustnější řešení bude samozřejmě lepší sáhnout po OSGi (až bude jeho implementace ve Springu dokončena) - tímto seriálem rozhodně nechci hodnotu OSGi shazovat (aby nedošlo k nějaké mýlce ;-) ).

Dodatek

Můj původní záměr byl pouze jediný článek. Materiálu je však na jeden příspěvek hodně a proto jsem se rozhodl text rozdělit do několika po sobě jdoucích příspěvků, které vám budu dávkovat zhruba v týdenních intervalech.

Díl #1: Aplikační kontexty