Java komponens modellek avagy hány JSR kell egy használható komponens modell bevezetéséhez? Srágli Attila
Áttekintés Fogalmak Miért kell nekünk komponens modell? A múlt Komponens modellek Komponens modell implementációk Összehasonlítás A jelen A jövő?
Fogalmak – komponens Ahány ház, annyi definíció. A kedvenceim: „A component is a unit of composition with contractually specified interfaces and fully context dependencies that can be deployed independently and is subject to third-party composition” Clemens Szyperski: Component Software: Beyond Object-Oriented Programming, 1998. „the smallest architecturally relevant building block, a piece of encapsulated application functionality” Markus Völter Azaz a hangsúly az egységbe záráson (komponens, mint egység) és a függőségek (nyújtott szolgáltatások (interfész) és elvárt szolgáltatások) definiálásán van.
Fogalmak – komponens Egy komponens tehát explicit módon deklarálja: az általa nyújtott szolgáltatásokat Java megfelelője: implementált interfészek az általa igényelt szolgáltatásokat Java megfelelője: ?? a kapcsolódási pontokat (portok) az igényelt szolgáltatások egyedei számára (referencia neve, kardinalitás) A Java nyelv a nyújtott szolgáltatások explicit deklarálására képes ugyan („implements” kulcsszó), azonban az igényelt szolgáltatások és portok explicit módon nem deklarálhatók, tehát a kizárólag a nyelvi lehetőségekre épülő komponens modell nem lehet teljes. Egyértelmű tehát, hogy egy teljes komponens modellt csak egy magasabb absztrakciós szinten lehet megvalósítani.
Fogalmak – komponens modell Definiálja a komponensek struktúráját (Hogyan néz ki egy komponens?): interfészek konfiguráció kompozíció (Hogyan építkezünk belőlük?) viselkedését (Hogyan működnek?): életciklus-kezelés kommunikáció ... valamilyen formalizmust használva. A formalizmus fontos, különben nem beszélhetünk modellről.
Fogalmak – komponens framework A komponens modell implementációja Kezeli a komponensek függőségeit életciklusát (telepítés, indítás, leállítás, frissítés, eltávolítás) nem-funkcionális követelményeit (QoS, perzisztencia, naplózás, kommunikáció, biztonság, tranzakciók stb.) -> fw. szolgáltatások. Szebb nevén komponens konténer.
Fogalmak – Dependency Injection (DI) Tervezési minta Egyéb elnevezése: Inversion of Control (IoC) Adott objektum (szolgáltatás) létrehozását kiveszi a szolgáltatás igénylője (kliens) hatásköréből. A szolgáltatást a komponens konténer hozza létre, majd az arra mutató referenciát megfelelő módon (konstruktor, egyedváltozó, metódus vagy byte-kód beszúrással) átadja a kliensnek. CIA-zsargonnal élve: Don’t call me, we call you.
Fogalmak – Dependency Lookup Tervezési minta Egyéb elnevezései: Service Locator, Object Factory, Component Broker, Component Registry Adott objektum (szolgáltatás) létrehozását kiveszi a szolgáltatás igénylője (kliens) hatásköréből. A szolgáltatást a komponens konténer hozza létre és tárolja (registry), a kliens a konténer API-n keresztül érheti el az arra mutató referenciát (lookup).
Miért kell nekünk komponens modell? Mert lehetővé teszi a komponens alapú szoftverfejlesztést a komponens formátum szabványosítását, szabványos szolgáltatások kialakítását (COTS) a Java nyelv és VM hiányosságainak pótlását: kód-hordozhatóság (magasabb szintű absztrakció, konténerek között) verziókezelés (JAR-hell) alkalmazás-felügyelet … A Java nyelv nem ismeri a komponens koncepciót: az osztály túl kis egység (interfész, konfiguráció?) a package túl egyszerű (nincs mögötte a szükséges formalizmus - kötetlen struktúra, nem specifikált viselkedés) a class loader túl alacsony szintű a JAR file megfelelő lenne, de nincs megfelelően specifikálva, mi és milyen formában kerüljön bele
A múlt Kezdetben nem definiáltak komponens modellt Később: Java Beans, EJB 1.x, 2.x, … Problémák: túl specifikusak hiányzó verziókezelés nem alkalmazhatók széles körben (beágyazott eszközök – nagyvállalati felhasználás) Ez sajnos csökkenti a Java platform elfogadottságát (lásd Java vs. .NET viták – a .NET-ben határozottan jó koncepció az Assembly). A „házon belüli” (Sun) fejlesztések gyakori problémái.
Komponens modellek – DI framework-ök Struktúra: POJO/POJI modell (szolgáltatás = osztály [+ interfész]) Konfiguráció: Java annotációk és/vagy konfigurációs file stb. Kompozíció: Dependency Injection Életciklus-kezelés: nincs vagy eltérő implementációk Példaként a Spring-et és a Guice-t használom az elterjedtségük miatt. Életciklus-kezelés: A „nincs” annyit jelent, hogy legtöbb esetben a komponensek a konténer elindulásakor indulnak, leállításakor leállnak.
Komponens modellek – DI framework-ök A metamodell csak vázlatos, a koncepciót hivatott bemutatni.
Komponens modellek - OSGi Struktúra: POJO/POJI modell (szolgáltatás = osztály [+ interfész]) Konfiguráció: MANIFEST.INF, XML (pl. Declarative Services, Spring-DM, Extension Registry), opcionálisan Java annotációk (pl. Spring-DM) Kompozíció: Dependency Lookup (BundleContext) Dependency Injection: konstruktor, setter (Spring-DM), egyedváltozó, metódus (iPOJO) Életciklus-kezelés: szabványos (JSR 291) állapotok: installed, resolved, starting, active, stopping, uninstalled
Komponens modellek - OSGi
Komponens modellek – Java Module System Struktúra: POJO/POJI modell (szolgáltatás = osztály [+ interfész]) Konfiguráció: MANIFEST.INF, opcionálisan Java annotációk Kompozíció: Dependency Lookup Életciklus-kezelés: szabványos (JSR 277) állapotok: new, preparing, validating, resolved, ready, error A szabványtervezet egyelőre csak Early Draft verzió, így akár jelentős változások is lehetnek.
Komponens modellek - SCA Célja elsősorban a technológia-függetlenség és az interoperabilitás. Struktúra: POJO/POJI modell (szolgáltatás = osztály [+ interfész]) Konfiguráció: Java annotációk és XML Kompozíció: Dependency Injection (vagy más, a szabvány említi, de nem definiálja) Életciklus-kezelés: a szabvány nem definiálja, implementáció-specifikus
Komponens modellek - SCA
Spring - programozási modell POJO-k: public class Service { … } public class ServiceConsumer { private Service service; public void setService(Service service) { this.service = service; XML konfiguráció: <bean id=„service” class=„com.acme.Service” /> <bean id=„consumer” name=„consumer” class=„com.acme.ServiceConsumer”> <property name=„service” ref=„service”/> </bean> vagy annotációk: @Component public class Service { … } public class ServiceConsumer { @AutoWired private Service service; XML konfiguráció helyett természetesen Java annotációk is használhatók.
OSGi - programozási modell package com.acme.service; public class Service { … } public class ServiceActivator implements BundleActivator { public void start(BundleContext context) { Service service = new Service(); context.registerService(Service.class.getName(), service, null); public void stop(BundleContext context) { package com.acme.client; public class ConsumerActivator implements BundleActivator { Service service = (Service) context .getService(Service.class.getName()); Service bundle - MANIFEST.INF Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Service Plug-in Bundle-SymbolicName: Service Bundle-Version: 1.0.0 Bundle-Activator: com.acme.service.ServiceActivator Export-Package: com.acme.service … ServiceConsumer bundle - MANIFEST.INF Bundle-Name: ServiceConsumer Plug-in Bundle-SymbolicName: ServiceConsumer Bundle-Activator: com.acme.client.ConsumerActivator Import-Package: com.acme.service Az Activator-ok kézzel való létrehozása elkerülhető, ha nem az alapértelmezett (és maximum csak egyszerűbb alkalmazások számára javasolt) függőség-kezelést vagy a ServiceTracker-t választjuk.
SCA – programozási modell package services.account; @Remotable public interface AccountService{ public AccountReport getAccountReport(String customerID); } public class AccountServiceImpl implements AccountService { @Property private String currency = "USD"; @Reference private AccountDataService accountDataService; public AccountReport getAccountReport(String customerID) { …
SCA – programozási modell XML konfiguráció: <componentType xmlns=http://www.osoa.org/xmlns/sca/1.0 xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <service name="AccountService"> <interface.java interface="services.account.AccountService"/> </service> <reference name="accountDataService"> <interface.java interface="services.accountdata.AccountDataService"/> </reference> <property name="currency" type="xsd:string">USD</property> </componentType>
Összehasonlítás Szempontok, melyek szerint differenciálni lehet: Hordozhatóság Dinamikus modulkezelés (betöltés, eltávolítás, frissítés) Framework szolgáltatások Verziókezelés Elterjedtség, szabvány … javaslatok?
Hordozhatóság SCA OSGi: DI framework-ök Java Module System (JSR 277) beágyazott eszközök (otthon-automatizálás, járműipar, navigációs eszközök stb.), ME (JSR 232), SE (JSR 291), EE (pl. BEA) DI framework-ök SE, EE Java Module System (JSR 277) tervezés alatt, leginkább SE SCA EE több implementáció (SpringSource, IBM, Oracle stb.)
Dinamikus modulkezelés Spring, Guice, JSR 277: statikus, a framework/alkalmazás indításakor vagy alkalmazás által kezelt módon OSGi: teljesen dinamikus (futás közben is), a framework alapszolgáltatása SCA: implementáció-specifikus
Framework szolgáltatások DI framework-ök: egyedi megoldások OSGi: szabványban rögzítve (JSR 232, JSR 291) Java Module System: a szabvány nem tartalmazza, más JSR-ek (pl. JSR 294) specifikálják majd SCA: nem része a szabványnak, implementáció-specifikus
Verziókezelés Spring, Guice: nincs OSGi, Java Module System: szabványos, modul szintű SCA: nincs specifikálva, más absztrakciós szint (fw-implementáció)
Elterjedtség, szabvány Spring: nagy felhasználói bázis (SE/EE) első verzió: 2002 kvázi szabvány (EE) Guice: terjedőben (SE/EE) első verzió: 2007 OSGi: viszonylag nagy felhasználói bázis (beágyazott/ME, SE, EE) első implementáció: 2000 szabványosított: JSR 232 (ME), JSR 291 (SE) Java Module System: csak szabványtervezet (JSR 277, early draft) nincs publikus implementáció SCA: több implementáció (leginkább EE) OSOA szabvány, 2005 (v0.9, az első publikus specifikáció), 2007 (v1.0)
A jelen Nagyon hasonló megoldások Spring, OSGi gyors térhódítása együttműködés: Spring Dynamic Modules Guice terjedése együttműködés: Guice-OSGi, Spring Java Module System szabványosítás alatt, publikus implementáció nincs együttműködés: OSGi (javaslat) Egyre több SCA implementáció Szabványháború (JSR 291, JSR 277)
A jövő? A komponens-alapú alkalmazások egyértelmű terjedése Szabványosítás (JCP?) vagy kvázi-szabványok? Java 7: JSR 277 vagy OSGi ? Együttműködő implementációk (pl. SCA) vagy Universal Middleware?
Hivatkozások Google Guice (http://code.google.com/p/google-guice/) Guice-OSGi (http://wiki.ops4j.org/confluence/display/ops4j/Guice-OSGi) Java Module System (http://www.jcp.org/en/jsr/detail?id=277) OSGi (http://www.osgi.org/) Service Component Architecture (SCA) (http://www.osoa.org/display/Main/Service+Component+Architecture+Home) Spring (http://www.springframework.org/) Spring Dynamic Modules (http://www.springframework.org/osgi/)
Köszönöm a figyelmet!