Pakunki OSGi w projekcie wielomodułowym Apache Maven 2 z maven-bundle-plugin

Z Jacek Laskowski - Wiki Projektanta Java EE

Pojawił się 5. artykuł w serii Getting started with OSGi autorstwa Neila Bartletta i podobnie, jak poprzednio opisywałem w Tworzenie pakietów OSGi z Apache Maven 2 zainspirowany OSGi, postanowiłem jeszcze bardziej urozmaicić lekturę artykułów Neila i zaprezentować kilka ciekawych usprawnień.

Spis treści

Wprowadzenie

Tym razem zaprezentuję możliwość zarządzania wieloma modułami przez M2 (projekt wielomodułowy) oraz wtyczkę Bundle Plugin for Maven dalej zwaną maven-bundle-plugin. Pozwoli to na kolejne uproszczenia w zarządzaniu projektem z wieloma pakunkami OSGi (ang. OSGi bundles). Już w przypadku 2 pakunków manualne zarządzanie nimi sprawia pewne trudności, a przy ich większej ilości jest bolesne. Pamiętanie wszystkich poleceń do kompilacji i utworzenia pakunków możemy zlecić M2, szczególnie, że jego obecność w projekcie dostarcza nam innych możliwości bez dodatkowych nakładów pracy (zarządzanie zależnościami, tworzenie dokumentacji, automatyczne wykonywanie testów, itp.). Wdrożenie wtyczki Bundle Plugin for Maven to pozbycie się ręcznego zarządzania tworzeniem pliku MANIFEST.MF (ech, byłoby jeszcze przyjemniej, gdyby OSGi wspierało adnotacje). Stworzymy pojedyńczą definicję MANIFEST.MF (jako konfigurację wtyczki maven-bundle-plugin) w projekcie macierzystym i wszystkie, zarządzane przez niego projekty będą ją dziedziczyły. Poza tym, skorzystamy również z biblioteki OSGi - org.osgi.core - dostarczanej przez projekt Apache Felix i zlecimy M2 jej pobranie.

Zarządzanie projektem pakunków z M2 krok po kroku

Stworzenie struktury projektu

UWAGA: Zakłada się, że M2 został już wcześniej zainstalowany!

Uruchamiamy interpreter poleceń (aka konsolę) i wywołujemy wtyczkę archetype:create.

 mvn archetype:create -DgroupId=pl.jaceklaskowski.osgi.gettingstarted -DartifactId=OSGi-Article -Dversion=1.0

Projekt OSGi-Article będzie projektem macierzystym (głównym). Jest wymagany przez M2 w projektach wielomodułowych (więcej informacji znajduje się w dokumentacji M2 - How do I build more than one project at once?)

Zanim przejdziemy do stworzenia podprojektów (modułów w sensie M2) konieczne jest zmodyfikowanie pliku pom.xml, który jest plikiem konfiguracyjnym projektu zarządzanego przez M2. Modyfikujemy plik pom.xml tak, aby packaging zawierał wartość pom. Jedynie projekt typu pom może zarządzać innymi.

Opcjonalnie możemy zmienić nazwę projektu na OSGi Article (sekcja name).

Ostatecznie plik powinien zawierać następującą treść:

 <project xmlns="http://maven.apache.org/POM/4.0.0" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>pl.jaceklaskowski.osgi.gettingstarted</groupId>
   <artifactId>OSGi-Article</artifactId>
   <packaging>pom</packaging>
   <version>1.0</version>
   <name>OSGi Article</name>
   <url>http://maven.apache.org</url>
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>3.8.1</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
 </project>

Utworzenie podprojektów - HelloWorld oraz HelloWorldStopper

Projekt HelloWorld będzie odpowiadał projektowi pakunku OSGi HelloWorld (zmodyfikowany pakunek z części 1. serii Getting started with OSGi: Your first bundle) podczas, gdy HelloWorldStopper będzie odpowiadał pakunkowi OSGi HelloWorldKiller (zmodyfikowany pakunek z części 2. serii Getting started with OSGi: Interacting with the Framework), który jedynie zatrzymuje pakunek HelloWorld zamiast go usuwać z systemu (jak zasugerowano w jednym z komentarzy do artykułu Getting started with OSGi: Interacting with the Framework).

Wydajemy polecenie tworzące podprojekty dla naszych pakunków OSGi w katalogu głównym projektu OSGi Article, który stanie się ich projektem macierzystym.

 mvn archetype:create -DgroupId=pl.jaceklaskowski.osgi.gettingstarted -DartifactId=HelloWorld -Dversion=1.0

oraz

 mvn archetype:create -DgroupId=pl.jaceklaskowski.osgi.gettingstarted -DartifactId=HelloWorldStopper -Dversion=1.0

Wydając powyższe polecenia M2 zmodyfikował plik pom.xml o dodanie sekcji modules wskazującej na nasze nowoutworzone projekty.

 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   ...
   <modules>
     <module>HelloWorld</module>
     <module>HelloWorldStopper</module>
   </modules>
 </project>

Katalog src w projekcie macierzystym - OSGi Article - jest ignorowany przez M2, więc można go śmiało usunąć. Usuwamy dla uproszczenia struktury i zminimalizowania wystąpienia błędów nie związanych bezpośrednio z głównym celem projektu.

 $ pwd
 /cygdrive/c/projs/osgi/OSGi-Article
 
 $ rm -rf src

Praca z projektami w środowisku IDE

Pora zaprząc do pracy nasze kombajny programistyczne - ulubione środowisko IDE.

W dalszej części artykułu zakładam, że pracujemy z IDE, który obsługuje projekty zarządzane przez M2 jak własne.

Dla celów artykułu wybrałem Eclipse IDE 3.3M5.

Instalacja wtyczki M2 dla Eclipse opisana jest w moim artykule pakiet%C3%B3w OSGi z Apache Maven 2 Tworzenie pakietów OSGi z Apache Maven 2.

UWAGA: NetBeans IDE (z wtyczką Mevenide2-NetBeans) pracuje z projektami M2 jak z własnymi. Eclipse IDE wymaga stworzenia projektu typu Java ze wskazaniem katalogu ze źródłami, co nakłada na nas pewne kroki przed faktycznym otwarciem naszych projektów.

Uruchommy mvn compile, aby stworzyć odpowiednią strukturę katalogów potrzebną podczas importu projektów przez Eclipse IDE (w przeciwnym przypadku Eclipse korzystałby domyślnie z katalogu bin zamiast z target jak to ma miejsce w M2). Jest to również dobry moment, aby sprawdzić, że wykonane kroki są poprawne i dalsze problemy nie będą związane z niewłaściwą pracą M2 (jest to dobry zwyczaj, aby iteratywnie podchodzić do tworzenia projektów i sprawdzać działanie przy każdej sposobności).

 $ mvn compile
 [INFO] Scanning for projects...
 [INFO] Reactor build order:
 [INFO]   OSGi Article
 [INFO]   HelloWorld
 [INFO]   HelloWorldStopper
 [INFO] ----------------------------------------------------------------------------
 [INFO] Building OSGi Article
 [INFO]    task-segment: [compile]
 [INFO] ----------------------------------------------------------------------------
 [INFO] No goals needed for project - skipping
 [INFO] ----------------------------------------------------------------------------
 [INFO] Building HelloWorld
 [INFO]    task-segment: [compile]
 [INFO] ----------------------------------------------------------------------------
 [INFO] [resources:resources]
 [INFO] Using default encoding to copy filtered resources.
 [INFO] [compiler:compile]
 Compiling 1 source file to c:\projs\osgi\OSGi-Article\HelloWorld\target\classes
 [INFO] ----------------------------------------------------------------------------
 [INFO] Building HelloWorldStopper
 [INFO]    task-segment: [compile]
 [INFO] ----------------------------------------------------------------------------
 [INFO] [resources:resources]
 [INFO] Using default encoding to copy filtered resources.
 [INFO] [compiler:compile]
 Compiling 1 source file to c:\projs\osgi\OSGi-Article\HelloWorldStopper\target\classes
 [INFO]
 [INFO]
 [INFO] ------------------------------------------------------------------------
 [INFO] Reactor Summary:
 [INFO] ------------------------------------------------------------------------
 [INFO] OSGi Article .......................................... SUCCESS [0.015s]
 [INFO] HelloWorld ............................................ SUCCESS [3.375s]
 [INFO] HelloWorldStopper ..................................... SUCCESS [0.375s]
 [INFO] ------------------------------------------------------------------------
 [INFO] ------------------------------------------------------------------------
 [INFO] BUILD SUCCESSFUL
 [INFO] ------------------------------------------------------------------------
 [INFO] Total time: 4 seconds
 [INFO] Finished at: Fri Feb 23 13:49:51 CET 2007
 [INFO] Final Memory: 3M/254M
 [INFO] ------------------------------------------------------------------------

Zgodnie z komunikatem BUILD SUCCESSFUL wszystko działa poprawnie.

Otwieramy projekty HelloWorld oraz HelloWorldStopper w Eclipse IDE. Wymaga to stworzenia projektu Java (File->New->Project...->Java Project), gdzie podajemy katalog, gdzie stworzyliśmy projekty (opcja Create project from existing source) jak pokazano na poniższym obrazku.

Grafika:osgi-m2-NewJavaProject-HelloWorld.PNG

i wciskamy przycisk FINISH.

Pojawią się błędy, które zostaną rozwiązane włączając obsługę M2 w projekcie.

Grafika:osgi-m2-Maven2Enable-HelloWorld.PNG

Powtarzamy czynność tworzenia projektu (a właściwie importu) i włączenia obsługi M2 dla projektów HelloWorldStopper oraz OSGi Article.

Nie wystarczy to jednak do całkowitego pozbycia się wszystkich błędów co zmusza nas do usunięcia definicji katalogów źródłowych w projekcie macierzystym - OSGi Article. Zatwierdzając usunięcie (Remove a następnie OK) rozwiązujemy pozostałe błędy zgłaszane przez Eclipse IDE.

Ostatecznie Java Build Path dla projektu OSGi Article wygląda tak:

Grafika:osgi-m2-OSGiArticle-JavaBuildPath.PNG

Powinniśmy otrzymać następującą strukturę projektów.

Grafika:osgi-m2-PackageExplorer.PNG

W końcu nadszedł moment stworzenia klas pakunków OSGi jak opisano w artykułach Getting started with OSGi: Your first bundle oraz Getting started with OSGi: Interacting with the Framework z tą różnicą, że klasy tworzymy w pakiecie pl.jaceklaskowski.osgi.gettingstarted (całkowicie przypadkiem wybranym) oraz korzystamy z dobrodziejstw Eclipse IDE.

W końcu ponownie zajmujemy się właściwą pracą, a nie zmuszaniem Eclipse IDE do pracy z M2 (czy ktoś mówił, że będzie prościej?! ;-)).

Modyfikujemy plik pom.xml projektu głównego - OSGi Article. Zamieniamy zależność projektu (sekcja dependencies) na org.osgi.core, dodajemy sekcję build, która uaktywania wtyczkę maven-bundle-plugin we wszystkich projektach - głównym i pochodnym oraz definiujemy repozytoria zależności.

Ostatecznie plik pom.xml projektu OSGi Article powinien zawierać następującą treść:

 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>pl.jaceklaskowski.osgi.gettingstarted</groupId>
   <artifactId>OSGi-Article</artifactId>
   <packaging>pom</packaging>
   <version>1.0</version>
   <name>OSGi Article</name>
   <url>http://maven.apache.org</url>
   <dependencies>
     <dependency>
       <groupId>org.apache.felix</groupId>
       <artifactId>org.osgi.core</artifactId>
       <version>0.8.0-incubator</version>
     </dependency>
   </dependencies>
   <build>
     <plugins>
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
         <version>0.8.0-incubator</version>
         <extensions>true</extensions>
 	    <configuration>
 	      <instructions>
 	      	<Bundle-SymbolicName>${artifactId}</Bundle-SymbolicName>
 	      	<Private-Package>${pom.groupId}.*</Private-Package>
 	        <Bundle-Activator>${pom.groupId}.${pom.artifactId}</Bundle-Activator>
 	      </instructions>
 	    </configuration>
       </plugin>
     </plugins>
   </build>
   <repositories>
     <repository>
       <id>apache.m2.incubator</id>
       <name>Apache M2 Incubator Repository</name>
       <url>http://people.apache.org/repo/m2-incubating-repository/</url>
     </repository>
   </repositories>
   <pluginRepositories>
     <pluginRepository>
       <id>apache.m2.incubator</id>
       <name>Apache M2 Incubator Repository</name>
       <url>http://people.apache.org/repo/m2-incubating-repository/</url>
     </pluginRepository>
   </pluginRepositories>
   <modules>
     <module>HelloWorld</module>
     <module>HelloWorldStopper</module>
   </modules>
 </project>

UWAGA: Wtyczka M2 dla Eclipse nie rozpozna dodania zależności w projekcie macierzystym i wymagane jest zamknięcie wszystkich projektów (menu kontekstowe Close Project) i ponownego ich otwarcia (menu kontekstowe Open Project).

Modyfikujemy plik pom.xml dla projektów HelloWorld i HelloWorldStopper tak, aby zawierał sekcję packaging z wartością bundle (w przeciwnym wypadku wtyczka maven-bundle-plugin nie rozpozna projektu jako projektu pakunku).

Plik pom.xml dla projektu HelloWorld powinien zawierać następującą treść:

 <?xml version="1.0"?>
 <project>
   <parent>
     <artifactId>OSGi-Article</artifactId>
     <groupId>pl.jaceklaskowski.osgi.gettingstarted</groupId>
     <version>1.0</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>pl.jaceklaskowski.osgi.gettingstarted</groupId>
   <artifactId>HelloWorld</artifactId>
   <packaging>bundle</packaging>
   <name>HelloWorld</name>
   <version>1.0</version>
   <url>http://maven.apache.org</url>
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>3.8.1</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
 </project> 

Zauważ dodaną sekcję packaging, która domyślnie nie jest definiowana i jej wartość wynosi jar.

Utworzenie pakunku HelloWorld (projekt HelloWorld)

W projekcie HelloWorld, tworzymy klasę pl.jaceklaskowski.osgi.gettingstarted.HelloWorld, o następującej treści:

 package pl.jaceklaskowski.osgi.gettingstarted;
 
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
 /**
  * Pomysł zapożyczony z artykułu Getting started with OSGi: Your first bundle
  * (http://www.eclipsezone.com/eclipse/forums/t90365.rhtml)
  */
 public class HelloWorld implements BundleActivator {
 
     public void start(BundleContext context) {
         System.out.println("Hello EclipseZone Readers!");
     }
 
     public void stop(BundleContext context) {
         System.out.println("Goodbye EclipseZone Readers!");
     }
 
 }

Utworzenie pakunku HelloWorldStopper (projekt HelloWorldStopper)

W projekcie HelloWorldStopper, tworzymy klasę pl.jaceklaskowski.osgi.gettingstarted.HelloWorldStopper, o następującej treści:

 package pl.jaceklaskowski.osgi.gettingstarted;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
 
 /**
  * Pomysł zapożyczony z artykułu Getting started with OSGi: Interacting with the Framework
  * (http://www.eclipsezone.com/eclipse/forums/m92131032.html)
  */
 public class HelloWorldStopper implements BundleActivator {
 
     private static final String HELLO_WORLD_BUNDLE_NAME = "HelloWorld";
 
     public void start(BundleContext context) throws Exception {
         System.out.println(HELLO_WORLD_BUNDLE_NAME + "Stopper searching...");
         Bundle[] bundles = context.getBundles();
         for (int i = 0; i < bundles.length; i++) {
             if (HELLO_WORLD_BUNDLE_NAME.equals(bundles[i].getSymbolicName())) {
                 try {
                     System.out.println(HELLO_WORLD_BUNDLE_NAME + " found, " + "stopping!");
                     bundles[i].stop();
                     return;
                 } catch (BundleException e) {
                     System.err.println("Failed: " + e.getMessage());
                 }
             } else {
                 System.out.println(bundles[i].getSymbolicName() + " ignored.");
             }
         }
         System.out.println("Hello World bundle not found");
     }
 
     public void stop(BundleContext context) throws Exception {
         System.out.println(HELLO_WORLD_BUNDLE_NAME + "Stopper shutting down");
     }
 
 }

Struktura projektów w Eclipse IDE

Struktura projektów w Eclipse IDE powinna wyglądać następująco (opcjonalnie możemy skasować niewykorzystywaną klasę pl.jaceklaskowski.osgi.gettingstarted.App w projektach, która jest domyślnie tworzona przez M2):

Grafika:osgi-m2-finalprojectsstructure.PNG

Budowanie pakunków w Eclipse IDE

Utworzenie pakunków z poziomu konsoli sprowadziłoby się do uruchomienia polecenia mvn package. My decydujemy się wykonać to polecenie z poziomu Eclipse (co okaże się za moment, że nie było dobrym posunięciem).

W tym celu definiujemy narzędzie zewnętrzne (menu Run->External Tools->External Tools...) typu m2 build.

Grafika:osgi-m2-ExternalTools.PNG

Wciskamy przycisk Run.

Jakimś cudem M2 uruchomiony jest wyłącznie w pojedyńczym projekcie OSGi Article (!) Wygląda jakby definicja M2 w Eclipse uaktywniała opcję -N (lub alternatywnie --non-recursive, która wyłącza przetwarzanie podprojektów). Cóż, będziemy zmuszeni do korzystania z linii poleceń (a nie mówiłem, że to nie był dobry pomysł?!).

Wykonujemy polecenie mvn clean package w katalogu głównym OSGi Article.

 jlaskowski@dev /cygdrive/c/projs/osgi/OSGi-Article
 $ mvn clean package
 [INFO] Scanning for projects...
 [INFO] Reactor build order:
 [INFO]   OSGi Article
 [INFO]   HelloWorld
 [INFO]   HelloWorldStopper
 [INFO] ----------------------------------------------------------------------------
 [INFO] Building OSGi Article
 [INFO]    task-segment: [clean, package]
 [INFO] ----------------------------------------------------------------------------
 [INFO] [clean:clean]
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\target
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\target\classes
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\target\test-classes
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\target\site
 [INFO] [site:attach-descriptor]
 [INFO] ----------------------------------------------------------------------------
 [INFO] Building HelloWorld
 [INFO]    task-segment: [clean, package]
 [INFO] ----------------------------------------------------------------------------
 [INFO] [clean:clean]
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\HelloWorld\target
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\HelloWorld\target\classes
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\HelloWorld\target\test-classes
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\HelloWorld\target\site
 [INFO] [resources:resources]
 [INFO] Using default encoding to copy filtered resources.
 [INFO] [compiler:compile]
 Compiling 1 source file to c:\projs\osgi\OSGi-Article\HelloWorld\target\classes
 [INFO] [resources:testResources]
 [INFO] Using default encoding to copy filtered resources.
 [INFO] [compiler:testCompile]
 Compiling 1 source file to c:\projs\osgi\OSGi-Article\HelloWorld\target\test-classes
 [INFO] [surefire:test]
 [INFO] Surefire report directory: c:\projs\osgi\OSGi-Article\HelloWorld\target\surefire-reports
 
 -------------------------------------------------------
  T E S T S
 -------------------------------------------------------
 Running pl.jaceklaskowski.osgi.gettingstarted.AppTest
 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.032 sec
 
 Results :
 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
 
 [INFO] [bundle:bundle]
 [INFO] ----------------------------------------------------------------------------
 [INFO] Building HelloWorldStopper
 [INFO]    task-segment: [clean, package]
 [INFO] ----------------------------------------------------------------------------
 [INFO] [clean:clean]
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\HelloWorldStopper\target
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\HelloWorldStopper\target\classes
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\HelloWorldStopper\target\test-classes
 [INFO] Deleting directory c:\projs\osgi\OSGi-Article\HelloWorldStopper\target\site
 [INFO] [resources:resources]
 [INFO] Using default encoding to copy filtered resources.
 [INFO] [compiler:compile]
 Compiling 1 source file to c:\projs\osgi\OSGi-Article\HelloWorldStopper\target\classes
 [INFO] [resources:testResources]
 [INFO] Using default encoding to copy filtered resources.
 [INFO] [compiler:testCompile]
 Compiling 1 source file to c:\projs\osgi\OSGi-Article\HelloWorldStopper\target\test-classes
 [INFO] [surefire:test]
 [INFO] Surefire report directory: c:\projs\osgi\OSGi-Article\HelloWorldStopper\target\surefire-reports
 
 -------------------------------------------------------
  T E S T S
 -------------------------------------------------------
 Running pl.jaceklaskowski.osgi.gettingstarted.AppTest
 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.031 sec
 
 Results :
 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
 
 [INFO] [bundle:bundle]
 [INFO]
 [INFO]
 [INFO] ------------------------------------------------------------------------
 [INFO] Reactor Summary:
 [INFO] ------------------------------------------------------------------------
 [INFO] OSGi Article .......................................... SUCCESS [1.078s]
 [INFO] HelloWorld ............................................ SUCCESS [2.235s]
 [INFO] HelloWorldStopper ..................................... SUCCESS [1.219s]
 [INFO] ------------------------------------------------------------------------
 [INFO] ------------------------------------------------------------------------
 [INFO] BUILD SUCCESSFUL
 [INFO] ------------------------------------------------------------------------
 [INFO] Total time: 4 seconds
 [INFO] Finished at: Fri Feb 23 14:41:27 CET 2007
 [INFO] Final Memory: 7M/254M
 [INFO] ------------------------------------------------------------------------

Uruchomienie pakunków OSGi

Uruchomienie polega na wykonaniu komend jak opisano w artykule Getting started with OSGi: Interacting with the Framework. Przykładowa sesja mogłaby wyglądać tak:

 jlaskowski@dev /cygdrive/c/projs/osgi/OSGi-Article
 $ java -jar c\:/.m2/org/eclipse/osgi/3.3.0.v20070208/osgi-3.3.0.v20070208.jar -console -configuration config
 
 osgi> ss
 
 Framework is launched.
 
 id      State       Bundle
 0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
 
 osgi> install file:HelloWorld/target/HelloWorld-1.0.jar
 Bundle id is 1
 
 osgi> ss
 
 Framework is launched.
 
 id      State       Bundle
 0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
 1       INSTALLED   HelloWorld_1.0.0
 
 osgi> install file:HelloWorldStopper/target/HelloWorldStopper-1.0.jar
 Bundle id is 2
 
 osgi> ss
 
 Framework is launched.
 
 id      State       Bundle
 0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
 1       INSTALLED   HelloWorld_1.0.0
 2       INSTALLED   HelloWorldStopper_1.0.0
 
 osgi> start 1
 Hello EclipseZone Readers!
 
 osgi> ss
 
 Framework is launched.
 
 id      State       Bundle
 0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
 1       ACTIVE      HelloWorld_1.0.0
 2       RESOLVED    HelloWorldStopper_1.0.0
 
 osgi> start 2
 HelloWorldStopper searching...
 org.eclipse.osgi ignored.
 HelloWorld found, stopping!
 Goodbye EclipseZone Readers!
 
 osgi> ss
 
 Framework is launched.
 
 id      State       Bundle
 0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
 1       RESOLVED    HelloWorld_1.0.0
 2       ACTIVE      HelloWorldStopper_1.0.0
 
 osgi> stop 2
 HelloWorldStopper shutting down
 
 osgi> ss
 
 Framework is launched.
 
 id      State       Bundle
 0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
 1       RESOLVED    HelloWorld_1.0.0
 2       RESOLVED    HelloWorldStopper_1.0.0
 
 osgi> close

Dodatkowy parametr -configuration podany przy wywołaniu konsoli OSGi wskazuje na katalog, gdzie zapisywany jest stan środowiska. Domyślnie katalogiem konfiguracyjnym jest podkatalog configuration katalogu biblioteki (w naszym przypadku byłby to c:/.m2/org/eclipse/osgi/3.3.0.v20070208/configuration). Zgodnie ze specyfikacją OSGi stan środowiska jest utrwalany przy zamknięciu i stan pakunków jest przywracany do stanu sprzed ostatniego zamknięcia środowiska OSGi. Usunięcie katalogu wskazanego przez parametr -configuration (w naszym przypadku config) spowoduje, że następne uruchomienie będzie rozpoczynało konfigurację zerową (standardową).

Jako dobre ćwiczenie na zakończenie poznawania OSGi z pomocą M2 i maven-bundle-plugin można uruchomić oba pakunki (polecenie start), a następnie zamknąć konsolę OSGi (polecenie close). Ponowne uruchomienie gwarantuje, że oba pakunki będę uruchomione (nie zapomnij o usunięciu katalogu ze stanem środowiska).

 jlaskowski@dev /cygdrive/c/projs/osgi/OSGi-Article
 $ java -jar c\:/.m2/org/eclipse/osgi/3.3.0.v20070208/osgi-3.3.0.v20070208.jar -console -configuration config
 
 osgi> ss
 
 Framework is launched.
 
 id      State       Bundle
 0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
 
 osgi> install file:HelloWorld/target/HelloWorld-1.0.jar
 Bundle id is 1
 
 osgi> install file:HelloWorldStopper/target/HelloWorldStopper-1.0.jar
 Bundle id is 2
 
 osgi> start 1
 Hello EclipseZone Readers!
 
 osgi> start 2
 HelloWorldStopper searching...
 org.eclipse.osgi ignored.
 HelloWorld found, stopping!
 Goodbye EclipseZone Readers!
 
 osgi> ss
 
 Framework is launched.
 
 id      State       Bundle
 0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
 1       RESOLVED    HelloWorld_1.0.0
 2       ACTIVE      HelloWorldStopper_1.0.0
 
 osgi> start 1
 Hello EclipseZone Readers!
 
 osgi> ss
 
 Framework is launched.
 
 id      State       Bundle
 0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
 1       ACTIVE      HelloWorld_1.0.0
 2       ACTIVE      HelloWorldStopper_1.0.0
 
 osgi> close
 
 HelloWorldStopper shutting down
 Goodbye EclipseZone Readers!
 
 jlaskowski@dev /cygdrive/c/projs/osgi/OSGi-Article
 $ java -jar c\:/.m2/org/eclipse/osgi/3.3.0.v20070208/osgi-3.3.0.v20070208.jar -console -configuration config
 Hello EclipseZone Readers!
 HelloWorldStopper searching...
 org.eclipse.osgi ignored.
 HelloWorld found, stopping!
 Goodbye EclipseZone Readers!
 
 osgi> ss
 
 Framework is launched.
 
 id      State       Bundle
 0       ACTIVE      org.eclipse.osgi_3.3.0.v20070208
 1       RESOLVED    HelloWorld_1.0.0
 2       ACTIVE      HelloWorldStopper_1.0.0
 
 osgi> close
 
 HelloWorldStopper shutting down
Osobiste