Zacznijmy od niewielkiej dawki teorii.
Pakunek jest uruchomiony przez wywołanie jednej z metod Bundle.start(...) lub bezpośrednie uruchomienie przez sam Szkielet OSGi, jeśli pakunek jest gotowy do uruchomienia lub konfiguracja ustawienia automatycznego startowania wskazuje, że musi on zostać uruchomiony.
Pakunek jest gotowy do uruchomienia, jeśli:
- Pakunek jest rozwiązany, tj. wszystkie jego zależności zadeklarowane w manifeście zostały odszukane i są dostępne
- Jeśli użyto opcjonalnej usługi Poziomu Uruchomienia (ang. Start Level service) i poziom uruchomienia pakunku jest spełniony
Pora na popróbowanie się z tą wiedzą praktycznie.
Rozpoczynam od stworzenia projektu dla pakunku, w którym zdefiniuję Bundle-ActivationPolicy: lazy.
mvn archetype:create \Następnie importuję projekt do Eclipse, poprawiam Java Build Path i rozpoczynam edycję pliku pom.xml, aby nadać właściwą nazwę pakunkowi (projektowi)
-DarchetypeGroupId=org.springframework.osgi \
-DarchetypeArtifactId=spring-osgi-bundle-archetype \
-DarchetypeVersion=1.0 \
-DgroupId=pl.jaceklaskowski.osgi \
-DartifactId=spring-osgi-activationpolicy \
-Dversion=1.0
<name>Pakunek z Bundle-ActivationPolicy: lazy</name>, zdefiniować aktywator pakunku wraz z konfiguracją aktywacji opóźnionej
<Bundle-Activator>${groupId}.AktywatorPakunku</Bundle-Activator>oraz dodać kolejną zależność projektową.
<Bundle-ActivationPolicy>lazy</Bundle-ActivationPolicy>
<dependency>Po zmianie pom.xml uruchamiam polecenie
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>4.0</version>
</dependency>
mvn eclipse:eclipseaby odświeżyć projekt w Eclipse i dodać do niego nowododaną zależność (wydaje się, że mógłbym ją dodać poprzez menu Maven w Eclipse i w ten sposób zniwelowałbym tą wycieczkę na linię poleceń). Po tym F5 (odświeżenie projektu) w Eclipse i voila - projekt gotowy.
Dodaję aktywatora pakunku - pl.jaceklaskowski.osgi.AktywatorPakunku.
package pl.jaceklaskowski.osgi;Następnie wykonuje polecenie budujące projekt, a tym samym i mój pakunek.
import java.util.logging.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class AktywatorPakunku implements BundleActivator {
Logger log = Logger.getLogger(AktywatorPakunku.class.getName());
public void start(BundleContext bundleContext) throws Exception {
Bundle bundle = bundleContext.getBundle();
long bundleId = bundle.getBundleId();
String bundleLocation = bundle.getLocation();
String bundleSymbolicName = bundle.getSymbolicName();
System.out.println("------------------------------------");
System.out.println("Charakterystyka aktywowanego pakunku:");
System.out.println(" Identyfikator: " + bundleId);
System.out.println(" Identyfikator położenia: " + bundleLocation);
System.out.println(" Nazwa symboliczna: " + bundleSymbolicName);
System.out.println("------------------------------------");
}
public void stop(BundleContext bundleContext) throws Exception {
log.info("stop() wykonano - czyszczę po sobie");
}
}
mvn clean packagePakunek z Bundle-ActivationPolicy: lazy jest gotowy.
Pora na kolejny pakunek instalujący poprzedni. Rozpoczynam podobnie, najpierw utworzenie projektu o nazwie spring-osgi-install, zmiany w pom.xml oraz dodanie aktywatora:
package pl.jaceklaskowski.osgi;. Zbudowanie projektu, tj. pakunku poleceniem
import java.util.logging.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class AktywatorPakunku implements BundleActivator {
Logger log = Logger.getLogger(AktywatorPakunku.class.getName());
public void start(BundleContext bundleContext) throws Exception {
Bundle bundle = bundleContext.installBundle(
"file:c:/projs/osgi/spring-osgi-activationpolicy/target/spring-osgi-activationpolicy-1.0.jar");
long bundleId = bundle.getBundleId();
String bundleLocation = bundle.getLocation();
String bundleSymbolicName = bundle.getSymbolicName();
System.out.println("------------------------------------");
System.out.println("Charakterystyka zainstalowanego pakunku:");
System.out.println(" Identyfikator: " + bundleId);
System.out.println(" Identyfikator położenia: " + bundleLocation);
System.out.println(" Nazwa symboliczna: " + bundleSymbolicName);
System.out.println("------------------------------------");
System.out.println("Startuję pakunek " + bundleSymbolicName);
bundle.start();
}
public void stop(BundleContext bundleContext) throws Exception {
log.info("stop() wykonano - czyszczę po sobie");
}
}
mvn clean packagei próba generalna.
jlaskowski@work /cygdrive/c/apps/felixI tu pierwsza niespodzianka - przykład nie działa (!) Ów wyjątek BundleException psuje całe moje rozumienie tematu. Hmmm, przechodzę, więc na inne środowisko OSGi - Eclipse Equinox. Equinox jest wzorcową (referencyjną) implementacją, więc wierzę, że będzie inaczej (czy lepiej to się właśnie okaże). Ponownie trochę lektury Equinox QuickStart Guide i uzbrojony w wiedzę uruchamiam moje pakunki.
$ java -Dfelix.cache.profile=install -jar bin/felix.jar
Welcome to Felix.
=================
DEBUG: WIRE: 1.0 -> org.osgi.service.packageadmin -> 0
DEBUG: WIRE: 1.0 -> org.osgi.service.startlevel -> 0
DEBUG: WIRE: 1.0 -> org.ungoverned.osgi.service.shell -> 1.0
DEBUG: WIRE: 1.0 -> org.osgi.framework -> 0
DEBUG: WIRE: 1.0 -> org.apache.felix.shell -> 1.0
DEBUG: WIRE: 2.0 -> org.osgi.framework -> 0
DEBUG: WIRE: 2.0 -> org.apache.felix.shell -> 1.0
DEBUG: WIRE: 3.0 -> org.osgi.service.obr -> 3.0
DEBUG: WIRE: 3.0 -> org.osgi.framework -> 0
-> DEBUG: WIRE: 3.0 -> org.apache.felix.shell -> 1.0
-> install file:c:/projs/osgi/spring-osgi-install/target/spring-osgi-install-1.0.jar
Bundle ID: 4
-> start 4
DEBUG: WIRE: 4.0 -> org.osgi.framework -> 0
DEBUG: WIRE: 4.0 -> pl.jaceklaskowski.osgi.impl -> 4.0
DEBUG: WIRE: 4.0 -> pl.jaceklaskowski.osgi -> 4.0
2008-04-03 19:49:20 pl.jaceklaskowski.osgi.AktywatorPakunku start
------------------------------------
Charakterystyka zainstalowanego pakunku:
Identyfikator: 5
Identyfikator położenia: file:c:/projs/osgi/spring-osgi-activationpolicy/target/spring-osgi-activationpolicy-1.0.jar
Nazwa symboliczna: pl.jaceklaskowski.osgi.spring-osgi-activationpolicy
------------------------------------
Startuję pakunek pl.jaceklaskowski.osgi.spring-osgi-activationpolicy
DEBUG: WIRE: 5.0 -> org.osgi.framework -> 0
DEBUG: WIRE: 5.0 -> pl.jaceklaskowski.osgi.impl -> 4.0
DEBUG: WIRE: 5.0 -> pl.jaceklaskowski.osgi -> 4.0
2008-04-03 19:49:20 pl.jaceklaskowski.osgi.AktywatorPakunku start
------------------------------------
Charakterystyka zainstalowanego pakunku:
Identyfikator: 5
Identyfikator położenia: file:c:/projs/osgi/spring-osgi-activationpolicy/target/spring-osgi-activationpolicy-1.0.jar
Nazwa symboliczna: pl.jaceklaskowski.osgi.spring-osgi-activationpolicy
------------------------------------
Startuję pakunek pl.jaceklaskowski.osgi.spring-osgi-activationpolicy
org.osgi.framework.BundleException: Starting a bundle that is starting or stopping is currently not supported.
-> ps
START LEVEL 1
ID State Level Name
[ 0] [Active ] [ 0] System Bundle (1.0.3)
[ 1] [Active ] [ 1] Apache Felix Shell Service (1.0.0)
[ 2] [Active ] [ 1] Apache Felix Shell TUI (1.0.0)
[ 3] [Active ] [ 1] Apache Felix Bundle Repository (1.0.2)
[ 4] [Resolved ] [ 1] Pakunek instalujacy (1.0)
[ 5] [Resolved ] [ 1] Pakunek z Bundle-ActivationPolicy lazy (1.0)
-> shutdown
jlaskowski@work /cygdrive/c/projs/osgi/spring-osgi-installI tu również wyjątek. Zanim skonstruowałem tak wyrafinowany przykład badałem działanie pakunku z Bundle-ActivationPolicy: lazy bezpośrednio z konsoli Felixa i każdorazowe polecenie start powodowało aktywację (uruchomienie aktywatora). Napisałem na grupę użytkowników Felixa, a tam kolejna niespodzianka. Na moje pytanie, dlaczego tak się dzieje otrzymałem odpowiedź (Bundle-ActivationPolicy: lazy and start command):
$ java -jar c:/apps/eclipse/plugins/org.eclipse.osgi_3.4.0.v20080205.jar -console
osgi> ss
Framework is launched.
id State Bundle
0 ACTIVE org.eclipse.osgi_3.4.0.v20080205
osgi> install file:c:/projs/osgi/spring-osgi-install/target/spring-osgi-install-1.0.jar
Bundle id is 1
osgi> start 1
2008-04-03 22:26:06 pl.jaceklaskowski.osgi.AktywatorPakunku start
------------------------------------
Charakterystyka zainstalowanego pakunku:
Identyfikator: 2
Identyfikator położenia: file:c:/projs/osgi/spring-osgi-activationpolicy/target/spring-osgi-activationpolicy-1.0.jar
Nazwa symboliczna: pl.jaceklaskowski.osgi.spring-osgi-activationpolicy
------------------------------------
Startuję pakunek pl.jaceklaskowski.osgi.spring-osgi-activationpolicy
2008-04-03 22:26:07 pl.jaceklaskowski.osgi.AktywatorPakunku start
------------------------------------
Charakterystyka zainstalowanego pakunku:
Identyfikator: 2
Identyfikator położenia: file:c:/projs/osgi/spring-osgi-activationpolicy/target/spring-osgi-activationpolicy-1.0.jar
Nazwa symboliczna: pl.jaceklaskowski.osgi.spring-osgi-activationpolicy
------------------------------------
Startuję pakunek pl.jaceklaskowski.osgi.spring-osgi-activationpolicy
org.osgi.framework.BundleException: Exception in
pl.jaceklaskowski.osgi.AktywatorPakunku.start() of bundle
pl.jaceklaskowski.osgi.spring-osgi-install.
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:1018)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:974)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:346)
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:298)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(FrameworkConsole.java:283)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(FrameworkConsole.java:219)
at java.lang.Thread.run(Thread.java:595)
Caused by: org.osgi.framework.BundleException: Exception in pl.jaceklaskowski.osgi.AktywatorPakunku.start()
of bundle pl.jaceklaskowski.osgi.spring-osgi-activationpolicy.
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:1018)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:974)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:346)
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 pl.jaceklaskowski.osgi.AktywatorPakunku.start(AktywatorPakunku.java:26)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl$2.run(BundleContextImpl.java:999)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:993)
... 14 more
Caused by: org.osgi.framework.BundleException:
State change in progress for bundle
"file:c:/projs/osgi/spring-osgi-activationpolicy/target/spring-osgi-activationpolicy-1.0.jar"
by thread "OSGi Console".
at org.eclipse.osgi.framework.internal.core.AbstractBundle.beginStateChange(AbstractBundle.java:1143)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:263)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:257)
at pl.jaceklaskowski.osgi.AktywatorPakunku.start(AktywatorPakunku.java:26)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl$2.run(BundleContextImpl.java:999)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:993)
... 22 more
Caused by: org.eclipse.osgi.framework.internal.core.AbstractBundle$BundleStatusException
... 29 more
...
osgi> ss
Framework is launched.
id State Bundle
0 ACTIVE org.eclipse.osgi_3.4.0.v20080205
1 RESOLVED pl.jaceklaskowski.osgi.spring-osgi-install_1.0.0
2 RESOLVED pl.jaceklaskowski.osgi.spring-osgi-activationpolicy_1.0.0
osgi> exit
Very simple answer: Felix does not yet implement that R4.1 feature...
więc mając tą odpowiedź i doświadczywszy problemów z uruchomieniem opóźnionym pakunku postanowiłem odłożyć temat na później.
Ważną informacją w kontekście uruchomienia pakunków z Equinoxem jest zapisywanie przez niego stanu (pakunków) w katalogu configuration, który znajduje się w tym samym katalogu, co jego plik jar (org.eclipse.osgi_3.4.0.v20080205.jar), czyli w podkatalogu plugins Eclipse'a. Warto go usuwać dla zapewnienia "czystości" środowiska uruchomieniowego, gdyż zgodnie ze specyfikacją stan pakunków jest trwały, pomimo możliwych przestojów środowiska OSGi.
Pytanie na zakończenie: Jak nazywa się nagłówek manifestu pozwalający na określenie opóźnionej aktywacji pakunku?. Nagród nie ma.
Brak komentarzy:
Prześlij komentarz