Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Utilizzare OSGi in Eclipse

Articolo di introduzione all'utilizzo di OSGI in ambiente Eclipse
Articolo di introduzione all'utilizzo di OSGI in ambiente Eclipse
Link copiato negli appunti

OSGI è un framework, frutto del lavoro di un consorzio di aziende tra cui Oracle, IBM, Ericsson ed altre, il cui scopo è semplificare la realizzazione di applicazioni modulari in java.

Applicazioni modulari

OSGI consente la definizione e l'utilizzo dell'intero ciclo di vita (registrazione, pubblicazione, deploy, etc) di servizi, tramite l'implementazione di moduli (in questo contesto chiamati bundles), di un service registry, e di un ambiente di esecuzione.
L'idea è migliorare il supporto degli ambienti java alla creazione e all'utilizzo di software modulare, partendo dall'osservazione di alcune carenze tutt'ora presenti nel linguaggio, in particolare:

1. limiti dei modificatori di accesso

Java ha i modificatori di accesso default (implicito), public, protected e private che limitano l'accesso alle classi ed al relativo codice, ma le stesse regole di definizione delle regole non possono ad esempio essere applicate ad un package. Questo limite si traduce ad esempio nel fatto che se consideriamo due package A e B distinti, con A contenente soltanto l'interfaccia (le api) e B contenente soltanto la rispettiva implementazione, è necessario garantire che A e B siano visibili tra di loro, il che comporta in genere esserlo praticamente per tutti.

Figura 1. api ed implementazione concreta
(clic per ingrandire)


api ed implementazione concreta

Consideriamo una interfaccia di esempio:

package org.foo.hello;
public interface Hello {
void sayHello();
}

quindi in un altro package una classe che la implementa:

package org.foo.hello.impl;
import org.foo.hello.Greeting;
public class HelloImpl implements Hello {
	final String name;
	public HelloImpl(String name) {
		this.name = name;
	}
	public void sayHello() {
		System.out.println("Hello, " + this.name + "!");
	}
}

ed infine una classe di test nel terzo package:

package org.foo.hello.main;
import org.foo.hello.Hello;
import org.foo.hello.impl.HelloImpl;
public class Main {
	public static void main(String[] args) {
	Hello greet = new HelloImpl("Hello World");
	greet.sayHello();
}
}

L'obiettivo era in questo caso rendere accessibile la classe di implementazione creata attraverso l'interfaccia, ma se ribaltassimo il problema, purtroppo è evidente che non esiste un meccanismo che ci consente di impedire di accedere alla classe direttamente.

Il problema è parzialmente risolvibile utilizzando il pattern Inversion Of Control, che sarà trattato in altri articoli.

2. il classloader di java

Il class loader di java non tiene conto della versione delle classi e degli archivi (vedi jar) che carica. Ad esempio supponiamo che una nostra applicazione necessiti di una classe memorizzata in un jar che chiamiamo 'mioarchivio.jar', presente sul classpath in due versioni: 1.0 e 1.1. In questo caso non abbiamo modo di specificare esplicitamente quale versione caricare escludendo l'altra; semplicemente dovremo assicurarci che il class loader carichi la versione corretta, provvedendo ad escludere quella sbagliata dal class path, o utilizzando dei sistemi di gestione delle dipendenze (come maven, ivy, etc), in modo da intervenire a monte del problema.

Cosa è OSGI

OSGI (Open Service Gateway Initiative) è una specifica che permette di costruire applicazioni modulari a componenti (i Bundle) e che introduce una programmazione Service Oriented, permettendo una separazione tra interfaccia ed implementazione molto più rigorosa di quella nativa Java.

Esistono diverse implementazioni (container) di OSGI, conformi alle specifiche e qui tra di loro equivalenti:

L'interfaccia prevede l'esistenza di un registro dove pubblicare e ricercare i servizi e di cambiare l'implementazione degli stessi a runtime in maniera dinamica e trasparente.

OSGI è composto dal framework vero e proprio, e dai servizi standard

Il framework prevede una separazione

  • module layer: qui sono 'collocati' i moduli (componenti o bundle)
  • lifecycle layer: si occupa della gestione del ciclo di vita dei bundle, e permette anche l'accesso ai servizi che il framework usa.
  • service layer: gestisce l'interazione tra i diversi servizi esposti dai bundle.

come è fatto un bundle

Un bundle semplicemente è un archivio jar contenente informazioni aggiuntive nel suo file MANIFEST.MF (il contenuto è descritto dalle specifiche di OSGI).

Nel caso dell'interfaccia relativa al nostro esempio:

Bundle-ManifestVersion: 2
Bundle-Name: Hello API
Bundle-SymbolicName: org.foo.hello
Bundle-Version: 1.0
Export-Package: org.foo.hello;version="1.0"

Prima di addentrarci in un esempio che chiarirà in maniera esaustiva i diversi aspetti esposti notiamo che nel MANIFEST.MF è presente la riga di testo:

Export-Package: org.foo.hello;version="1.0"

questa riga indica al container che il bundle esporta all'esterno (cioè rende visibile) unicamente il package org.foo.hello, e che quindi non sarà possibile accedere a classi contenute in altri package di questo bundle.

OSGI quindi introduce modificatori di accesso a livello di package, e permette di specificare la versione associata al package esportato.

In particolare i due parametri che identificano univocamente un bundle sono i seguenti:

Bundle-SymbolicName: org.foo.hello
Bundle-Version: 1.0

Esempio: un bundle osgi con Eclipse

Vediamo una semplice applicazione di esempio, riprendiamo il semplice esempio 'helloWorld' e realizziamolo attraverso OSGI ed Eclipse.

Realizziamo per primo il modulo che contiene l'interfaccia della nostra semplice classe, avviamo eclipse e scegliamo file/new Plugin-> project

Figura 2. osgi in eclipse: creazione bundle
(clic per ingrandire)


osgi in eclipse: creazione bundle

Abbiamo usato come nome del progetto org.foo.hello e scelto il container equinox.

OSGI dà una grossa importanza al versioning di package e bundle e questo aspetto anche se può sembrare molto
rigoroso è molto importante in termini di modularità e consistenza tra i moduli stessi:

Figura 3. osgi in eclipse: versione bundle
(clic per ingrandire)


osgi in eclipse: versione bundle

deselezionare la voce 'generate an activator...': un activator è una classe che permette l'avvio del bundle, un po' come la classe main di un jar.

Il cerchio rosso evidenzia la versione del bundle che OSGI considera suddivisi in questo formato: major.micro.minor.qualifier, con i primi tre che in genere sono numeri e l'ultimo un alfanumerico. Nel nostro caso la versione del modulo è 1.0.0.qualifier ma avremo potuto scrivere anche qualcosa come 1.1.0.mybundle.

Premere il tasto 'finish' ed eclipse creerà il progetto.

Creiamo adessp un package con lo stesso nome del progetto, cioè di nome org.foo.hello, all'interno del quale mettere la nostra interfaccia di riferimento:

package org.foo.hello;
public interface Hello {
void sayHello();
}

fatto questo clicchiamo due volte sul file MANIFEST.MF si aprirà la seguente schermata:

Figura 4. osgi in eclipse: il progetto
(clic per ingrandire)


osgi in eclipse: il progetto

selezioniamo il tab Runtime e nella sezione exported package; clicchiamo su add digitando org.foo.hello:

Figura 5. osgi in eclipse: selezione dei package da esporre
(clic per ingrandire)


osgi in eclipse: selezione dei package da esporre

quindi salviamo il progetto e clicchiamo sulla tab MANIFEST.MF:

Figura 6. osgi in eclipse: creazione del file MANIFEST.MF
(clic per ingrandire)


osgi in eclipse: creazione del file MANIFEST.MF

A questo punto creiamo un secondo bundle org.foo.hello.impl, contenente stavolta l'implementazione concreta della nostra interfaccia, seguendo la stessa modalità di creazione del bundle vista per l'interfaccia stessa.

Stavolta però dopo aver creato il bundle dovremo specificare la dipendenza dalla nostra interfaccia, perché la nostra nuova classe possa implementarla!

Selezioniamo il tab 'dependencies' e selezioniamo il bundle org.foo.hello; creiamo infine l'ultimo bundle che sarà quello che attiverà l'applicazione.

Figura 7. osgi in eclipse: dipendenze
(clic per ingrandire)


osgi in eclipse: dipendenze

... ed abbiamo specificato che il bundle org.foo.hello.impl dipende dal package org.foo.hello!

Questo il contenuto del MANIFEST.MF:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Impl
Bundle-SymbolicName: org.foo.hello.impl
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: org.foo.hello

Nell'ultima riga di codice è facile riconoscere la definizione della dipendenza.

Ti consigliamo anche