27 lutego 2008

Pora na łyk OSGi - rozdział 1. Wprowadzenie

Nie mogłem się oprzeć, aby nie zajrzeć do specyfikacji OSGi. Co jakiś czas to tu, to tam pojawiają się jakieś ciekawostki z nim związane, a na koniec jeszcze Daniel ze swoim komentarzem dotyczącym Wicketa, Springa i właśnie OSGi. Zaczęło się całkiem niewinnie:

Jeżeli chodzi o samego Wicketa, to korzystam z niego od prawie roku (w połączeniu m.in. ze Springiem i OSGi) i mogę tylko powiedzieć, że nie żałuję decyzji o jego wyborze. Polecam ;)

Okazuje się, że integracja nie jest czymś nadzwyczajnym w/g Daniela, a korzyści płynące z jej zastosowania są ogromne (tak, brzmi jakby za chwile miało trzęsienie ziemi nastąpić, albo podobnie, ale "ogromne" najbardziej mi w tym kontekście leżało). Dopiero, co wdrażam się w Wicketa, od kilku dni mam go uruchomionego ze Springiem, więc pozostaje jedynie włączyć OSGi. Hmmm, łatwo powiedzieć, trudno zrobić. Najlepiej, więc zacząć od wprowadzenia Daniela w jego kolejnym komentarzu. Ten komentarz sam w sobie zasługuje na pojawienie się jako wpis w moim Notatniku, więc nie zawaham się go użyć:

Jak widać po Twoich wpisach OSGi nie jest Ci obce, dlatego zdziwiło mnie zdanie: "to nie wiem jaki miałby zysk wdrożenie OSGi mając na pokładzie Spring + Wicket." :) Przecież korzyści jakie płyną z wykorzystania OSGi są w miarę jasne, chociażby podstawowa: dobre wsparcie dla modularyzacji aplikacji.

Wicket z OSGi integruje się dosyć łatwo. Można to zrobić publikując servlet wicketowy jako serwis OSGi, który następnie zostanie zlokalizowany przez odpowiedni OSGi HTTP service (np. standardowo dostępny Jetty, jeżeli korzystamy z Equinoxa: http://www.eclipse.org/equinox/server/) i zarejestrowany. Oczywiście możemy włączać/wyłączać bundla z naszą aplikacją webową w trakcie działania aplikacji, możemy też w jednym środowisku uruchomić wiele takich aplikacji jednocześnie. Cała integracja sprowadza się w praktyce do zaimplementowania kilku (w moim przypadku pięciu) klas: "osgi-owych" wersji WicketServlet i WicketFilter, OsgiWicketServiceRegistration - zawierającą info o rejestrowanym serwisie, no i jeszcze proste application factory i application factory bean (aplikację konfigurujemy za pomocą Springa, jako bean będący właśnie taką faktorką), który w praktyce rejestruje i wyrejestrowywuje serwis z naszą aplikacją. Dalej już korzystamy ze standardowych mechanizmów Wicketa. Jest jeszcze projekt pod egidą OPS4J - Pax Wicket, gdzie też jest zrobiona taka integracja.

Kilka dni temu ukazała się oficjalna wersja Spring Dynamic Modules (wcześniej Spring-OSGi), która ułatwia pewne rzeczy tj. definiowanie i konsumowanie serwisów OSGi (są tu pewne analogie do declarative services). Jeżeli używamy Springa, to pod OSGi wykorzystanie tych mechanizmów wydaje się naturalne. Serwisy definiujemy jako normalne beany w Springu i publikujemy za pomocą elementu [osgi:service] (oczywiście wszedzie zamiast [ ] wstaw < >), np.:
[osgi:service interface="com.naszafirma.najlepiejJakisInterface" ref="beanZeSpringa" /]
a tam gdzie korzystamy z tego serwisu, uzyskujemy do niego dostęp za pomocą:
[osgi:reference interface="com.naszafirma.najlepiejJakisInterface" id="nazaBeanaPodJakaBedzieOnWidoczny" /]
Proste prawda ;). Ciekawe porównanie sposobów obsługi serwisów jest tu: http://www.eclipsezone.com/articles/extensions-vs-services/

Na koniec integracja Wicketa ze Springiem. Najwygodniej jest chyba korzystać z adnotacji @SpringBean. Jeżeli mamy zdefiniowanego beana o [bean id="contactStore" class="com.naszafirma.OracleDataStore" /], gdzie com.naszafirma.OracleDataStore implementuje interfejs DataStore, wtedy wstrzyknięcie beana do dowolnego komponentu (np. strony, czy panelu) wygląda tak:

class MyPanel extends Panel {
@SpringBean(name = "contactStore")
private DataStore contactStore;

public MyPanel(String id) {
super(id);
contactStore.someMethod();
}
}

czyli już w konstruktorze mamy dostęp do tego beana. Oczywiście możemy go wstrzykiwać jako interfejs albo klasę. Wicket utworzy nam dla niego odpowiednie proxy, które będzie serializowalne w komponencie, natomiast nie będzie serializowalny bezpośrednio wstrzykiwany bean. Jeżeli chodzi o użycie tego w OSGi to nie ma problemu dopóki nie podzielimy aplikacji na więcej modułów i gdy pojawia się wiecej niż jeden application context (w praktyce każdy bundle ma swój własny). Ale to już inna historia, o której może innym razem ;).

To brzmi jak jakieś zaklęcie (!) Dorzuć szczyptę skrzydła muchy, kropelkę jadu, trochę pajęczyny, itp. Pewnie, że proste, ale dla niektórych to nawet zrobienie jajecznicy zakrawa na wyczyn i nagrodę Nobla. Nie, Daniel, nie chcę Cię urazić, ale wybacz, połowy nie zrozumiałem. Jakkolwiek z "lotu ptaka" jestem w stanie sobie to jakoś wyobrazić, to żeby to zaprezentować w działaniu. Co to, to nie...jeszcze.

Jakby tego było mało pojawił się nowy test OSGI basic na javaBLACKbelt, o którym już wspominałem i już po pierwszym pytaniu...WPADKA (!) Błędna odpowiedź, więc wypad, idź się podszkolić.

Na koniec moich wynurzeń odnośnie wzrastającej świadomości programistów Java architekturą OSGi jako metodą na zwiększenie modularności aplikacji natrafiłem na zapowiedź serii artykułów w JavaWorld. Swego czasu JavaWorld było kopalnią wiedzy, jednakże podupadło i dopiero od niedawna ponownie zaczynają się pojawiać ciekawe artykuły. I tu proszę:

Hello, OSGi
First article in a three-part series introducing the Open Source Gateway Initiative. - UPCOMING ON JAVAWORLD's Enterprise Java Newsletter.


Czyż nie zabawnie?

Wczoraj więc, na dobranoc, postanowiłem zajrzeć do specyfikacji OSGi. Całość to jedynie 288 stron, więc możnaby to w jeden dobry wieczór "obrobić". Mnie starczyło sił na początkowy rozdział wprowadzający 1 Introduction. Dobrze jest go przeczytać przez wszystkich parających się Javą w jakikolwiek sposób, aby rozeznać się naprędce, co to cudeńko potrafi. Kilka słów o zaletach, zero wad, więc w zasadzie nie ma złudzeń - trzeba zagłębić się w temat. Z rzeczy, które wydały mi się wartościowe to przede wszystkim:
  • OSGi Service Platform (w skrócie OSGi) to otwarta specyfikacja architektury dostarczania zarządzanych usług poprzez sieć
  • Ostatnia wersja specyfikacji to 4.1
  • Zakłada się, że usługi będą funkcjonowały w różnych środowiskach - od urządzeń domowych, w samochodzie, telefonów komórkowych, komputerów stacjonarnych, itp.
  • Głównym graczem w architekturze OSGi jest szkielet aplikacyjny w Javie rozszerzający jej mechanizm bezpieczeństwa i modularyzacji
  • Podstawową jednostką w OSGi jest pakunek (ang. bundle) - zwarty acz rozbudowywalny moduł usługowy
  • Urządzenia OSGi mają możliwość pobrania i zainstalowania pakunków OSGi oraz ich usunięcia na żądanie
  • Platforma OSGi umożliwia dynamiczne uaktualnianie pakunków podczas działania systemu
  • OSGi udostępnia mechanizm zależności między pakunkami i dostarczanymi przez nie usługami
  • Wyróżnia się następujące warstwy w platformie OSGi:
    • Security Layer - Warstwa Bezpieczeństwa
      • Rozszerza mechanizm bezpieczeństwa w Javie 2 m.in. przez udostępnienie mechanizmów bezpiecznego opakowania ("gwarancja pierwszego otwarcia")
    • Module Layer - Warstwa Zarządzania Modułami / Warstwa Modułów
      • Udostępnia model modularyzacji w Javie i kontroli dostępności pakunków
      • Udostępniane są jedynie zadeklarowane pakiety klas (a tym samym ukrywane są te, które bezpośrednio nie są publiczne - mowa o pakietach Java a nie klasach czy interfejsach)
      • Nie wymaga Warstwy Rozwojowej i Warstwy Kontroli Usług
    • Life Cycle Layer - Warstwa udostępniająca mechanizm Kontroli Rozwoju pakunków / Warstwa Rozwojowa
      • Udostępnia interfejs programistyczny API do zarządzania pakunkami w warstwie modułów
      • Udostępnia mechanizm uruchamiania/zatrzymywania oraz instalacji/aktualizacji/odinstalowania
      • Udostępnia model zdarzeń i jego interfejs programistyczny API
      • Wymaga Warstwy Modułów, podczas gdy Warstwa Bezpieczeństwa jest opcjonalna
    • Service Layer - Warstwa Komunikacji/Kontroli Usług (pakunków) / Warstwa Usługowa
      • Udostępnia mechanizm komunikacji między pakunkami
      • Udostępnia interfejs programistyczny API, który pozwala na komunikację z jej interfejsem ukrywając implementację
      • Udostępnia możliwość dostarczania implementacji podczas działania pakunku
      • Udostępnia model programistyczny, który umożliwia dostosowywanie implementacji pakunków do dostępnych zasobów środowiska uruchomieniowego (urządzenia z dostępnymi zasobami, w którym pakunki są uruchomione)
      • Udostępnia mechanizm wykrywania implementacji pakunków przez rejestr usług OSGi
      • Pakunki rejestrują się, otrzymują informacje zwrotne od środowiska o stanie innych pakunków z możliwością dynamicznej rekonfiguracji podczas działania systemu
    • Actual Services - Warstwa Pakunków
  • Wymaga się, aby osoby rozpoczynające swoją przygodę z OSGi jako programiści pakunków mieli większe niż przeciętne doświadczenie programistyczne w Javie, ze szczególnym naciskiem na mechanizm ładowania klas, odśmiecania, bezpieczeństwa oraz ładowania bibliotek natywnych (nie ma lekko, jak widać).
Ciekaw jestem ilu z Was para się OSGi i do czego tę architekturę wykorzystujecie? Zawsze miałem wrażenie, że OSGi to jakaś bardzo wyrafinowana i specjalistyczna architektura, a tu proszę Daniel wykorzystuje ją do udoskonalenia aplikacji opartej o Wicket wspartej przez Spring Framework. Ech, w jakiej to człowiek niewiedzy żył przez lata.