2010-05-04 18 views
7

Sto usando OSGi per il mio ultimo progetto al lavoro, ed è piuttosto bello per quanto riguarda la modularità e la funzionalità.Che cos'è un flusso di lavoro di sviluppo OSGi ragionevole?

Ma non sono soddisfatto del flusso di lavoro di sviluppo. Alla fine, ho in programma di avere 30-50 bundle separati, disposti in un grafico delle dipendenze - presumibilmente, questo è ciò per cui OSGi è progettato. Ma non riesco a capire un modo pulito per gestire le dipendenze al tempo compilare.

Esempio: i pacchetti A e B. B dipendono dai pacchetti definiti in A. Ciascun pacchetto viene sviluppato come progetto Java separato.

Per compilare B, A deve essere nel percorso di classe javac.

  1. di riferimento la posizione del file system del progetto A in script di build di B:

    fare?

  2. Costruisci A e getta il contenitore nella directory lib di B?
  3. Affidatevi alla funzione "progetti di riferimento" di Eclipse e utilizzate sempre il classpath di Eclipse per compilare (ugh)
  4. Utilizzare una directory di "lib" comune per tutti i progetti e scaricare i contenitori di bundle lì dopo la compilazione?
  5. Configurare un repository di bundle, analizzare il manifest dallo script di build e tirare giù i bundle richiesti dal repository?

No. 5 suona il più pulito, ma anche come un sacco di spese generali.

risposta

2

In sostanza, è possibile utilizzare:

  • dipendenza sorgente (con "progetti di riferimento" di Eclipse)
  • dipendenza binario (utilizzando il barattolo di fascio A)

Ma dal momento che la dipendenza binario è molto più pulito, è anche il tipo di dipendenza meglio gestito da un framework di gestione del rilascio come Maven.
E puoi integrare Maven nel tuo progetto Eclipse tramite m2eclipse.

The Maven plugin per utilizzare sarebbe allora: maven-bundle-plugin, che si può vedere in azione in:

Considera questo esempio più reale utilizzando l'implementazione del servizio log di Felix.
Il progetto del servizio di log è costituito da un unico pacchetto: org.apache.felix.log.impl.
Ha una dipendenza dalle interfacce principali OSGi e una dipendenza dalle interfacce Compiegium OSGi per le specifiche interfacce dei servizi di registro.Di seguito è riportato il suo file POM:

<project> 
    <modelVersion>4.0.0</modelVersion> 
    <groupId>org.apache.felix</groupId> 
    <artifactId>org.apache.felix.log</artifactId> 
    <packaging>bundle</packaging> 
    <name>Apache Felix Log Service</name> 
    <version>0.8.0-SNAPSHOT</version> 
    <description> 
    This bundle provides an implementation of the OSGi R4 Log service. 
    </description> 
    <dependencies> 
    <dependency> 
     <groupId>${pom.groupId}</groupId> 
     <artifactId>org.osgi.core</artifactId> 
     <version>0.8.0-incubator</version> 
    </dependency> 
    <dependency> 
     <groupId>${pom.groupId}</groupId> 
     <artifactId>org.osgi.compendium</artifactId> 
     <version>0.9.0-incubator-SNAPSHOT</version> 
    </dependency> 
    </dependencies> 
    <build> 
    <plugins> 
     <plugin> 
     <groupId>org.apache.felix</groupId> 
     <artifactId>maven-bundle-plugin</artifactId> 
     <extensions>true</extensions> 
     <configuration> 
      <instructions> 
      <Export-Package>org.osgi.service.log</Export-Package> 
      <Private-Package>org.apache.felix.log.impl</Private-Package> 
      <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName> 
      <Bundle-Activator>${pom.artifactId}.impl.Activator</Bundle-Activator> 
      <Export-Service>org.osgi.service.log.LogService,org.osgi.service.log.LogReaderService</Export-Service> 
      </instructions> 
     </configuration> 
     </plugin> 
    </plugins> 
    </build> 
</project> 
+0

Le dipendenze binarie sono cose pericolose da consigliare. Ho aiutato un cliente la scorsa settimana a eseguire il debug di un problema con il caricatore di classi causato dall'avere 2 copie dello stesso barattolo binario in 2 bundle diversi. Quando hanno tentato di passare istanze di oggetti dal jar binario da un bundle all'altro erano presenti un'eccezione cast di classe. È molto meglio usare le istruzioni del pacchetto di importazione/esportazione come previsto. Nel caso del cliente, la soluzione consisteva nel creare un pacchetto dal barattolo binario che ha esportato i pacchetti richiesti. Quindi entrambi i pacchetti clienti hanno importato i pacchetti necessari dal nuovo pacchetto. –

+0

Hm. Speravo di evitare di rendere Mavenizing l'intero progetto, ma potrei non riuscire ad evitarlo. – levand

+0

Hai un seguito da questa domanda, come l'hai gestita? Ho un problema molto simile che ho risolto reinventando la ruota Maven. Ci sono voluti molti sforzi per evitare l'utilizzo di Maven, quindi alla fine ho trovato una soluzione che era un sottoinsieme di Maven che alla fine dovrò convertire a Maven. Più le dipendenze del progetto diventano complesse, maggiori sono i benefici che Maven offre a ciò che proviene da qualcuno che non gradisce la complessità di esso). – Chris

7

La mia azienda ha più di 100 progetti di bundle e usiamo Eclipse per gestire le dipendenze. Tuttavia, non raccomando l'approccio "Plugin richiesti" per la gestione delle dipendenze. La soluzione migliore è creare progetti plugin. Esportare solo i pacchetti da ciascun progetto che si desidera essere visibili. Poi sul lato delle importazioni effettuare le seguenti operazioni:

Aprire l'editor manifesto

Vai alla scheda dipendenze In basso a sinistra è una sezione chiamata "gestione automatizzata delle dipendenze"

Aggiungi alcun plugin che il plugin corrente dipende da lì

Una volta scritto il codice, è possibile fare clic sul collegamento "aggiungi dipendenze" in quella scheda per eseguire automaticamente il calcolo dei pacchetti importati.

Se si esegue da Eclipse, questo viene eseguito automaticamente quando si esegue.

I vantaggi di questo approccio sono che i bundle creati utilizzano solo il meccanismo di importazione/esportazione del pacchetto definito da OSGi, al contrario di qualcosa di Eclipse.

Se vuoi saperne di più, ti consiglio di visitare questo sito e ordinare il libro. È eccellente

http://equinoxosgi.org/

+0

Questa è una soluzione molto più pratica (quella basata su Maven), integrata con Eclipse PDE. +1 – VonC

2

C'è un 6 ° opzione, che ho usato per diversi progetti, che è quello di utilizzare un unico progetto Eclipse (non un progetto plug-in, ma solo un progetto Java ordinario) e mettere tutto il codice sorgente lì dentro. Un file di build associato al progetto semplicemente compila tutto il codice in un singolo passaggio e successivamente crea bundle dalle classi compilate (usando Bnd da Ant o da BndTools che presto verrà rilasciato).

Questo ha il lato negativo che non onora la visibilità durante lo sviluppo e il tempo di compilazione, ma il vantaggio che si tratta di un modello di sviluppo davvero semplice che consente tempi di compilazione e implementazione molto rapidi.

5

Bene, fai ciò che dovresti avere molto tempo prima, implementazione separata e API ... ok, questo non è sempre così facile sui sistemi esistenti, ma quel modello ha un enorme botto. Una volta che la tua API si trova in un bundle/jar separato (molto più stabile), puoi compilare i client e le implementazioni su quel bundle/jar.

Una delle qualità principali di un pacchetto di successo è che fa il minimo possibile di ipotesi sul mondo esterno. Ciò implica che non è necessario compilare i bundle contro cui si esegue in fase di esecuzione, ma preferisco provare a non farlo. Dovresti compilare solo il set minimo di dipendenze dei bundle. Se vengono fatte delle ipotesi, sono esplicite come pacchetti importati e l'uso dei servizi. I sistemi OSGi ben progettati tentano di utilizzare i servizi per tutte le comunicazioni inter-bundle. Questo modello non solo elimina i problemi di caricamento della classe, ma rende anche più disaccoppiata la configurazione della build.

Sfortunatamente la maggior parte del codice è scritto come librerie che hanno un'interfaccia piuttosto ampia perché gestiscono molte delle funzionalità che i servizi forniscono fuori dalla scatola come Fabbriche e Ascoltatori. Questo codice ha una stretta relazione tra implementazione e API, quindi è necessario avere lo stesso sul percorso classe durante la compilazione e in OSGi. Una soluzione a questo problema consiste nell'includere questo tipo di codice all'interno del bundle che lo utilizza (ma assicurarsi che nessun oggetto di questa libreria non presenti perdite in altri bundle). Un po 'di consumo extra di memoria, ma ti salva da alcuni mal di testa.

Quindi con OSGi, provare a creare sistemi che si basano su servizi e compilare contro la loro API di servizio, non un pacchetto di implementazione.

Problemi correlati