Dzięki serii artykułów Getting started with OSGi, w ostatnich dniach coraz więcej mówi się na temat OSGi. Ponieważ zajmuję się od jakiegoś czasu tym tematem, postanowiłem - w myśl zasady Jak wszyscy to i Wania - dorzucić coś do tego co zostało już napisane.
Zanim przejdę dalej, zachęcam do lektury krótkiego wprowadzenia w temat na blogu Jacka Laskowskiego, oraz wspomnianej wyżej serii artykułów.
Rzecz, o której chcę napisać, to możliwość śledzenia aktywności interesujących nas serwisów OSGi. Wyobraźmy sobie, że w momencie pojawienia się serwisu pewne przyciski aplikacji stają się dostępne, a w momencie zniknięcia serwisu - niedostępne. Możemy też skorzystać z usług serwisu tuż przed jego wyłaczeniem oraz natychmiast po jego pojawieniu się.
Na początku utworzymy trzy nowe projekty wtyczek: osgi1, osgi2, osgi3 w następujący sposób.
W projektach osgi2 i osgi3 dodajemy pakiety osgi.iface oraz osgi.impl. W pakietach osgi.iface umieszczamy następujący interfejs:
package osgi.iface; public interface OsgiTest { String show(); }
Natomiast w pakietach osgi.impl następującą klasę:
package osgi.impl; import osgi.iface.OsgiTest; public class OsgiTestImpl implements OsgiTest { public String show() { return "Hej! Jestem osgi2."; } }
Podstawiając oczywiście w projekcie osgi3 ciąg "Hej! Jestem osgi3." w zwracanym stringu.
Teraz musimy zarejestrować nasze serwisy przy starcie wtyczki. W klasach Activator projektów osgi2 i osgi3 dodajemy następujący kod:
public void start(BundleContext context) throws Exception { System.out.println("Witaj, jestem " + this.getClass().getName()); OsgiTest osgiTest = new OsgiTestImpl(); registration = context.registerService( OsgiTest.class.getName(), osgiTest, null); System.out.println(this.getClass().getName() + ": Serwis zarejestrowany"); }
Natomiast przy zatrzymaniu, wyrejestrowujemy serwis:
public void stop(BundleContext context) throws Exception { System.out.println("Pa pa "+ this.getClass().getName()); registration.unregister(); System.out.println(this.getClass().getName() + ": Serwis wyrejestrowany"); }
Następnie w metodzie start klasy Activator projektu osgi1 umieszczamy następujący kod:
final ServiceTracker tracker = new ServiceTracker(context, "osgi.iface.OsgiTest", new ServiceTrackerCustomizer() { public Object addingService(ServiceReference reference) { System.out.println("pojawił się nowy serwis: " + reference); Object service = context.getService(reference); if (service != null) { try { Method method = service.getClass().getMethod( "show", new Class[]{}); String wynik = (String) method.invoke(service, new Object[]{}); System.out .println("korzystam z niego:" + wynik); } catch (Exception e) { e.printStackTrace(); } } return service; } public void modifiedService(ServiceReference reference, Object service) { } public void removedService(ServiceReference reference, Object service) { System.out.println("serwis zostanie usuniŕty: " + reference + ": " + service); if (service != null) { try { Method method = service.getClass().getMethod( "show", new Class[]{}); String wynik = (String) method.invoke(service, new Object[]{}); System.out .println("korzystam z niego:" + wynik); } catch (Exception e) { e.printStackTrace(); } } }; }); tracker.open();
Teraz już możemy uruchomić nasz przykład. Klikamy Wykonaj.../Środowisko Equinox OSG/Nowa konfiguracja startowa. Na zakładce wtyczki zaznaczamy nasze 3 wtyczki i klikamy wykonaj. Na konsoli powinniśmy zobaczyć coś takiego:
osgi> Witaj, jestem OSGi1! Witaj, jestem osgi2.Activator pojawił się nowy serwis: {osgi.iface.OsgiTest}={service.id=20} korzystam z niego:Hej! Jestem osgi2. osgi2.Activator: Serwis zarejestrowany Witaj, jestem osgi3.Activator pojawił się nowy serwis: {osgi.iface.OsgiTest}={service.id=21} korzystam z niego:Hej! Jestem osgi3. osgi3.Activator: Serwis zarejestrowany
Jak widać nasz pierwszy plugin skorzystał z dwóch serwisów dostarczających implementację interfejsu osgi.iface.OsgiTest. Listę aktualnie dostępnych serwisów zwraca nam metoda getService klasy ServiceTracker.
Spróbujmy teraz zatrzymać i uruchomić jeden z serwisów:
osgi> ss Framework is launched. id State Bundle 0 ACTIVE system.bundle_3.2.1.R32x_v20060919 8 ACTIVE osgi1_1.0.0 9 ACTIVE osgi2_1.0.0 10 ACTIVE osgi3_1.0.0 osgi> stop 9 Pa pa osgi2.Activator serwis zostanie usunięty: {osgi.iface.OsgiTest}={service.id=22}: osgi.impl.OsgiTestImpl@c5c3ac korzystam z niego:Hej! Jestem osgi2. osgi2.Activator: Serwis wyrejestrowany osgi> start 9 Witaj, jestem osgi2.Activator pojawił się nowy serwis: {osgi.iface.OsgiTest}={service.id=23} korzystam z niego:Hej! Jestem osgi2. osgi2.Activator: Serwis zarejestrowany osgi> close Pa pa osgi3.Activator serwis zostanie usunięty: {osgi.iface.OsgiTest}={service.id=21}: osgi.impl.OsgiTestImpl@17fa65e korzystam z niego:Hej! Jestem osgi3. osgi3.Activator: Serwis wyrejestrowany Pa pa osgi2.Activator serwis zostanie usunięty: {osgi.iface.OsgiTest}={service.id=23}: osgi.impl.OsgiTestImpl@18385e3 korzystam z niego:Hej! Jestem osgi2. osgi2.Activator: Serwis wyrejestrowany Pa pa OSGi1!!
Jak widać nasz plugin jest w stanie reagować na start i zatrzymywanie śledzonych serwisów.
Mam nadzieję, że ten przykład zachęci was do zainteresowania się bliżej standardem OSGi.
Comments
OSGi - moje trzy grosze...
Witam,
Moje trzy grosze odnośnie OSGi....
W pełni popieram entuzjazm Jacka Laskowskiego odnośnie OSGi, opisywany w jego Notatniku Projektanta Java EE. Chciałbym podzielić się moim rozumieniem OSGi oraz paroma komentarzami odnośnie tej technologii:
1. dla mnie OSGi stanowi ulepszenie koncepcji classloader?a w Java. W OSGi aplikacje (i usługi) są zorganizowane w postaci komponentów (bundle). Klasy (zgrupowane w package) są opakowane w postaci bundle?a (JARa) i mogą być w precyzyjny sposób (dużo bardziej elastyczny niż w czystej Javie) udostępniane na zewnątrz (eksportowane). Także zależności między komponentami mogą być elastycznie opisywane ? zwłaszcza z uwzględnieniem wersji i reguł bezpieczeństwa (tak jak to napisał Neil Bartlett, OSGi wprowadza do Java nową warstwę ochrony kodu). Środowisko OSGi dba o rozwiązywanie tych zależności i ich kontrolę. Od classloader?a podejście OSGi odróżnia także dynamizm ? bez restartu JVM ani specjalnych zabiegów można instalować, uruchamiać, stopować i odinstalowywać poszczególne komponenty. Znowu, OSGi dba w takim dynamicznym środowisku o poprawne zachowanie się komponentów, które od siebie zależą. Zdefiniowany jest jasno cykl życia komponentu ? co między innymi ułatwia wstawianie własnej logiki obsługi wybranych zdarzeń (np. co się ma stać jeśli komponent jest zatrzymywany).
2. chciałbym przy tym podkreślić że komponent (bundle) obejmuje zwykle package - grupę klas ? jedną lub (zwykle) więcej klas. I to jest przyjęty poziom granulacji OSGi ? tak trzeba też partycjonować aplikację (a dokładnie jej poszczególne warstwy). Dla porównania Spring w kontekście OSGi obejmowałby przede wszystkim konfigurację klas w ramach jednego bundle?a (a za jakiś czas także między bundle'ami). O Springu i OSGi jeszcze trochę później.
3. OSGi pozwala na udostępnianie w ramach JVM współdzielonych usług. Czyli OSGi popularyzuje koncepcję architektury zorientowanej na usługi ? tak, tak: SOA. Tyle że w mikroskali ? podkreślam w ramach JVM. "Klasyczne" rozumienie SOA, to skala makro ? czyli usługi udostępniane w ramach całego środowiska IT organizacji dla różnych aplikacji. OSGi musi zatem udostępniać w ramach JVM typowe komponenty występujące w SOA: m.in. rejestr usług (po to, aby można było odszukać usługę spośród potencjalnie setek innych, odpytać o jej metadane, interfejs, wybrać jej implementację ? potencjalnie może być wiele implementacji ? wszystko w dynamiczny sposób). Inny przykład z ?klasycznego? SOA, to mechanizm pozwalający na rozluźnienie zależności między konsumentem a dostawcą usługi oraz routing zapytań (np. do właściwej implementacji dostawcy usługi) ? coś co w SOA zwykle wykonuje szyna usługowa (ESB). Tutaj ? w mikroskali JVM - robi to framework OSGi. Implementacja usługi może być dynamicznie ładowana ? hot swap, a nawet potencjalnie ściągana ze zdalnych lokalizacji. Tutaj także podkreślam, że implementacja usługi składa się zwykle z wielu klas. Po to, aby konfigurować relacje (zamiast zaszywać je w kodzie) między klasami w implementacji usługi warto posiadać kontener IoC w rodzaju Springa.
4. Między innymi za namową ludzi z BEA ludzie ze Springa utworzyli projekt Spring-OSGi. Podobnie jak dla innych aplikacji, Spring pozwala na łatwiejsza implementację komponentów OSGi ? dzięki IoC, AOP, czy udostępnianiu w spójny sposób prostszego interfejsu do pracy z zasobami typu JDBC, JEE, JMS, itd. Po drugie, Spring ma znacznie bardziej zaawansowane mechanizmy wyrażania zależności niż to co dzisiaj oferuje OSGi. I tak też rozumiem pomysł wzbogacenia OSGi o te mechanizmy, tak aby łatwiej konfigurować zależności pomiędzy bundle?ami oraz pomiędzy usługami OSGi. Mam zatem odmienne zdanie niż Jacek i nie przeciwstawiałbym OSGi przeciwko Springowi (notabene także nie przeciwstawiam EJB3 versus Spring ? polecam zresztą: Pitchfork. I myślę że rok 2007 będzie wciąż rokiem Springa (być może rokiem Springa i JEE 5, zwłaszcza Springa i JPA) oraz że 2008 będzie rokiem Springa i JEE5 i OSGi. Co ważniejsze Spring pokonał już barierę wejścia do środowisk korporacyjnych, czego o wielu innych frameworkach (w tym Hibernate) nie można jeszcze (już?) powiedzieć (głośność o danej technologii w sieci nie przekłada się na jej popularność w rozwiązaniach korporacyjnych ? korporacje, to po prostu inny świat). Dlaczego dopiero 2008 ? Myślę, że trzeba jeszcze trochę poczekać na wygrzanie się OSGi, a zwłaszcza jego ?otoczki? ? narzędzi, dobrych praktyk, związanych z OSGi frameworków aplikacyjnych, integracji z usługami serwerów aplikacyjnych (Java EE), udostępnienia łatwego modelu OSGi dla budowy aplikacji osadzanych na serwerach aplikacyjnych, itd. Niektóre ze ?standardowych? usług OSGi (HTTP, Preferences, ...) muszą też uzyskać akceptację szerszego grona ludzi i zostać zaimplementowane w popularnych implementacjach OSGi (np. w Eclipse Equinox) lub zmapowane do istniejących rozwiązań.
5. OSGi będzie widoczny nie tylko na poziomie aplikacji oraz środowisk deweloperskich (np. Eclipse, Equinox). Także infrastruktura aplikacyjna ? np. serwery aplikacyjne, rozwiązania integracyjne, różne silniki wykonawcze ? będą oparte o OSGi. Serwery aplikacyjne "przykrajane" pod konkretne potrzeby z łatwym skalowaniem funkcjonalności w górę i w dół (czyli zarówno enterprise jak i embedded) ? No problem. Czy doprowadzi to do sytuacji, w której będzie można samodzielnie złożyć sobie np. serwer aplikacyjny z komponentów (bundle?i) różnych dostawców ? Hmm... teoretycznie tak, wystarczy przecież tylko spełnić zależności między bundle?ami. W praktyce ? zwłaszcza w rozwiązaniach klasy enterprise ? proces ten będzie dosyć żmudny, gdyż trzeba będzie znacznie więcej czasu poświęcić na testy integracyjne, certyfikacje zgodności, itp. Nie znika też problem poprawności działania różnych wersji implementacji poszczególnych komponentów, choć znacznie łatwiej będzie tym zarządzać. Model supportu takiego rozwiązania też będzie dużym wyzwaniem.
Odpowiadając na pytanie Gab7: do czego OSGi w konkretnych aplikacjach ? Od OSGi funkcjonalność aplikacji się nie powiększy. OSGi ma pozwolić na większą modularność aplikacji, łatwiejsze zarządzanie tymi modułami i ich wersjami, w dynamiczny sposób, tj. m.in. bez potrzeby restartu JVM. Wyobraź sobie aplikację, w której funkcjonalność jest dystrybuowana i uaktualniana w taki sposób jak w Eclipse IDE ? poprzez pluginy. I to także dla aplikacji serwerowych. To jest (a raczej będzie za jakiś czas) bardzo elastyczne podejście. Takie podejście jak w OSGi przyczyni się też do budowania aplikacji o lepszej architekturze. Modularność zwykle też wpływa pozytywnie na sam proces budowy, rozwoju i utrzymania aplikacji. Zalety (i wady) OSGi są bardzo podobne jak w przypadku SOA, z tym że OSGi dotyczy mikroskali (pojedynczej aplikacji), a SOA makroskali (wielu aplikacji). I chodzi mi oczywiście o SOA z naciskiem na A ? czyli architekturę.
Pozdrawiam,
Waldek
BEA
Przykłady != Pomysły
Fantazjowanie na temat potencjalnych zastosowań OSGi jest z pewnością interesującym zajęciem i przyjemnym.
Jednak mnie bardziej zależało na konkretnych przypadkach użycia, wynikających z potrzeb klienta lub sytuacji. Twój przykład z przyciskiem jest czymś namacalnym, ale zbyt mało mówi o samym problemie. Spodziewałem się odpowiedzi mniej wiecej takiej. Np. tworzymy nowoczesny system ERP od podstaw. Mamy takie i takie problemy z występowaniem wielomu podsystemów/modułów. Obecne rozwiązania typu EJB, Spring, czy tez ESB nie zapewniają tego i tego. Wybraliśmy OSGi bo: np. się szybciej i łatwiej pisze. Albo bo zapewnia to, tamto i siamto.
Mimo wszyskto dziekuję za odpowiedź. Będę również wdzięczny za ew. dodatkowe wyjaśnienia.
Pozdrawiam.
Eclipse RCP => OSGi ;)
Aktualnie jesteśmy w bardzo wstępnej fazie projeku i nie mamy jeszcze wielu konkretnych - działających przykładów.
Warstwa kliencka naszej aplikacji powstaje na bazie Eclipse RCP, więc wybór OSGi po stronie klienta jest dla nas krokiem bardzo naturalnym. Aktualnie OSGi stosujemy tylko w kliencie - na serwerze programujemy w EJB3.
Myślę, że w miarę rozwoju naszej aplikacji będę w stanie podzielić się bardziej konkretnymi przypadkami użycia.
Pozdrowienia!
To brzmi przyjemniej
Dzieki i zycze powodzenia.
Pozdrawiam.
Przepraszam, że po tak
Przepraszam, że po tak długim czasie, ale ...
Pracujemy nad projektem sporej aplikacji ERP. Pomysłów na użycie OSGi jest naprawdę bardzo dużo (wciśnij przycisk - fantazja ;) )
Przykładowe zastosowanie, to możliwośc sprawdzania w kartotece towarowej stanu towaru u dostawców.
Jeśli np. pojawią się problemy z dostepem do aplikacji dostawcy, przycisk do uruchomienia tej funkcjonalności może stać się nieaktywny.
Pomysłów mamy naprawdę wiele, technologia jest bardzo ciekawa i obiecująca.
Pozdrowienia!
Jakieś przykłady zastosowań?
W jakich projektach stosujesz OSGi? Chodzi mi o branżę, rodzaj aplikacji, mniej więcej funkcjonalność, i wielkość aplikacji. Jakie problemy rozwiązało Ci korzystanie z OSGia?
Pozdrawiam,
Gabriel.