Hlavní menu
Nástroje |
NavigaceiPOJOiPOJO (injected-POJO) je runtime servisních komponent zaměřený na zjednodušení vývoje OSGi aplikací. Nativně podporuje veškeré dynamické aspekty OSGi. iPOJO je vytvořen pro běh moderních aplikací, které se vyznačují modularitou, vyžadující adaptaci za běhu a autonomní chování. iPOJO je vyvíjen týmem kolem Apache Felix (implementace OSGi). Prvotní verze 0.8 je z roku 2008 a vznikla na univerzitě v Grenoblu (Clement Escoffier, Richard S. Hall). Aktuální verze (prosinec 2014) je 1.12.1. Příklad iPOJO komponenty Základní principyPrincipem iPOJO je co největší oddělení funkčního od mimofunkčního kódu (dependency management, service provision, konfigurace, atd.). KomponentaKomponenta je centrálním konceptem iPOJO. Komponentu jako samostatně nasaditelnou jednotku (ve smyslu definice z hlavní stránky této wiki) v iPOJO představuje bundle, stejně jako v OSGi. Tím vzniká menší konflikt v terminologii, jelikož iPOJO notace (v anotacích, XML, atd.) označuje slovem Component Java třídy, poskytující a požadující služby z jiných bundlů. Tyto třídy se pak také označují za komponentové typy (component types) nebo továrny (factories). BundleBundle je svazek komponentových typů (ideálně tématicky spřízněných) nasazovaný zároveň. Z programátorského pohledu je to vlastně Java projekt, který specifikuje imporotované (požadované) a exportované (poskytované) balíky. To určuje pouze jejich viditelnost pro ostatní bundly, ne přímo poskytování služeb. Balíky pak obsahují jednotlivé factory/komponentové typy (třídy), z nichž se tvoří instance (objekty). Ty pak poskytují/požadují služby (implementovaná rozhraní/metody, resp. objekty tříd typované na tyto rozhraní) a jejich vlastnosti (properties; proměnné). Komponentový typV jádru iPOJO modelu komponentový typ popisuje závislosti služeb, poskytované služby a callbacky. Tyto informace jsou uloženy v metadatech komponentového typu (třídy). Jelikož iPOJO staví na principu POJO (Plain Old Java Object; standardních Java tříd), komponentový typ v iPOJO reprezentuje třída označená jako component type (také označovaná jako factory) jedním ze tří základních způsobů - anotace přímo ve zdrojovém kódu, XML v speciálním souboru popisující iPOJO komponentové typy a nastavení (XML deskriptoru) nebo pomocí fluent API. Stejnými způsoby lze z component type vytvořit instanci. Instance komponentového typu je analogií k instanci třídy v objektovém programování. Instance iPOJO a její kontejner Instance jejich životní cyklusInstance mají ke komponentovým typům (component type / factory) týž vztah, jako běžná Java instance ke třídám. Narozdíl od životního cyklu komponent (bundlů; stejný jako v OSGi) iPOJO instance mají velmi jednoduchý životní cyklus, který obsahuje pouze 2 stavy: INVALID a VALID. Po svém vytvoření může instance být validní pouze tehdy, pokud všechny její připojené handlery jsou validní. V nejzákladnějším případě to znamená, že všechny instancí požadované služby jsou dostupné. Například, instance požadující službu (a tím pádem používající dependency handler) nemůže být validní, pokud požadovaná služba není dostupná. Instance začíná a končí ve stavu INVALID (viz obr. níže). Životní cyklus instance Pro úspěšné spuštění instance je ovšem nutné aby všechny bundly poskytující jí služby byly ve stavu Resolved. Do něj framework převede všechny automaticky všechny takové instalované bundly. Problém nastává, pokud takový bundle závisí na dalším (a zřetězením případně dále), který není nainstalován, nebo nemůže být převeden do stavu Resolved. Tento případ končí výjimkou Vytvoření instance lze vynutit okamžitě po přechodu komponenty (bundlu) do stavu ACTIVE atributem Okamžité vytvoření instance atributem immediate Rozhraní (kontrakt)Rozhraní je reprezentováno poskytovanými a požadovanými službami (metodami nebo promněnými, popř.: konstantami), které se v iPOJO specifikují stejnými způsoby zápisu jako komponentové typy (anotace, XML, fluentAPI). Služba je vlastně jakékoli rozhraní, které POJO reprezentující komponentový typ implementuje. Komponentový typ tak může poskytovat více služeb. Framework automaticky hledá všechny taková rozhraní a nadtřídy každého komponentového typu při instalaci bundlu. Interakce služeb mezi iPOJO instancemi ModelKomponentový model iPOJO je v základu stejný jako u OSGi, jelikož iPOJO pouze vylepšuje tento framework. Jedná se o jednoduchý a rozšiřitelný (viz níže) model servisních komponent založených na POJO. Servisní komponenta může poskytovat a/nebo požadovat služby, přičemž služba je objekt implementující dané rozhraní. Model představují základní možnosti iPOJO ohledně nastavení konfigurace a komunikace mezi komponentami (viz seznam anotací níže). Model lze však libovolně upravovat a rozšiřovat přidáváním vlastních anotací. Navíc iPOJO zavádí koncept callbacků (volání), které dávají komponentě vědět o různých změnách stavu v životním cyklu (např. PostRegistration, PostUnregistration callbacky při (od)registrování služby, nebo přechod instance na stav Valid a Invalid). FrameworkKomponentový framework je pak celé iPOJO, resp. iPOJO spojené s patřičnou implementací OSGi (viz technické detaily níže). Princip fungování závisí na 2 hlavních částech - kontejner a handler. Kontejner obklopuje obsah (implementace POJO objektů) a spravuje všechny jeho mimofunkční požadavky jako propojení s ostatními instancemi nebo zdroji, životní cyklus, atd. Kontejner je popsán v component type třídě (opět anotacemi, XML nebo API). Kontejner v iPOJO tudíž není monolitem, ale je složen z handlerů. Každý handler spravuje jeden mimofunkční požadavek a požadované hadlery jsou připojeny za běhu aplikace. Instance komponentového typu je pak validní pouze pokud všechny připojené handlery jsou validní. Handlery je možné vytvářet a nasazovat mimo jádro iPOJO, tudíž každý si může vytvořit vlastní handler a přizpůsobit si tak model iPOJO svým potřebám (viz zde). Při běhu aplikace pak iPOJO runtime kombinuje funkční (implementace instancí) a mimofunkční (uchované v konfiguraci kontejneru) aspekty aplikace, odhaluje a "vstřikuje" (inject) požadované služby spojením metadat komponenty a konfigurace instance. Následně uveřejňuje (propaguje) poskytované služby a řídí životní cyklus komponenty. Technické detailyiPOJO funguje na jakékoli implementaci R4.1 OSGi a také na mnoha JVM jako Oracle JRockit, JamVM, Dalvik (Android) a Mika. Požaduje pouze J2ME Fondation 1.1 JVM. Díky tomu lze aplikace používat v mobilních a jiných zařízeních. Základem iPOJO fyzicky je iPOJO Core bundle (stáhnout). Samotné programování pak probíhá obdobně jako při standardním vývoji v Javě. Rozdílem je jen konfigurace instancí a metadata komponent. Ty je možné zavádět třemi způsoby:
Proč iPOJO?OSGi Service Platform poskytuje výborný základ pro vývoj dynamicky rozšiřitelných Java aplikací. Nicméně tato síla a pružnost není zadarmo. Kromě nevýhod ve formě nových API a formátů balíků, vývojáři v OSGi musí změnit svoje uvažování, aby byli schopni vytvářet vysoce dynamické aplikace. Rané pokusy, jako Service Binder a Service Tracker, se snažily o zmírnění některých z těchto problémů stejně jako některé aktuálnější příklady jako Declarative Services a Spring Dynamic Modules. iPOJO je další takovou snahou v této oblasti. Je to service-oriented komponentový model vytvořený přímo pro OSGi Service Platform. Hlavní účel na pozadí iPOJO je dvojí. Prvním jeho cílem je zjednodušení vývoje v OSGi na naprosto nezbytné minimum. To znamená, že poskytování a používání služeb a vyrovnávání se s dynamizmem by mělo vyžadovat co nejméně snahy na straně vývojáře. Druhým cílem je posunout se za hranici podpory zákadních OSGi mechanismů a pokusit se více nenuceně zahrnout pokročilé atributy včetně konfigurace komponent, synchronizace a kompozice. Vytvoření aplikace prostřednictvím služeb v samotném OSGi bez dalších frameworků je náročné, protože OSGi API je komplexní a je třeba určité úrovně znalosti o vnitřních mechanismech, aby se předešlo problémům se synchronizací. iPOJO poskytuje velmi jednoduchý vývojový model, což ukazuje následují základní ilustrační příklad (bez vnitřní implementace) pro
@Component @Provides public class MyServiceImplementation implements MyService { //.... }
@Component public class MyServiceConsumer { @Requires private MyService myservice; // stačí použít požadovanou službu jako obyčejnou proměnnou } Pozn.: Pro úplnost by bylo třeba přidat nad obě třídy ještě anotaci Podpora OSGi aplikací není jedinou výhodou iPOJO pro zjednodušení vývoje sofistikovaných aplikací. Podporuje také konfiguraci komponent pomocí Configuration Admin, posílání a přijímání událostí pomocí Event Admin, vzdálenou konfiguraci pomocí JMX a další. Další výhodou iPOJO je jeho flexibilita. Poskytuje totiž mechanismy pro rozšíření sebe samotného, které nevyžadují úpravy jádra. iPOJO se dá tudíž adaptovat pro vlastní potřeby pomocí vlastních handlerů (viz výše Základní principy) AnotaceAnotace jsou jedním ze způsobů zápisu metadat komponent a konfigurace instancí v iPOJO. Anotace jsou automaticky zpracovány iPOJO manipulátorem a nemusí být nasazeny při runtimu. Zde jsou vyjmenovány základní anotace iPOJO obsažené v knihovně
Další anotace mohou být v externích handlerech, např. temporální závislosti nebo možnost vystavení instance jako JMX MBean. K použití externích anotací je nutné pouze přidat je do build path. Více informací o anotacích např. zde. iPOJO Reference Card pak ukazuje paralelně použití některých základních principů jak anotacemi, tak XML deskriptorem + několik dalších věcí jako Extender Pattern a Whiteboard Pattern. Rozdíly v implementaci oproti OSGiPopisované rozdíly jsou demostrovány na implementaci iPOJO aplikací pomocí Maven a anotací. Pro další možnosti implementace (XML deskriptor, fluentAPI, Ant, atd.) možno konzultovat hlavní stránku iPOJO na Apache Felix nebo další zdroje uvedené na této wiki. Nahrazení manifestuAtributy bundlů jako jméno, symbolické jméno, verze a další vedených v OSGi v manifestu je možné nahradit obdobnými elementy v Mavenu (pom.xml). Obdobně importované balíky jsou nahrazeny dependencies a exportované balíky pomocí elementu <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <configuration> <instructions> Komponentový typKomponentový typ (factory) stačí označit anotací SlužbyPoskytovanou služby stačí identifikovat anotací VlastnostiMožné je též specifikovat vlastnosti služeb anotacemi ActivatorMísto aktivátoru používaného v OSGi stačí použít callbacky identifikované anotacemi UdálostiPoužití
Defaultní způsob zasílání událostí je asynchronní. Názorná ukázka zasílání událostí: @Publishes(name="vysilac_parkoviste_mista", synchronous=true, topics="parkoviste/mista") Publisher vysilac_mista; @Publishes(name="vysilac_parkoviste_plne", synchronous=true, topics="parkoviste/plne") Publisher vysilac_plne; ... private void posliZpravu() { if (volnaMista == 0) { vysilac_plne.send(new Properties()); } Dictionary<Object, Object> properties = new Properties(); properties.put("volnaMista", volnaMista); vysilac_mista.send(properties); } Příjem událostí je realizován použitím anotace @Subscriber(name="prijmac_tabule_plne", topics="parkoviste/plne") public void prijmoutPlno(Event e) { println("Parkoviste plne!"); } @Subscriber(name="prijmac_tabule_mista", topics="parkoviste/mista", dataKey="volnaMista", dataType="java.lang.Integer") public void prijmoutMista(Integer mista) { println("Zbyva mist : " + mista); } Celý koncept práce s událostmi ilustruje obrázek níže. Pro více informací o Event Admin Handleru viz zde. Zasílání a zpracování událostí v iPOJO KompoziceZajímavou vlastností iPOJO je možnost vytváření kompozic, tj. aplikací agregujících několik bundlů a schopných určit rozsah viditelnosti (propagace) jejich služeb. Prakticky řečeno lze nastavit, které služby budou dostupné jen uvnitř kompozice a které budou uveřejněny i pro bundly vnější vzhledem ke kompozici (více zde). V příkladu na obrázku je služba Dictionary Service dostupná pouze uvnitř kompozice, zatímco služba komponenty Checker je propagována vně kompozice. Příklad kompozice Kompozice je možné definovat pouze v XML deskriptoru (element Dále je pak možné skládat kompozice kompozic a dalších bundlů a tím dosáhnout hierarchické struktury celé agragace, na jejíž každé úrovni je možné omezit propagování služeb za její hranici. Příklad na obrázku ilustruje takovou situaci. Příklad hierarchické kompozice Možnosti customizaceMožností vlastních úprav komponentového modelu iPOJO je definování vlastních handlerů (včetně vlastních anotací). Podrobné informace o tomto tématu naleznete zde. Handler komunikuje s kontejnerem komponenty, POJO, ostatními komponentami, službami, bundly, OSGi frameworkem, atd. Prvním krokem k vytvoření vlastního handleru je implementace Java třídy rozšiřující abstraktní třídu Životní cyklus handleru Metody abstraktní třídy
Metody abstraktní třídy
Handler je pak možné používat přidáním v XML deskriptoru (viz odkaz výše) nebo pomocí definování anotace. Anotaci je možné definovat vytvořením Java souboru s následující hlavičkou: Zde je podle potřeby možné definovat atributy anitace formou atributů Java třídy. Poté lze handler snadno používat v komponentových typech použitím jeho anotace (popř. s atributy). Pro funkčnost je samozřejmě nutné nasadit bundle s handlerem před spuštěním aplikace, která ho používá. Návody na zpracování konfigurace handleru a instance, interakce s iPOJO frameworkem a další pokročilé techniky včetně 2 ilustračních příkladů, viz odkaz výše. Další znaky iPOJO
iPOJO používají
Praktické příklady a tutoriályPříklady na vyzkoušení jsou k nalezení na internetu a zahrnují aplikace
Další zdroje
Praktická částOba příklady jsou vypracovány s maximální možnou podobností (až na několik drobných změn) jako jejich protějšky z kapitoly o OSGi pro snadné porovnání obou implementací. Kroky převodu implementačních principů z OSGi na iPOJO v příkladech použité jsou z většiny popsané v kapitole Rozdíly v implementaci oproti OSGi (viz výše). Oba příklady využívají anotace a Maven. FelixOba níže uvedené příklady obsahují instanci Felix frameworku konfigurovanou pro své potřeby pomocí Maven.
Překlad příkladů
Příklad Message PrinterAttach:MessagePrinterIpojo.zip. Příklad Parkoviště |