Quando dovrei usare Import-Package e quando dovrei usare Require-Bundle?

OSGi consente di determinare le dipendenze tramite Import-Package , che collega solo un singolo pacchetto (esportato da qualsiasi bundle) e Require-Bundle , che collega le esportazioni di un bundle specifico.

Nella creazione di un’applicazione OSGi greenfield, quale approccio dovrei utilizzare per rappresentare le dipendenze? La maggior parte dei bundle sarà interna, ma ci saranno alcune dipendenze da pacchetti esterni (open-source).

Credo che Require-Bundle sia una cosa di Eclipse (che ora è disponibile nelle specifiche OSGi per ospitare Eclipse). Il modo “puro” OSGi è quello di utilizzare Import-Package , in quanto disaccoppia in modo specifico il pacchetto dal pacchetto che lo fornisce. Dovresti dichiarare dipendenze sulla funzionalità di cui hai bisogno (l’API Java fornita da una determinata versione di un determinato pacchetto) invece di dove proviene quella funzionalità (che non dovrebbe essere rilevante per te). Ciò mantiene la composizione dei pacchi più flessibile.

Analogia JavaScript: è come rilevare se un browser Web supporta una determinata API anziché dedurre da quello che la stringa user-agent indica quale tipo di browser è.

Peter Kriens della OSGi Alliance ha altro da dire su questo sul blog OSGi .

Probabilmente l’unico caso in cui è necessario utilizzare Require-Bundle è se si dispone di pacchetti divisi, ovvero di un pacchetto distribuito su più bundle. I pacchetti divisi sono ovviamente molto scoraggiati.

Favorire il pacchetto di importazione su Richieste-Bundle.

Richiede-Bundle:

  • specifica il pacchetto esplicito (e la versione) da utilizzare. Se un bundle requirde deve essere refactored e un pacchetto spostato altrove, i dipendenti devono modificare il loro MANIFEST.MF
  • ti dà accesso a TUTTE le esportazioni del pacchetto, indipendentemente da cosa siano e indipendentemente dal fatto che tu ne abbia bisogno. Se le parti di cui non hai bisogno hanno le loro dipendenze, ne avrai bisogno
  • i pacchetti possono essere riesportati
  • sebbene scoraggiato, consente l’uso di pacchetti divisi, ovvero: un pacchetto distribuito su più pacchetti
  • può essere utilizzato per dipendenze non di codice, ad es. risorse, aiuto, ecc.

Import-Package:

  • accoppiamento più lento, viene specificato solo il pacchetto (e la versione) e il runtime trova il pacchetto richiesto
  • Le implementazioni effettive possono essere eliminate
  • I pacchetti dipendenti possono essere spostati in diversi pacchetti dal proprietario del pacchetto
  • Ma richiede che vengano mantenuti più metadati (ad esempio: ciascun nome di pacchetto) a livelli inferiori di granularità

Credo che Importa-pacchetto ti dia un accoppiamento più sciolto e dovrebbe essere preferito. Lo uso quando dichiaro dipendenze su pacchetti che non possiedo, come ad esempio slf4j, e posso scambiare implementazioni come vorrei. Io uso Require-Bundle quando la dipendenza è qualcosa su cui ho il controllo, come i miei bundle, perché ogni cambiamento importante sarebbe passato attraverso me stesso comunque.

Evita il pacchetto di importazione. Poiché i pacchetti forniscono relazioni molti-a-molti tra i pacchetti, sono soggetti a cicli di dipendenza difficili da individuare ed evitare.

Require-Bundle, d’altra parte, fa riferimento a un singolo bundle, rendendo il grafico delle dipendenze protetto dai cicli da un banale controllo in fase di compilazione. Con Require-Bundle è molto più semplice build un’architettura a livelli con un livello di astrazione inferiore isolato.

Import-Package dovrebbe essere migliore perché, come detto in precedenza, è ansible spostare un pacchetto da un pacchetto all’altro senza modificare MANIFEST.MF del client esistente.

Ma…

C’è un motivo pratico per utilizzare Require-Bundle se si utilizza Eclipse per sviluppare i bundle:

Eclipse non usa i pacchetti come unità di risoluzione. Usa pacchi. Cioè, se si utilizza un pacchetto di un pacchetto, Eclipse compila il pacchetto senza segnalare alcun problema con l’uso del resto dei pacchetti non importati da quel pacchetto.

Potresti (tu sei umano) pensare che tutto sia OK e caricare il tuo bundle per la distribuzione ma … il tuo bundle si romperà in fase di runtime.

Ne sono sicuro perché questo problema è successo (a me!) Oggi.

La soluzione migliore sarebbe quella di modificare il contenitore del classpath Eclipse ma … se questo non verrà fatto … potresti decidere di evitare questo tipo di problemi che richiedono bundle, anziché pacchetti, pagando il prezzo indicato (nessun retrocompatibile codice di movimento tra pacchi).

Non sono convinto che l’utilizzo di Import-Package sia migliore, perché la mia aspettativa predefinita quando si lavora con un bundle è di lavorare con l’API pubblica associata. Per questo motivo, Require-Bundle ha più senso.