ObrázokToto je tretie pokračovanie článkov o špecifikácii OSGi, ktorá popisuje modulárny, dynamický java framework. Po úvode, v ktorom sme si vysvetlili, čo je OSGi a bundle a druhom článku, kde sme prebrali, ako sa bundle vytvára a akým životom v OSGi kontajneri žije, sa dnes pozrieme na tretiu vrstvu, ktorú predstavujú služby. Tie sú v OSGi ďalšou formou spolupráce kódu medzi jednotlivými bundlami s ešte slabšími väzbami a väčším dynamickým potenciálom ako mechanizmy, ktoré sme preberali doteraz.Ako som už viackrát spomenul, väzby medzi bundlami sú formované na základe balíkov. Inak povedané, bundle závisí na zozname balíkov, ktoré poskytujú iné bundle a on sám môže do prostredia poskytovať tie svoje. Pre určité scenáre použitia kódu to môže byť dostačujúce. Ak však chcete vyššiu úroveň abstrakcie väzieb, je tu mechnizmus služieb.

Základná myšlienka je taká, že bundle poskytuje nejakú službu. Ak ste sa stretli so Service Oriented Computing alebo Service-Oriented Architecture, je to veľmi podobné. OSGi vlastne predstavuje prostredie, v ktorom sa nachádzajú bundle, ktoré služby poskytujú a bundle, ktoré ich využívajú. Pritom službu si viete predstaviť ako triedu, ktorá implementuje určité rozhranie. To, čo klientský bundle (ten, ktorý službu používa) v podstate dostane, je inštancia takejto triedy, nad ktorou môže volať metódy.

OSGi obsahuje niečo, čo sa nazýva OSGi Service Register. Je to miesto, kde sa musí zaregistrovať každá služba na to, aby bola použitá. Registrácia prebieha pomocou takzvanej BundleContext triedy. To je trieda, ktorú vie získať každý nasadený bundle zo svojho prostredia (v metóde start a stop, ktoré sú volané, keď sa bundlu štartuje a keď sa stopuje), a ktorá slúži na komunikáciu bundlu s prostredím. Tento BundleContext má viacero použití a jedno z nich je, že umožňujú kódu bundlu pracovať so službami. Novú službu zaregistrujem pomocou príkazu:

ServiceRegistration BundleContext.registerService(interface, service, metadata)

Funkcia teda berie ako vstupné parametre rozhranie (to je v podstate identifikátor služby v prostredí), implementáciu služby (objekt, ktorý ju implementuje) a nepovinné metadata (ľubovoľné údaje vo forme kľúč – hodnota). To, čo vracia, je objekt typu ServcieRegistration, ktorý slúži na manipuláciu s registrovanou službou (hlavne jej odregistrovanie). Ten by mal ostať súkromný a nikde by sa nemal zdieľať.

Ak už ste službu zaregistrovali v jednom bundly, v druhom ju potrebujete získať. To sa robí opäť pomocou BundleContext objektu:

ServiceReference BundleContext.getServiceReference(interface)

To, čo takto získate nie je služba. Je to akýsi jej popis. Ešte stále nemáte jej inštanciu. Na to, aby ste ju získali, musíte volať ešte jednu metódu:

BundleContext.getService(ServiceReference)

Až volaním tejto metódy získavate samotnú službu, ktorú viete použiť.

Podobne, ako môžete mať nasadených niekoľko bundlov, ktoré poskytujú tie isté balíky, môžete mať v registri zaregistrovaných niekoľko inštancií tej istej služby. OSGi vám potom poskytne jednu z nich. Ak chcete medzi takými inštanciami služby rozlišovať, viete na to použiť práve metadata, ktoré sú tretím parameterom registrácie. Službu teda môžete zaregistrovať viackrát s rôznymi metadatami a pri získavaní referencie využiť dotazy vo forme LDAP queries a získať tak jednu z nich na základe metadát.

V prípade, že ste službu v kóde použili a viac ju už nebudete potrebovať, mali by ste to dať OSGi kontajneru vedieť volaním ďalšej metódy BundleContext triedy:

BundleContext.ungetService(reference)

OSGi si totiž vedie evidenciu používaných služieb, ktorá sa v niektorých prípadoch využíva.

BundleContext teda predstavuje bránu k používaniu služieb. Nie je ale jedinou. Okrem neho existujú ešte ďalšie dve mechanizmy: ServiceListerner a ServiceTracker. To prvé je v podstate štandardné listener java rozhranie, čo znamená, že ho treba implementovať, niekde zaregistrovať a potom čakať, že niekto bude volať jeho metódy. Konkrétne bude volané pri registrovaní služby, jej modifikovaní (je možné pozmeniť metadata už registrovanej služby) a odregistrovaní. ServiceTracker je inštancia triedy, ktorá zjednodušuje získavanie služby. Službu pomocou nej viete získať volaním jednej metódy namiesto dvoch. Okrem toho je možné nasadiť svoj vlastný upravený ServiceTracker, a tak ovplyvniť získavanie služby všade tam, kde sa používa.

Pri práci s OSGi službami si je nutné uvedomiť, že kód sa nachádza v dynamickom prostredí. Služba, ktorá ešte pred chvíľou bola dostupná už v tomto momente nemusí byť. Ak získate referenciu služby, ešte to neznamená, že máte službu, pretože k odregistrovaniu môže dôjsť práve medzi získaním referencie a pokusom o získanie služby. Dynamickosť je ale jedna z hlavných predností OSGi frameworku, a preto sa netreba diviť, že je tak hlboko zakomponovaná. To, na čo pri písaní špecifikácie jej tvorcovia tiež mysleli je zadefinovanie množiny služieb, ktoré budú dostupné v každej implementácii. V súčastnosti existuje skupina služieb, ktoré boli zadefinované, naprogramované a viete ich nasadiť. Ide o veľmi užitočné triedy, ale ich popis si zasluhuje samostatný článok.