30 września 2008

Repozytoria pakunków OSGi

1 komentarzy
Istnieje kilka repozytoriów pełnoprawnych pakunków OSGi (z odpowiednimi nagłówkami w manifeście) dla popularnych projektów otwartych:
Naturalnym jest, że skoro pakunki OSGi są zwykłymi plikami jar z odpowiednimi nagłówkami w manifeście (cf. Kolejny łyk OSGi - rozdział 3. Warstwa modułowa) dowolne repozytoria mavenowe (np. http://repo1.maven.org/maven2/) lub dowolne inne udostępniające jary, mogą być używane przy zestawianiu środowiska z wymaganymi zależnościami. Problemem jest określenie zależności między pakunkami poprzez nagłówki Import-Package, Export-Package, Ignore-Package, Private-Package, DynamicImport-Package i in. dla zwykłych plików jar, co nie jest obsługiwane przez Platformę OSGi bez dodatkowej pracy przy ich konfiguracji jako pakunki. Właśnie to jest zaletą pobrania plików jar z w/w repozytoriów - posiadanie gwarancji, że są one poprawnymi pakunkami. Założeniem repozytoriów jest udostępnianie poprawnie skonfigurowanych pakunków ze wszystkimi wymaganymi nagłówkami. Jako, że są to oddzielne repozytoria, zarządzane przez różne osoby, czasami prowadzi to do sytuacji, gdzie pakunek X w repozytorium R1 ma inne wymagania niż pakunek X w repozytorium R2 (niestety w tej chwili nie mogę znaleźć informacji o zgłoszonej rozbieżności między Orbit a BRITS). Światło na ich przydatność może rzucić wątek - BRITS vs. Temporary Spring-DM Repo, gdzie mimo prowadzenia dwóch repozytoriów przez pojedyńczą firmę SpringSource, nawet one mają niepoprawnie zdefiniowane pakunki.

Rozwiązaniem rozmieszczenia pakunków w repozytorium jest specyfikacja OSGi RFC 112 Bundle Repository. Innym sposobem zaradzenia problemom z nieścisłymi deklaracjami pakunków jest projekt Pax URL, który pozwala na instalację dowolnego pliku jar dostępnego poprzez inne protokoły dostępu niż domyślne http czy file, np. classpath, mvn, wrap lub narzędzie bnd. Bez względu jakiego narzędzia zastosujemy, część pracy i tak będziemy musieli wykonać samodzielnie, np. przy wykorzystaniu mechanizmu prześwietlania w Javie (Reflection API), gdzie nazwa klasy podawana jest niejawnie. W takiej sytuacji skorzystanie z gotowego pakunku dla popularnego projektu otwartego z w/w repozytoriów może być najmniej czasochłonnym rozwiązaniem (jeśli istnieje).

Zabawa dla wytrwałych i dociekliwych: Co oznacza skrót BRITS będący alternatywną nazwą dla repozytorium SpringSource Enterprise Bundle Repository? (odpowiedzi można szukać w SpringSource Application Platform ships).

29 września 2008

Eclipse IDE 3.5M2 a Eclipse Equinox i OSGi R4.2

2 komentarzy
Dzisiaj, podczas pobierania pełnej wersji Equinoksa (wraz ze wszystkimi dostępnymi pakunkami) - eclipse-equinox-3.5M1.zip pojawił się poniższy komunikat:

The Equinox downloads are meant as a base for building OSGi applications. As such, they do not include an application of their own and simply running the framework will do nothing.

Teraz już wiem, co autorzy mieli na myśli. Po prostu pobieram samo środowisko uruchomieniowe dla pakunków OSGi (w świecie Eclipse będą to wtyczki), bez których nie ma co oczekiwać funkcjonalności oferowanej przez Eclipse IDE. Podobnie jak z serwerem aplikacyjnym Java EE 5, bez aplikacji korporacyjnych, nie ma czego więcej oczekiwać od niego, poza udostępnieniem usług, na bazie których można je konstruować. Dodatkowo, komunikat może być o tyle ważny, gdyż po pobraniu paczki Eclipse Equinox 3.5M1 i rozpakowaniu, pojawi się katalog eclipse z podkatalogami features oraz plugins, co idealnie odpowiada strukturze bogatego funkcjonalnie Eclipse IDE (w końcu to nic innego jak zestaw wtyczek w katalogu plugins uruchamianych na Equinoksie).

Uważni obserwatorzy projektu Eclipse IDE zauważyli zapewne pojawienie się wersji Eclipse IDE 3.5M2, w której pojawiły się zmiany w obszarze Equinoksa (opisane w dokumencie Eclipse 3.5 M2 - New and Noteworthy dla Equinox):

Security Manager enhancements
This milestone includes an implementation of RFC 120 from the OSGi R4.2 draft specification. RFC 120 specifies enhancements to the Conditional Permission Admin service which is used to manage the permissions assigned to bundles. The enhancements include adding the ability to grant or deny permissions based on conditions, and to manage conditions as an ordered list of rules. For more information see the OSGi R4.2 draft spec.


oraz

New publisher bundle
p2 has introduced a new bundle called the publisher, which provides infrastructure for generating, packaging, and publishing metadata and artifacts into p2 repositories. The publisher provides an extensible API that clients can extend to perform customized publishing to repositories, and includes an advice mechanism for injecting additional metadata into the generation and packaging process.


Nie powinno dziwić, że Equinox przewodzi peletonowi platform OSGi zabierając się za realizację specyfikacji OSGi R4.2, która jakkolwiek w fazie szkicu, potrzebuje środowiska referencyjnego, aby pomóc w akceptacji proponowanych funkcjonalności przez programistów. Dla Java EE 5 referencyjną implementacją jest GlassFish, a dla OSGi jest nią Eclipse Equinox. Zastanawiam się jednak, czy powinienem prowadzić doświadczenia z Equinoksem dystrybuowanym w ramach Eclipse IDE (org.eclipse.osgi_3.5.0.v20080916-2300.jar), czy pobierać bezpośrednio ze strony domowej Eclipse Equinox (org.eclipse.osgi_3.5.0.v20080804-1730.jar). Aktualność samodzielnego Equinoksa nie pozostawia złudzeń - ten dystrybuowany z Eclipse jest aktualniejszy oraz gwarantuje się jego działanie przez włączenie do Eclipse IDE, więc od razu przechodzę na niego. Kilka dni temu próbowałem pobrać wersję Eclipse Equinox 3.5M2 i niestety, ale kończyło się na "404 File Not Found". Może jutro?

p.s. Od momentu zainteresowania OSGi doszła mi kolejna sekcja, którą monitoruję pod kątem zmian w Eclipse - sekcja "Equinox" w "New and Noteworthy". A u Ciebie? ;-)

28 września 2008

Katalog plugins i automatyczna instalacja pakunków OSGi na Equinoksie

2 komentarzy
Już kiedyś wspominałem o tym dokumentcie - Equinox QuickStart Guide - ale nigdy jakoś nie usiadłem nad nim i dokładnie przeanalizowałem jego treści. Tym razem jednak, po kilku dniach zestawiania potrzebnych pakunków do uruchomienia Spring-DM 1.2.0-m2-SNAPSHOT na Eclipse Equinox i przekroczeniu 10 pakunków koniecznych do jego uruchomienia, stwierdziłem, że wystarczy tych ręcznych robótek i pora skrócić moje cierpienia - pójść po rozum do głowy i skorzystać z ułatwień, które są na wyciągnięcie ręki - automatyczne uruchamianie pakunków przy starcie Equinoksa. Przy okazji, poznając działanie Equinoksa poznajemy działanie całego Eclipse, który mechanizm wtyczek oparł całkowicie o OSGi z Equinox w roli środowiska uruchomieniowego.

Podczas uruchamiania Equinoksa poleceniem
 java -jar org.eclipse.osgi_3.5.0.v20080804-1730.jar -console
uruchomiony zostaje automatycznie pakunek systemowy - org.eclipse.osgi. Ma on identyfikator 0 i będzie tak na każdej platformie OSGi (oczywiście nazwa pakunku systemowego będzie inna, specyficzna dla danej platformy).
 jlaskowski@work /cygdrive/c/apps/equinox
$ java -jar org.eclipse.osgi_3.5.0.v20080804-1730.jar -console

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730
Przy pierwszym uruchomieniu tworzony jest katalog configuration w katalogu bieżącym (z możliwością wskazania innego parametrem -configuration).
 jlaskowski@work /cygdrive/c/apps/equinox
$ ls -lt
total 988
drwxr-xr-x+ 3 jlaskowski None 0 Sep 28 21:27 configuration
-rwx------+ 1 jlaskowski None 1009283 Sep 22 16:07 org.eclipse.osgi_3.5.0.v20080804-1730.jar
Instalacja pakunków odbywa się poleceniem install <plik_pakunku>. Jeśli założę katalog plugins (na razie przyjmijmy, że jest to nazwa całkowicie przypadkowa), a w nim umieszczę pakunek spring-osgi-core-1.2.0-m2-SNAPSHOT.jar, jego instalacja będzie wyglądała następująco:
 jlaskowski@work /cygdrive/c/apps/equinox
$ java -jar org.eclipse.osgi_3.5.0.v20080804-1730.jar -console

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730

osgi> install file:plugins/spring-osgi-core-1.2.0-m2-SNAPSHOT.jar
Bundle id is 1

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730
1 INSTALLED org.springframework.bundle.osgi.core_1.2.0.m2-SNAPSHOT
Kolejne uruchomienie platformy OSGi gwarantuje uruchomienie pakunków do stanu, który był bieżącym przed zatrzymaniem całej Platformy, np. poleceniem close dla Equinoksa. Właśnie katalog configuration jest katalogiem, gdzie utrwalone zostają informacje o stanie pakunku (i skasowanie go powoduje skasowanie danych pakunków, co równoważne jest z uruchomieniem początkowym Equinoksa).
 jlaskowski@work /cygdrive/c/apps/equinox
$ java -jar org.eclipse.osgi_3.5.0.v20080804-1730.jar -console

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730
1 INSTALLED org.springframework.bundle.osgi.core_1.2.0.m2-SNAPSHOT
Przy pojedyńczym pakunku sprawa jego instalacji i uruchomienia nie jest poważnym zadaniem. Sprawa zaczyna się komplikować, kiedy przychodzi nam uruchomić, powiedzmy, 20 pakunków. Wtedy pozostaje nam liczyć na poprawny katalog configuration, albo...config.ini.

Plik config.ini w katalogu configuration jest plikiem konfiguracyjnym Equinoksa, w którym definiuje się, jakie pakunki mają zostać uruchomione i gdzie one w ogóle się znajdują. Dodając do tego wsparcie pakunku org.eclipse.update.configurator nie musimy umieszczać nazw wszystkich pakunków do instalacji w pliku config.ini, a wystarczy umieścić je w katalogu plugins.

Zatem plik config.ini prezentuje się następująco:
 eclipse.ignoreApp=true
osgi.bundles=org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start
a sama struktura katalogowa tak:
 |____configuration
| |____config.ini
|____org.eclipse.equinox.common_3.4.0.v20080421-2006.jar
|____org.eclipse.osgi_3.5.0.v20080804-1730.jar
|____org.eclipse.update.configurator_3.2.200.v20080417.jar
|____plugins
| |____spring-osgi-core-1.2.0-m2-SNAPSHOT.jar
Pakunek org.eclipse.equinox.common pobrałem ze strony Equinox Stable Build: 3.5M1, natomiast org.eclipse.update.configurator znalazłem w katalogu Eclipse Ganymede w plugins (nigdzie indziej nie mogłem go namierzyć).

Przy powyższej konfiguracji każdy z pakunków umieszczonych w katalogu plugins będzie zainstalowany automatycznie podczas uruchomienia Equinoksa.
 jlaskowski@work /cygdrive/c/apps/equinox
$ java -jar org.eclipse.osgi_3.5.0.v20080804-1730.jar -console

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730
1 ACTIVE org.eclipse.equinox.common_3.4.0.v20080421-2006
2 ACTIVE org.eclipse.update.configurator_3.2.200.v20080417
3 INSTALLED org.springframework.bundle.osgi.core_1.2.0.m2-SNAPSHOT
Z pewnością znacząco uprości zabawę z uruchomieniem wszystkich pakunków Spring-DM niezbędnych do uruchomienia aplikacji webowych na Apache Tomcat 6.0.18 w ramach Equinoksa. Do tej pory wymagało to ręcznego uruchamiania około 20 pakunków przy każdorazowym usunięciu katalogu configuration (!)

26 września 2008

WAS 7.0 już jest oraz JDD 2008 i NetBeans Day 2008 nadchodzą

3 komentarzy
Nie mogłem doczekać się, aż to opublikuję i w końcu jest! Wielki dzień dla społeczności Korporacyjnej 5-tki (Java EE 5), gdyż IBM wypuścił na runek długooczekiwany produkt IBM WebSphere Application Server V7.0 (IBM WebSphere Application Server V7.0 delivers an agile, solid foundation for SOA to align the advancements of business and IT). Nie planuję rozpisywać się nad jego możliwościami, bo są one znane i (nie)lubiane ;-) Ważne, że czekamy jedynie na JBoss AS 5, który ma zamknąć okres rozwoju serwerów aplikacyjnych w ich krucjacie do pełnego wsparcia specyfikacji Java EE 5. Szczęśliwcy, którzy mogą już pracować z Korporacyjną 5-tką, a wszystkim pozostałym zaleca się natychmiastową migrację na nową platformę. Zdaje się, że kolejnym obowiązkowym elementem serwerów aplikacyjnych Java EE 5 będzie OSGi. Niewiele serwerów udostępnia możliwość uruchamiania aplikacji korporacyjnych budowanych na bazie pakunków, ale wiele korzysta z nich wewnętrznie. Sądzę, że wsparcie dla OSGi będzie kolejnym dużym krokiem w rozwoju serwerów aplikacyjnych, czym znacznie powinny uprościć tworzenie złożonych aplikacji korporacyjnych. W niezwykle ciekawych czasach żyjemy (i wciąż żyjemy, mimo codziennych ochów, echów, i innych sercowych atrakcji, nie wspominając o wszechobecnym stresie ;-))!

Korzystając z chwili rozgłoszę również dwie nadchodzące imprezy, których mam przyjemność być aktywnym uczestnikiem - JDD 2008 w Krakowie oraz NetBeans Day 2008 w Poznaniu i Gdańsku. Pierwsza już za niecałe 3 tygodnie - 16 października, a druga tydzień później - 25 października w Poznaniu, po czym kolejnego dnia - 26 października - przenosi się do Gdańska. Już nie mogę doczekać się podzielenia się z Wami nowinkami z obszaru OSGi i Spring Dynamic Modules (Spring-DM) w Krakowie, a przeglądem nowości NetBeans 6.5 w Poznaniu i Gdańsku. Już od miesięcy przygotowuję się do występów, więc merytorycznie jestem przygotowany conajmniej na 3+ ;-) Dodatkowe pytania i sugestie, o czym chcielibyście posłuchać w kontekście Spring-DM, a później NetBeans IDE 6.5 mile widziane. Nikt nie życzy sobie spędzenia godziny na moim przedłużającym się wystąpieniu, więc stwórzmy miejsce wymiany doświadczeń, gdzie zostanie zaprezentowanego wiele technicznego materiału i pojawią się ciekawe pytania. Liczę na Was, nie mniej niż Wy na mnie!

Za kilka dni - 7 października o godz. 19:00 - w Warszawie odbędzie się pierwsze spotkanie blogerów piszących o IT dla pasjonatów IT - Bloggers Underground. Spotkanie organizowane przez grupę microsoftową, aczkolwiek obiecano, że będzie wyłącznie merytorycznie (czyli nie pojawią się wstawki jaka to Vista jest cacy i takie tam). Zaproszony, od razu zapisałem się z nadzieją podpatrzenia, jak inni sobie radzą w temacie dzielenia się wiedzą poprzez blogi (nawet, jeśli zajmują się niszowymi rozwiązaniami spod znaku MS ;-)). Zawsze wierzę, że poznawanie nowych osób, to miejsce na nowe pomysły i tym razem jestem przekonany, że nie będzie inaczej. Zapraszam w imieniu organizatorów.

Jeśli Ty wciąż zastanawiasz się, czy blog mógłby być dla Ciebie źródłem inspiracji i pomysłów zapraszam do lektury Najlepsze nasiona (gdzie nie będzie ziaren EJB, a jedynie nasiona, ale i tak warto). Autorka już niejeden raz ciekawie przedstawiła otaczającą mnie rzeczywistość i chętnie czytam jej wpisy, a teraz mogę wskazać jeden jako argument do założenia własnego bloga. Jeśli go nie masz, to właśnie dzisiaj jest ten dzień, abyś miał. Jeśli nie blog, to przynajmniej udział w grupie jugowej w Twoim mieście, organizacja konferencji, albo chociażby nieformalne spotkanie w grupie entuzjastów javowych. Cokolwiek, ale odejdź w końcu od komputera i spotkaj się z kimś nowym! Niedługo Warsjava+Eclipse DemoCamp 2008 w Warszawie, więc będzie okazja się spotkać i przegadać to i owo. A może udział w spotkaniu Warszawa JUG na MIMUW 30-tego? Będzie Szimano, więc dobra zabawa murowana (a że się doktoryzuje, więc i naukowo trochę również będzie ;-)). Zapraszam!

24 września 2008

Equinox i jego diag do analizy wymagań pakunku OSGi

2 komentarzy
Dzisiaj postanowiłem spróbować odpowiedzieć kilku osobom o roli Spring Dynamic Modules (Spring-DM) w integracji Spring Framework, OSGi i aplikacji webowych. Efektem prac miała być demonstracyjna aplikacja webowa, gdzie biblioteki z WEB-INF/lib byłyby osobnymi pakunkami, a sam katalog byłby pusty. Już rozpisałem sobie plan działania - stworzenie projektu aplikacji webowej, pakunków, itp., uruchomienie platformy OSGi (w tej roli Equinox) ze Spring-DM, gdzie w roli głównej występowałby pakunek Spring-DM web extender (spring-osgi-web-extender), i...właśnie, w chwili kiedy napisałem nazwę tego pakunku postanowiłem zacząć od tyłu - od uruchomienia pakunku spring-osgi-web-extender. Jego rolą jest nasłuchiwanie na zdarzenia instalacji i odinstalowywania pakunków, i przy spełnieniu warunków dla pakunków OSGi będących aplikacjami webowymi - rozszerzenie war lub posiadanie katalogu WEB-INF - przekazanie ich do kontenera servletów (dostępne są Apache Tomcat lub Jetty). Już pisałem o nim trochę w notce Aplikacja webowa jako pakunek OSGi ze Spring Dynamic Modules, ale tamto dotyczyło Spring-DM 1.1.0 M2, a teraz pracuję z Spring-DM 1.2.0-m2-SNAPSHOT (zbudowanym samodzielnie ze źródeł - instrukcja w notce Budowanie Spring-DM ze źródeł) i wiele się zmieniło. Stwierdziłem, że do tematu podejdę na opak, gdzie narzędziami diagnostycznymi Equinoksa rozpoznam zależności pakunku spring-osgi-web-extender i po kolei będę je wczytywał. W końcu zbudowałem Spring-DM ze źródeł z włączonymi testami jednostkowymi, więc miałem pewność, że wszystkie niezbędne biblioteki-pakunki miałem w moim lokalnym repozytorium mavenowym.

Rozpocząłem od uruchomienia platformy OSGi, którą był Eclipse Equinox.
 jlaskowski@work /cygdrive/c/apps/equinox
$ java -jar org.eclipse.osgi_3.5.0.v20080804-1730.jar -console

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730
Następnie zainstalowałem pakunek spring-osgi-web-extender (z lokalnego repozytorium mavenowego).
 osgi> install file:/C:/.m2/org/springframework/osgi/spring-osgi-web-extender/
1.2.0-m2-SNAPSHOT/spring-osgi-web-extender-1.2.0-m2-SNAPSHOT.jar
Bundle id is 1

osgi> headers 1
Bundle headers:
Bnd-LastModified = 1222091464343
Build-Jdk = 1.5.0_14
Built-By = jlaskowski
Bundle-Activator = org.springframework.osgi.web.extender.internal.activator.WarLoaderListener
Bundle-Description = Spring/OSGi web extender. Detects war bundles and deployes them into the configured web container.
Bundle-DocURL = http://www.springframework.org
Bundle-License = http://www.apache.org/licenses/LICENSE-2.0
Bundle-ManifestVersion = 2
Bundle-Name = spring-osgi-web-extender
Bundle-SymbolicName = org.springframework.bundle.osgi.web.extender
Bundle-Vendor = Spring Framework
Bundle-Version = 1.2.0.m2-SNAPSHOT
Import-Package = org.apache.commons.logging,org.osgi.framework;version="1.3",org.springframework.beans.factory;version="2.5.4",
org.springframework.core;version="2.5.4",org.springframework.core.task;version="2.5.4",org.springframework.osgi;version="1.2.0.m2",
org.springframework.osgi.context;version="1.2.0.m2",org.springframework.osgi.context.support;version="1.2.0.m2",
org.springframework.osgi.util;version="1.2.0.m2",org.springframework.osgi.web.deployer;version="1.2.0.m2",
org.springframework.osgi.web.deployer.jetty;resolution:=optional;version="1.2.0.m2",
org.springframework.osgi.web.deployer.support;version="1.2.0.m2",org.springframework.osgi.web.deployer.tomcat;
resolution:=optional;version="1.2.0.m2",org.springframework.scheduling.timer;version="2.5.4",
org.springframework.util;version="2.5.4"
Manifest-Version = 1.0
Private-Package = org.springframework.osgi.extender.internal.util,
org.springframework.osgi.extender.internal.util.concurrent,
org.springframework.osgi.web.extender.internal.activator,
org.springframework.osgi.web.extender.internal.scanner
Spring-DM-Version = 1.2.0-m2-SNAPSHOT
Spring-Version = 2.5.6-SNAPSHOT
Tool = Bnd-0.0.238
UWAGA: Na zrzucie linia z poleceniem install oraz dla nagłówków Import-Package i Private-Package są "złamane" dla celów prezentacji.

Jak widać na powyższym zrzucie, w nagłówku Import-Package, pakunek spring-osgi-web-extender wymaga wielu pakietów udostępnianych przez inne (wspierające) pakunki. To właśnie wybrałem jako temat rozpoczynający prace - poprawnie zdefiniować wszystkie wymagane zależności pakunku spring-osgi-web-extender na podstawie Import-Package.

Przeglądając źródła Spring-DM, a konkretnie pomy, doszedłem do pierwszych wymaganych pakunków, które spełnią istnienie pierwszego pakietu na liście Import-Package - org.apache.commons.logging:
  • org/slf4j/com.springsource.slf4j.org.apache.commons.logging/1.5.0/com.springsource.slf4j.org.apache.commons.logging-1.5.0.jar
  • org/slf4j/com.springsource.slf4j.api/1.5.0/com.springsource.slf4j.api-1.5.0.jar
  • org/slf4j/com.springsource.slf4j.log4j/1.5.0/com.springsource.slf4j.log4j-1.5.0.jar
  • org/springframework/osgi/log4j.osgi/1.2.15-SNAPSHOT/log4j.osgi-1.2.15-SNAPSHOT.jar
Po ich zainstalowaniu i uruchomieniu pozostało określić dostawców pozostałych pakietów. Tylko, że po jakimś czasie może pojawić się pytanie - które jeszcze pakiety/pakunki nie są dostępne? Zacząłem rozmyślać, jak fajnie byłoby mieć narzędzie ala Maven w OSGi, które pobierze wymagane pakunki, aby środowisko było poprawnie zestawione dla wybranego pakunku, albo co najmniej ujawni brakujące pakiety. I jakoś szczęśliwie się zdarzyło, że przeglądając wynik equinoksowego polecenia help znalazłem odpowiedź - diag.
 osgi> help
---Eclipse Runtime commands---
diag - Displays unsatisfied constraints for the specified bundle(s).
enableBundle - enable the specified bundle(s)
disableBundle - disable the specified bundle(s)
disabledBundles - list disabled bundles in the system
Polecenie diag dokładnie spełnia moje oczekiwania - wyświetla wymagania niespełnione w środowisku dla wybranego pakunku.
 osgi> diag 1
file:/C:/.m2/org/springframework/osgi/spring-osgi-web-extender/
1.2.0-m2-SNAPSHOT/spring-osgi-web-extender-1.2.0-m2-SNAPSHOT.jar [1]
Direct constraints which are unresolved:
Missing imported package org.springframework.beans.factory_2.5.4.
Missing imported package org.springframework.core_2.5.4.
Missing imported package org.springframework.core.task_2.5.4.
Missing imported package org.springframework.osgi_1.2.0.m2.
Missing imported package org.springframework.osgi.context_1.2.0.m2.
Missing imported package org.springframework.osgi.context.support_1.2.0.m2.
Missing imported package org.springframework.osgi.util_1.2.0.m2.
Missing imported package org.springframework.osgi.web.deployer_1.2.0.m2.
Missing imported package org.springframework.osgi.web.deployer.jetty_1.2.0.m2.
Missing imported package org.springframework.osgi.web.deployer.support_1.2.0.m2.
Missing imported package org.springframework.osgi.web.deployer.tomcat_1.2.0.m2.
Missing imported package org.springframework.scheduling.timer_2.5.4.
Missing imported package org.springframework.util_2.5.4.
I to jest dokładnie to! Tych pakietów jeszcze nie zainstalowałem. To jest jednakże już praca na kolejne dni.

23 września 2008

34. spotkanie Warszawskiej Grupy Użytkowników Technologii Java (Warszawa JUG)

0 komentarzy
Warszawska Grupa Użytkowników Technologii Java (Warszawa JUG) zaprasza na 34. spotkanie, które odbędzie się 30.09.2008 o godzinie 18:00 w sali 5440 Wydziału MIMUW przy ul. Banacha 2 w Warszawie.

Temat prezentacji: Podstawy języków formalnych, ANTLR i ANTLRWorks
Prowadzący: Tomek Szymański (vel szimano)

Pisząc różne programy często zdarza się, że mamy jakieś źródło, które wcale nie jest w XMLu ani nawet JSONie... są różne Scannery, Matchery, wyrażenia regularne, ale często to jest za mało i więcej czasu tracimy na "przeczytanie" tego źródła niż na jego "obrobienie". I tutaj wybawieniem jest ANTLR, którego staram się pokazać.

Ale niech nie zrazi was straszny tutuł - podstawy języków formalnych poznać trzeba, ale będzie jak naprzystępniej a potem to już zajmiemy się wyłącznie kodowaniem w naszej ulubionej Javie !

Co jeszcze ? ANTLRWorks - narzędzie z ładnym GUI i różnymi bajerami ułatwiające prace z ANTLRem, zrobienie tego, co mamy na myśli mówiąc "kompilator" - czyli czegoś co wygeneruje program z naszego języka, robienie parserów, obalanie paru mitów i tymczasowe oderwanie od, mogących się na chwile znudzić, technologii webowych, którymi karmimy się na codzień.

Tomek Szymański (vel szimano) - Kontraktor pewnej firmy, która właśnie wypuściła CR2 Application Servera zgodnego z EE 5.0. Zainteresowany narzędziami typu compiler-compiler od momentu, kiedy uczestniczył w odpowiednim przedmiocie na studiach... potem napisał pracę magisterską na ten temat, żeby przez pół roku prowadzić, już jako doktorant (którym nie jest), laboratorium z tych zajęć. Postanowił, że skoro jeszcze coś z tego pamięta, to się podzieli zanim zapomni. Poza tym jest miły, sympatyczny, kulturalny i lubi chodzić w kaszkiecie.

Planowany czas prezentacji to 1,5 godziny, po której planuje się 15-30-minutową dyskusję.

Wstęp wolny!

Zapraszam w imieniu grupy Warszawa JUG!

22 września 2008

Pakunki częściowe OSGi w akcji z Equinox

0 komentarzy
Już wiem, że pakunki częściowe (ang. fragment bundles) nie są wspierane przez Apache Felix (więcej o nich i braku wsparcia przez Feliksa w OSGi - 3.14 Pakunki częściowe), więc nie pozostaje mi nic innego jak korzystać z Eclipse Equinox do dalszych testów. Tak długo, jak wymagane będzie wsparcie pakunków częściowych Platformą OSGi nie będzie Apache Felix. To jest właśnie ów techniczny powód, dla którego, w kontekście Spring-DM, często pojawiał się będzie Equinox. Zainteresowanych zmianami w tej materii uprasza się o śledzenie rozwoju zgłoszenia FELIX-29 Implement bundle fragments.

Rozpocznę praktyczne rozpoznanie pakunków częściowych od stworzenia dwóch pakunków - pakunku macierzystego i pakunku częściowego - z pomocą spring-osgi-bundle-archetype.

UWAGA: Użyłem zadania archetype:generate z parametrem -Darchetype.interactive=false, gdyż wcześniejużywany archetype:create został oznaczony jako nieaktualny ([WARNING] This goal is deprecated. Please use mvn archetype:generate instead)

Najpierw pakunek macierzysty springdm-host-bundle:
 mvn archetype:generate \
-DarchetypeGroupId=org.springframework.osgi \
-DarchetypeArtifactId=spring-osgi-bundle-archetype \
-DarchetypeVersion=1.2.0-m2-SNAPSHOT \
-DgroupId=pl.jaceklaskowski.springdm.fragment \
-DartifactId=springdm-host-bundle \
-Dversion=1.0 \
-Darchetype.interactive=false
, po którym tworzę pakunek częściowy springdm-fragment-bundle:
 mvn archetype:generate \
-DarchetypeGroupId=org.springframework.osgi \
-DarchetypeArtifactId=spring-osgi-bundle-archetype \
-DarchetypeVersion=1.2.0-m2-SNAPSHOT \
-DgroupId=pl.jaceklaskowski.springdm.fragment \
-DartifactId=springdm-fragment-bundle \
-Dversion=1.0 \
-Darchetype.interactive=false
Możnaby utworzyć je w ramach większego projektu mavenowego (packaging=pom), ale pozostawiam to dla zaangażowanych.

Na początku zadeklaruję pakunek springdm-fragment-bundle jako pakunek częściowy dla springdm-host-bundle za pomocą nagłówka Fragment-Host. Jako, że projekt pakunku częściowego springdm-fragment-bundle zarządzany jest przez Apache Maven 2 nagłówek dodaję do konfiguracji wtyczki maven-bundle-plugin w pom.xml.
 <Fragment-Host>pl.jaceklaskowski.springdm.fragment.springdm-host-bundle</Fragment-Host>
Nazwę pakunku macierzystego można poznać przez utworzenie docelowego manifestu przez wykonanie polecenia mvn package i odczytanie nagłówka Bundle-SymbolicName w utworzonym META-INF/MANIFEST.MF.

Tworzę pakunki poleceniem mvn package i uruchamiam na Equinoksie (najświeższa wersja do pobrania ze strony equinox osgi downloads, np. Equinox Stable Build: 3.5M2, chociaż adres na stronie nie działa! Można skorzystać z jeszcze innego adresu equinox osgi downloads, gdzie można pobrać Equinox Stable Build: 3.5M1). Początkowo korzystałem z Equinoksa dostarczanego w ramach Eclipse Ganymede - plugins/org.eclipse.osgi_3.4.0.v20080605-1900.jar, ale przy finalnym uruchomieniu przeniosłem się na nowszą wersję - org.eclipse.osgi_3.5.0.v20080804-1730.jar, wyłącznie ze względów bycia na bieżąco.

Dla dociekliwych zaleca się lekturę niewielkiego podręcznika Equinoksa - Equinox QuickStart Guide.
 jlaskowski@work /cygdrive/c/apps/eclipse
$ java -jar plugins/org.eclipse.osgi_3.4.0.v20080605-1900.jar -console

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.4.0.v20080605-1900

osgi> install file:/C:/projs/sandbox/springdm-fragment-bundle/target/springdm-fragment-bundle-1.0.jar
Bundle id is 1

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.4.0.v20080605-1900
1 INSTALLED pl.jaceklaskowski.springdm.fragment.springdm-fragment-bundle_1.0.0

osgi> start 1
org.osgi.framework.BundleException: A fragment bundle cannot be started:
file:/C:/projs/sandbox/springdm-fragment-bundle/target/springdm-fragment-bundle-1.0.jar [1]
at org.eclipse.osgi.framework.internal.core.BundleFragment.startWorker(BundleFragment.java:224)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:265)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:257)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._start(FrameworkCommandProvider.java:257)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.execute(FrameworkCommandInterpreter.java:150)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(FrameworkConsole.java:302)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(FrameworkConsole.java:287)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(FrameworkConsole.java:223)
at java.lang.Thread.run(Thread.java:595)

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.4.0.v20080605-1900
1 INSTALLED pl.jaceklaskowski.springdm.fragment.springdm-fragment-bundle_1.0.0

osgi> install file:/C:/projs/sandbox/springdm-host-bundle/target/springdm-host-bundle-1.0.jar
Bundle id is 2

osgi> start 2

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.4.0.v20080605-1900
1 RESOLVED pl.jaceklaskowski.springdm.fragment.springdm-fragment-bundle_1.0.0
Master=2
2 ACTIVE pl.jaceklaskowski.springdm.fragment.springdm-host-bundle_1.0.0
Fragments=1

osgi> bundle 1
file:/C:/projs/sandbox/springdm-fragment-bundle/target/springdm-fragment-bundle-1.0.jar [1]
Id=1, Status=RESOLVED Data Root=C:\apps\eclipse\plugins\configuration\org.eclipse.osgi\bundles\1\data
No registered services.
No services in use.
Exported packages
pl.jaceklaskowski.springdm.fragment; version="0.0.0"[exported]
No imported packages
Host bundles
file:/C:/projs/sandbox/springdm-host-bundle/target/springdm-host-bundle-1.0.jar [2]
No named class spaces
No required bundles

osgi> bundle 2
file:/C:/projs/sandbox/springdm-host-bundle/target/springdm-host-bundle-1.0.jar [2]
Id=2, Status=ACTIVE Data Root=C:\apps\eclipse\plugins\configuration\org.eclipse.osgi\bundles\2\data
No registered services.
No services in use.
Exported packages
pl.jaceklaskowski.springdm.fragment; version="0.0.0"[exported]
No imported packages
Fragment bundles
file:/C:/projs/sandbox/springdm-fragment-bundle/target/springdm-fragment-bundle-1.0.jar [1]
Named class space
pl.jaceklaskowski.springdm.fragment.springdm-host-bundle; bundle-version="1.0.0"[provided]
No required bundles

osgi> close
Dodam do pakunku macierzystego funkcjonalność, która przy każdorazowym zainstalowaniu nowego pakunku będącym rozszerzeniem (pakunkiem częściowym) dla niego, wypisze dostępne pliki wchodzącego w skład przestrzeni pakunku. Dzięki metodzie org.osgi.framework.Bundle.findEntries(String,String,boolean) pakunek ma możliwość przejrzenia wszystkich zasobów zawartych w nim (bezpośrednio w jego pliku jar) oraz wszystkich rozszerzeniach (pakunkach częściowych). Nie należy mylić działania tej metody z metodą Bundle.getResource(String) czy Bundle.getResources(String), które działają na całej przestrzeni klas dostęnych dla pakunku (co może być rozbudowane w porównaniu z przestrzenią pakunku o deklaracje w nagłówku Import-Package).

Definiuję aktywator w pakunku macierzystym, który zarejestruje słuchacza reagującego na zdarzenia rozwiązania (stan RESOLVED) pakunków (podpieram się artykułem Bundle.findEntries() i spring-osgi-bundle-archetype w akcji - monitorowanie pakunków OSGi z określoną strukturą katalogową).
 package pl.jaceklaskowski.springdm.fragment.internal;

import java.util.Dictionary;
import java.util.Enumeration;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;

public class Aktywator implements BundleActivator {

private final class Sluchacz implements BundleListener {
private String nazwaPakunkuMacierzystego;

public Sluchacz(String nazwaPakunkuMacierzystego) {
this.nazwaPakunkuMacierzystego = nazwaPakunkuMacierzystego;
}

public void bundleChanged(BundleEvent event) {
Bundle bundle = event.getBundle();
String nazwaPakunku = bundle.getSymbolicName();
// Sprawdź, czy jest pakunkiem częściowym
Dictionary<?, ?> headers = bundle.getHeaders();
String pakunekMacierzysty = (String) headers.get("Fragment-Host");
if (!nazwaPakunkuMacierzystego.equalsIgnoreCase(pakunekMacierzysty)) {
return;
}
switch (event.getType()) {
case BundleEvent.RESOLVED:
System.out.println("Pakunek czesciowy " + nazwaPakunku + " w stanie RESOLVED");
wyswietlLiczbeDostepnychPlikow(bundle);
break;
case BundleEvent.STOPPED:
System.out.println("Pakunek czesciowy " + nazwaPakunku + " w stanie STOPPED");
wyswietlLiczbeDostepnychPlikow(bundle);
break;
}
}
}

private BundleListener sluchacz;

public void start(BundleContext context) throws Exception {
String nazwaPakunku = context.getBundle().getSymbolicName();
System.out.println("Pakunek macierzysty " + nazwaPakunku + " w stanie STARTING");
sluchacz = new Sluchacz(nazwaPakunku);
System.out.println("...instalacja " + sluchacz);
context.addBundleListener(sluchacz);
wyswietlLiczbeDostepnychPlikow(context.getBundle());
}

public void stop(BundleContext context) throws Exception {
String nazwaPakunku = context.getBundle().getSymbolicName();
System.out.println("Pakunek macierzysty " + nazwaPakunku + " w stanie STOPPING");
System.out.println("...usuniecie " + sluchacz);
context.removeBundleListener(sluchacz);
wyswietlLiczbeDostepnychPlikow(context.getBundle());
}

private void wyswietlLiczbeDostepnychPlikow(Bundle bundle) {
int liczbaPlikow = 0;
Enumeration<?> entries = bundle.findEntries("/", "*", true);
for (; entries.hasMoreElements(); entries.nextElement()) {
liczbaPlikow++;
}
System.out.println("+++ Liczba plikow: " + liczbaPlikow);
}

}
Pierwsze uruchomienie przykładu zakończyło się niepowodzeniem.
 jlaskowski@work /cygdrive/c/apps/eclipse
$ java -jar plugins/org.eclipse.osgi_3.4.0.v20080605-1900.jar -console

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.4.0.v20080605-1900

osgi> install file:/C:/projs/sandbox/springdm-host-bundle/target/springdm-host-bundle-1.0.jar
Bundle id is 1

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.4.0.v20080605-1900
1 INSTALLED pl.jaceklaskowski.springdm.fragment.springdm-host-bundle_1.0.0

osgi> start 1
org.osgi.framework.BundleException: The bundle could not be resolved. Reason:
Missing Constraint: Import-Package: pl.jaceklaskowski.springdm.fragment.internal; version="0.0.0"
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:305)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:265)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:257)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._start(FrameworkCommandProvider.java:257)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.execute(FrameworkCommandInterpreter.java:150)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(FrameworkConsole.java:302)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(FrameworkConsole.java:287)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(FrameworkConsole.java:223)
at java.lang.Thread.run(Thread.java:595)

osgi> close
O dziwo nie doświadczałem tych problemów podczas pracy z Apache Felix (!) Najwyraźniej Equinox jest bardziej restrykcyjny i sprawdzając poprawność nagłówków, dla każdego Import-Package weryfikuje widoczność pakietów w przestrzeni klas. Jako, że domyślnie pakiet pl.jaceklaskowski.springdm.fragment.internal jest domyślnie wyłączany z Export-Package przez Spring-DM (a właściwie niewprost przez bnd wywoływane przez wtyczkę maven-bundle-plugin, która jest tak konfigurowana przez archetyp spring-osgi-bundle-archetype w pom.xml) pojawia się komunikat błędu o niespełnieniu wymagania nałożonego przez Import-Package. Analizując źródła projektu Spring-DM (dokładniej pomy w spring-osgi-extender oraz spring-osgi) kończę z następującą konfiguracją dla maven-bundle-plugin:
 <plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<version>1.4.0</version>
<configuration>
<manifestLocation>META-INF</manifestLocation>
<instructions>
<Export-Package>!pl.jaceklaskowski.springdm.fragment.*internal*</Export-Package>
<Private-Package>pl.jaceklaskowski.springdm.fragment.*internal*</Private-Package>
<Include-Resource>src/main/resources</Include-Resource>
<Bundle-Activator>pl.jaceklaskowski.springdm.fragment.internal.Aktywator</Bundle-Activator>
<Bundle-Version>2</Bundle-Version>
</instructions>
</configuration>
</plugin>
Kluczem do sukcesu jest nagłówek Private-Package.

Warto pomiędzy uruchomieniami Equinoksa usuwać jego katalog konfiguracyjny - configuration, aby poprzednia konfiguracja nie kolidowała na bieżące testy. Katalog configuration tworzony jest w katalogu, w którym znajduje się uruchomieniowy jar Equinoksa.
 jlaskowski@work /cygdrive/c/apps/equinox
$ rm -rf configuration
Podczas analizy poniższego działania pakunków macierzystego i częściowego na Equinoksie proszę zwrócić uwagę na komunikat +++ Liczba plikow, który informuje o liczbie plików dostępnych w pakunku macierzystym (przypominam, że pakunek częściowy nie jest pełnoprawnym pakunkiem OSGi, tzn. obostrzenia OSGi zugożają go sprowadzając do roli pakunku rozszerzającego).
 jlaskowski@work /cygdrive/c/apps/equinox
$ java -jar org.eclipse.osgi_3.5.0.v20080804-1730.jar -console

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730

osgi> install file:/C:/projs/sandbox/springdm-host-bundle/target/springdm-host-bundle-1.0.jar
Bundle id is 1

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730
1 INSTALLED pl.jaceklaskowski.springdm.fragment.springdm-host-bundle_2.0.0

osgi> start 1
Pakunek macierzysty pl.jaceklaskowski.springdm.fragment.springdm-host-bundle w stanie STARTING
...instalacja pl.jaceklaskowski.springdm.fragment.internal.Aktywator$Sluchacz@ca470
+++ Liczba plikow: 18

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730
1 ACTIVE pl.jaceklaskowski.springdm.fragment.springdm-host-bundle_2.0.0

osgi> install file:/C:/projs/sandbox/springdm-fragment-bundle/target/springdm-fragment-bundle-1.0.jar
Bundle id is 2

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730
1 ACTIVE pl.jaceklaskowski.springdm.fragment.springdm-host-bundle_2.0.0
2 INSTALLED pl.jaceklaskowski.springdm.fragment.springdm-fragment-bundle_1.0.0

osgi> refresh 1

osgi> Pakunek macierzysty pl.jaceklaskowski.springdm.fragment.springdm-host-bundle w stanie STOPPING
...usuniecie pl.jaceklaskowski.springdm.fragment.internal.Aktywator$Sluchacz@ca470
+++ Liczba plikow: 18
Pakunek macierzysty pl.jaceklaskowski.springdm.fragment.springdm-host-bundle w stanie STARTING
...instalacja pl.jaceklaskowski.springdm.fragment.internal.Aktywator$Sluchacz@42552c
+++ Liczba plikow: 29


osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20080804-1730
1 ACTIVE pl.jaceklaskowski.springdm.fragment.springdm-host-bundle_2.0.0
Fragments=2
2 RESOLVED pl.jaceklaskowski.springdm.fragment.springdm-fragment-bundle_1.0.0
Master=1

osgi> uninstall 2

osgi> refresh 1

osgi> Pakunek macierzysty pl.jaceklaskowski.springdm.fragment.springdm-host-bundle w stanie STOPPING
...usuniecie pl.jaceklaskowski.springdm.fragment.internal.Aktywator$Sluchacz@42552c
Pakunek macierzysty pl.jaceklaskowski.springdm.fragment.springdm-host-bundle w stanie STARTING
...instalacja pl.jaceklaskowski.springdm.fragment.internal.Aktywator$Sluchacz@1113622
+++ Liczba plikow: 18


osgi> close

Pakunek macierzysty pl.jaceklaskowski.springdm.fragment.springdm-host-bundle w stanie STOPPING
...usuniecie pl.jaceklaskowski.springdm.fragment.internal.Aktywator$Sluchacz@1113622
+++ Liczba plikow: 18
Ciekawe przedstawienie tematu dostępne również w bezpłatnej książce OSGi in Practice w rozdziale The Extender Model.

Pojawił się nowy harmonogram nowej wersji NetBeans 6.5 - NetBeans NB65Milestones. Przyjdzie jeszcze trochę poczekać na finalną wersję NetBeans 6.5 - 12 listopada 2008.