vai al contenuto principale

Progetti base

Livebase mette a disposizione una serie di progetti base che permettono di iniziare immediatamente lo sviluppo dei Plugin.

Sappiamo che per creare un plugin Livebase dobbiamo avere una minima conoscenza dell’ambiente OSGi ed effettuare una serie di passaggi per configurare il bundle, molti dei quali sono automatizzabili con degli script Gradle. Sono dunque necessarie molte competenze, per cui abbiamo predisposto una serie di progetti base già configurati per consentirti di iniziare immediatamente lo sviluppo di un plugin.

Attualmente sono disponibili tre progetti base, reperibili presso questo repository BitBucket:

  • Plugin singolo (mono-bundle): la configurazione più semplice e leggera. Ideale se hai bisogno di un solo plugin per la tua Cloudlet, o se sei nuovo allo sviluppo dei plugin Livebase.
    Plugin project mono
  • Multi plugin (multi-bundle): un template più flessibile che consente di realizzare più plugin per la singola Cloudlet. È un multi-progetto Gradle costituito da un progetto radice, che contiene la configurazione comune, e tanti progetti foglia quanti sono i plugin che si desidera produrre.
    Plugin project multi
  • Multi plugin preconfigurato per jOOQ (multi-bundle-jooq): è anch’esso un multi-progetto, preconfigurato per utilizzare il framework jOOQ che facilita l’accesso al database delle Cloudlet.

Setup del progetto #

Per iniziare, scarica l’archivio .tar.gz corrispondente al progetto base desiderato ed estrai i suoi contenuti in una cartella.

Se hai in precedenza scaricato lo SPI della tua Cloudlet, copialo nella cartella lib/cloudlet all’interno della root del progetto e rinominalo in spi.jar. Se desideri collocare lo SPI in una cartella diversa, e/o dargli un nome differente, modifica le proprietà SPI_LOCATION e SPI_FILENAME all’interno del file gradle.properties.

Se importi il progetto base all’interno di un IDE che possiede il supporto a Gradle, come ad esempio Eclipse, noterai che il progetto radice viene identificato con il nome specificato dalla proprietà rootProject.name nel file settings.gradle. I progetti foglia avranno invece un nome nel formato <rootProjectName>-<projectName>.

Per includere dipendenze e librerie esterne per il progetto radice o per una foglia, apri il relativo build.gradle e modifica la sezione dependencies:

  • le dipendenze di compilazione, vale a dire le dipendenze necessarie per la compilazione del plugin ma di cui non è richiesta l’inclusione al suo interno, come lo SPI della Cloudlet, vanno indicate nella forma compileOnly "<group>:<name>:<version>";
  • le dipendenze che devono essere incluse nel bundle del plugin vanno indicate nella forma implementation "<group>:<name>:<version>";
  • le dipendenze di test, necessarie all’esecuzione dei test automatizzati, vanno indicate nella forma testCompileOnly "<group>:<name>:<version".

Se la dipendenza non è ospitata in un repository, ma è una libreria esterna disponibile solo in locale, il relativo jar andrà inserito nella cartella lib/ del progetto.

Dopo aver completato questi passaggi di configurazione, genera il wrapper Gradle: così facendo Gradle utilizzerà la versione compatibile con il progetto indipendentemente da quella effettivamente installata sulla macchina, evitando problemi di portabilità. Se usi un sistema Linux, apri la shell ed esegui il comando ./gradlew wrapper all’interno della root del progetto; se sei su Windows dovrai invece eseguire il comando gradlew wrapper.

Infine, se l’IDE che intendi usare per il progetto è Eclipse, esegui il comando ./gradlew eclipse nella root del progetto per far generare a Gradle i file necessari, dopodiché effettua l’import all’interno di Eclipse. Per far risolvere a Gradle le dipendenze specificate nei build script, fai clic destro sul progetto e seleziona Gradle > Refresh Gradle Project.

Procedura di build #

Una volta che hai fornito un’implementazione per ogni interfaccia dello SPI rappresentante un Handler, apri la root del progetto all’interno di una shell ed esegui il comando ./gradlew build. Così facendo Gradle compilerà il codice, eseguirà tutti i test automatici che vi sono stati definiti, genererà i blueprint OSGi, includerà le librerie indicate con implementation, ed infine produrrà un bundle OSGi nella cartella output.

Ai bundle generati da Gradle viene assegnato un nome secondo il formato <projectName>-<spiVersion>, dove <projectName> è il nome del progetto come dichiarato negli appositi file Gradle, e <spiVersion> è il valore della proprietà SPI_VERSION contenuta nel file gradle.properties. Se desideri cambiare il formato del nome assegnato ai bundle, modifica il valore di jar.archiveName nella sezione allprojects del build.gradle.

Il jar prodotto dall’operazione di build avrà questa struttura:

archiveName/
├── packages/
│   └──.../
├── OSGI-INF/
│   └── blueprint/
├── META-INF/
│   └── manifest.mf
└── lib/
  • la cartella OSGI-INF contiene i blueprint generati dall’Annotation Processor;
  • la cartella META-INF contiene il manifest del jar, comprendente l’elenco delle dipendenze di tipo implementation che sono state aggiunte al suo interno;
  • la cartella lib contiene i jar delle dipendenze implementation.

Progetti base #

Nelle sezioni che seguono, analizzeremo in maggiore dettaglio i tre progetti base offerti da Livebase: mono-bundle, multi-bundle e multi-bundle-jooq.

Mono-bundle #

Il progetto base mono-bundle è consigliato se è necessario realizzare un solo plugin da installare sulla Cloudlet; ha la seguente struttura:

root/
├── lib/
│   └── cloudlet/
├── src/
│   │   ├──main..
│   │   └──test..
│   └── build.gradle
├── build.gradle
├── settings.gradle
├── gradle.properties
└── pluginConfig.gradle

Multi-bundle #

Se hai bisogno di realizzare più plugin da eseguire indipendentemente sulla tua Cloudlet, è consigliato l’uso del progetto base multi-bundle. Il progetto ha la seguente struttura:

root/
├── lib/
│   └── cloudlet/
├── plugin1/
│   ├── src/
│   │   ├──main..
│   │   └──test..
│   └── build.gradle
├── plugin2/
│   ├── src/
│   │   ├──main..
│   │   └──test..
│   └── build.gradle
├── build.gradle
├── settings.gradle
├── gradle.properties
└── pluginConfig.gradle

Il progetto base comprende solo i due sotto-progetti plugin1 e plugin2, ma è possibile aggiungerne altri seguendo questa procedura:

  • crea un nuovo progetto Java adeguatamente strutturato all’interno del progetto radice. Se stai usando Eclipse, clicca col destro sul progetto radice e seleziona New > Other...; dal successivo menu seleziona Gradle > Gradle project e segui la procedura guidata;
  • apri il settings.gradle del progetto radice e aggiungi il nome del nuovo progetto alla lista include;
  • sempre se stai usando Eclipse, fai un refresh del progetto per aggiornare la sua struttura.

All’interno dell’IDE, ogni sotto-progetto sarà identificato da un nome nel formato <rootProjectName>-<projectName>.

Progetti plugin e utility #

Un multi-progetto ammette due tipi di sotto-progetto: plugin e utility.

Un progetto di tipo plugin si traduce in un bundle OSGi e può rappresentare tanto un Cloudlet plugin vero e proprio quanto un semplice bundle di classi che può essere referenziato da altri. Per dare la natura di plugin a un sotto-progetto, aggiungi le seguenti dipendenze al build.gradle:

def processorLib = 'com.fhoster.livebase:cloudlet-spi-annotation-processor:+'
dependencies {
  compileOnly spiLib
  compileOnly "org.slf4j:slf4j-api:${SLF4J_VERSION}"
  compileOnly "org.slf4j:slf4j-log4j12:${SLF4J_VERSION}"

  compileOnly processorLib
  annotationProcessor processorLib
}

I progetti utility contengono codice condiviso e librerie di supporto. Possono essere aggiunti come dipendenza di un progetto plugin in modo da essere inclusi nel suo bundle a tempo di build; per questo è necessario aggiungere la seguente riga alla sezione dependencies del relativo build.gradle:

implementation project(":${rootProject.name}-<YourUtilityProjectName>")

Riferimenti tra bundle #

Un bundle può referenziare i package di altri bundle: per fare questo, è necessario aggiungere i loro nomi agli array commonImports e imports, che sono situati nella sezione ext del file pluginConfig.gradle del progetto radice e nei file build.gradle di ogni sotto-progetto, rispettivamente.

I package indicati in commonImports saranno inclusi in tutti i sotto-progetti, mentre quelli in imports saranno inclusi solo nel relativo sotto-progetto.

Multi-bundle-jooq #

Se hai bisogno di realizzare dei plugin che effettuano accesso al database della Cloudlet, puoi utilizzare il progetto base multi-bundle-jooq. Questa è la sua struttura:

root/
├── lib/
│   └── cloudlet/
├── jooq-utils
│   ├── src/
│   │   ├──main..
│   │   └──test..
│   └── build.gradle
├── jooq
│   ├── src/
│   │   ├──main..
│   │   └──test..
│   └── build.gradle
├── plugin1
│   ├── src/
│   │   ├──main..
│   │   └──test..
│   └── build.gradle
├── build.gradle
├── settings.gradle
├── gradle.properties
└── pluginConfig.gradle

Il progetto comprende jOOQ come strumento per accedere al Cloudlet database, ed è già configurato per utilizzarlo.

jOOQ è un framework Java che, servendosi di un generatore di codice, è in grado di mappare un database in un insieme di classi che possono essere utilizzate per formulare delle query nello stesso linguaggio Java, grazie ad un apposito DSL (Domain Specific Language).

Tale progetto contiene un sotto-progetto di utilità con nome jooq che mette a disposizione i seguenti task Gradle:

  • generateDB: crea una replica locale del database della Cloudlet, utilizzando il file structure.sql incluso nel suo SPI;
  • generateJooqClasses (alias jooq): si connette al database della Cloudlet ed effettua un reverse engineering del suo schema per generare gli oggetti jOOQ;
  • cleanJooqClasses (alias cleanJooq): rimuove tutti gli oggetti jOOQ precedentemente generati;
  • dropDB: rimuove lo schema della replica locale del Cloudlet database.

Una volta che il container Docker è attivo, posiziona lo SPI della tua Cloudlet nella cartella lib/cloudlet ed esegui ./gradlew generateJooqClasses. jOOQ genererà i sorgenti necessari per accedere agli elementi del database e li inserirà nella cartella src/main/jooq.

Il progetto base comprende un ulteriore sotto-progetto di utilità denominato jooq-utils, che contiene una serie di funzionalità da utilizzare insieme ai sorgenti generati da jOOQ.

Riferimenti #