MokaByte 90- 9mbre 2004 
Framework JBoot
di
Yuru Fedorov

Il framework JBoot aiuta ad implementare velocemente il processo di bootstrap dell'applicazione Java. Definisce anche classi per gestire opzioni in modo più che mai facile, usando generics. L'implementazione del framework è basata sui pattern: Abstract Factory, Factory Method, Singleton, Template Method e Facade facendolo più flessibile e facile da usare

"Il programmatore vero deve essere pigro…
pigro per scrivere codice
ma non per pensare di cosa scrive!"

 

Introduzione
Sono stanco di scrivere il nuovo-stesso codice per ogni programma nuovo. Ormai siamo nell'epoca dei pattern e dei framework. Nell'articolo si descrive un framework flessibile che ti può salvare un paio di giorni quando decidi di cominciare a scrivere il tuo nuovo capolavoro.
Parliamo dei programmi del mondo reale. A prima vista sembra che fanno pure logica di business che è chiaro diversa per ogni applicazione. Ma non è proprio così. Ad esempio, parecchie devono lavorare con opzioni. Ancora più spaziose quelle che devono scrivere qualcosa in log. Direi che la lista non finisce qui. Ma ad ogni cosa il suo posto. Cominciamo…

 

Application è il entry point nuovo
Il framework ti dà la possibilità di dimenticare il metodo main. Definisce due nuovi entry point: run e quello ancora più veloce - rush. Guardiamo il codice del metodo run lui spiega la differenza meglio delle parole.

public void run() {
try {
rush();
} catch ( Throwable ex ) {
Log.log.warning( ex.toString() );
}
}

Come vedi, cambia poco, ma usando rush puoi non scrivere il blocco try-catch al più alto livello. Il metodo run è più classico, definito dall'interfaccia java.lang.Runnable.

 

La domanda eterna
Così, per creare l'applicazione, devi definire un figlio della classe Application e ridefinirci uno dei due entry point. Ma come il framework si crea l'oggetto della classe? Il framework non può sapere come tu chiamerai la classe. Chi e come si crea il primo oggetto?

Per risolvere questo problema il framework usa la linea di comando. Aspetta come primo parametro il nome del figlio di Application. Per la tua comodità c'è script file: si chiama jboot e dà la possibilità di lanciare i tuoi applicativi quasi come le altre applicazioni Java, la differenza è solo che devi chiamare jboot invece di JVM. Cioè scrivere qualcosa del genere:

jboot -cp demo.jar it.company.app.Demo

Così JBoot riceve il nome del figlio e crea la sua istanza usando i metodi della classe java.lang.Class forName e newInstance.


Figura 1 - Un esempio della configurazione dell'applicazione che usa JBoot

Factory
Subito dopo la creazione dell'oggetto di Applicazione si chiama il metodo createFactory che implementa il pattern Factory Method [1]. Il metodo crea l'oggetto Factory che implementa un altro pattern - Abstract Factory [1].

L'uso dei pattern dà la possibilità di costruire un'architettura molto flessibile e facile per fare il reengineering, una cosa importantissima riguarda che per il supporto si spende circa un terzo del costo totale del sistema.

La nostra Factory contiene la definizione dei metodi per produrre le prossime classi:

  • la collezione delle opzioni;
  • l'oggetto di java.util.ResourceBundary;
  • l'oggetto di java.util.logging.Logger.

Molto probabilmente per la tua applicazione servirà cambiare logica di lavoro oppure produrre altri tipi di oggetti. In questo caso puoi creare un figlio del classe Factory ed aggiungerci i metodi necessari.

Via
L'ultima cosa che fa il metodo main è chiamare il metodo start dell'applicazione. Cosa c'è dentro? Guardiamo UML.


Figura 2
- Il diagramma statico delle classi.

Come vedi, da parte delle classi Application e Factory, il framework lavora anche con altre. Vediamo quando.


Figura 3 - Il ciclo di vita dell'applicazione

All'interno del metodo Application.start si fa una serie di chiamate dei Template Method [1]: init, run, destroy. Il metodo init crea gli oggetti delle classi Options, ResourceBundle e Logger chiamando gli appropriati metodi di Factory.

 

Opzioni
Parecchie applicazioni hanno delle opzioni. Il framework fa l'accesso alle opzioni sincrono, fa il controllo dei tipi e salva automaticamente le opzioni fino al prossimo lancio dell'applicazione.


Per definire un'opzione nuova basta scrivere qualcosa del genere:

public final static Option < Date > LAST_UPDATE = new Option < Date > ( "LAST_UPDATE", null );

public final static Option < Boolean > CHECK_UPDATES = new Option < Boolean > ( "CHECK_UPDATES", true );

Usarla è ancora più semplice, grazie a generics [2] e autoboxing/unboxing [3].

if ( CHECK_UPDATES.get() ) {
final Date lastUpdate = LAST_UPDATE.get();
// ...
LAST_UPDATE.set( new Date() );
}

La classe Option opera come Facade [1] e il suo compito principale è fare il controllo di tipo usando generics. L'oggetto della classe non contiene il valore dell'opzione ma solo il suo nome che deve essere unico. Gestisce il valore nella classe Options che può essere pensata come una Map sincronizzata tra nomi e valori. Prima di chiudersi, l'applicazione, nel suo metodo destroy, salva l'oggetto Options in un file usando Serialization [4]. Al prossimo lancio, il metodo init dell'applicazione recupera l'oggetto Options dal file. Così il valore di default passato al costruttore d'oggetto Option si usa solo al primo lancio dell'applicazione. Poi il valore si recupera dal file che si trova nella home directory dell'utente.


Figura 4 - La classe Option opera come Facade.

Internazionalizzazione
E' ovvia l'importanza di seguire le regole d'internazionalizzazione fin dalla fase iniziale dello sviluppo dell'applicazione che potrebbe essere fruita in diverse lingue. Ma se l'applicazione supporta una lingua sola, come la maggior parte, puoi anche avere vantaggi seguendo le regole d'internazionalizzazione. Il tuo codice si rende più pulito delle stringhe cablate e diventa possibile riusarle, sia nella stessa applicazione che in altre.
Le risorse testuali si usano intensamente perciò anche la più piccola comodità aggiuntiva fa in modo che il processo di scrivere il codice sia più facile. Usando pure Java API per ritirare una riga testuale dal ResourceBundle dobbiamo scrivere qualcosa di questo tipo:

String text = resouceBundle.getString( "text" );

Il framework definisce una classe-involucro che fa lo stesso scrivendo:

String text = Res.get( "text" );

Questa soluzione è un po' più breve ma non è perfetta neanche. Sviluppando il framework ho seguito lo scopo di farlo più leggero possibile. Ma se ti interessa migliorare ulteriormente la situazione leggi il mio articolo "Come rendere l'uso delle risorsi testuali in Java facile e sicuro" [6].

 

Log
Una cosa che è presente nella maggior parte delle applicazioni. Facendo il framework più piccolo possibile ho scelto java.util.logging.Logger introdotto in JDK 1.4. Per aggiungere un messaggio d'informazione nel log basta scrivere:

Log.log.info( "L'avvio in corso..." );

Ma se devi fare più chiamate c'è senso ad usare static import [5] introdotto in JDK 5.0.

import static it.esistema.jboot.Log.log;

//...

log.info( "L'avvio in corso..." );
log.info( "Il carico di dati..." );

 

Ciao mondo!
Con il framework va la classica applicazione "HelloWorld". Il suo codice è tutto qui:

import it.esistema.jboot.*;

public class Demo extends Application {
  protected void rush() throws Exception {
   Log.log.info( Res.get( "txt.hello_world" ) );
  }
}

Come vedi è rimasto abbastanza corto! Ma ora puoi subito salutare il mondo in italiano.

Conclusione
Java API ti dà la massima flessibilità per l'implementare il processo di bootstrap. Il punto è che devi implementare il processo per ogni applicativo nuovo quando cominci a scrivere il codice… e sentire guardandolo "Déjà vu". JBoot ti dà la possibilità di cominciare subito a scrivere la logica di business, creando per te gli oggetti delle classi più comuni: Factory, Options, ResourceBundle, Logger. Puoi sempre adattare il processo alla sua necessità grazie all'architettura flessibile basata sui pattern riconosciuti. Prova e regalati un po' di tempo per bere il caffè!

 

Sorgenti
Il progetto JBoot si distribuisce come un progetto con sorgenti aperte (open source). Puoi scaricarlo gratuitamente dall'indirizzo http://esistema.it/pubblicazioni/jboot/jboot-src.zip .

 

Bibliografia
[1] Stephen Stelting; Olav Maassen - Applied Java Patterns, Prentice Hall PTR, 2002, ISBN 0130935387
[2] Sun Microsystems, Inc. - Generics, Java JDK 5.0 Guide, 2004
[3] Sun Microsystems, Inc. - Autoboxing/Unboxing, Java JDK 5.0 Guide, 2004
[4] Sun Microsystems, Inc. - Object Serialization, Java JDK 5.0 Guide, 2004
[5] Sun Microsystems, Inc. - Static Import, Java JDK 5.0 Guide, 2004
[6] Yury Fedorov - Come rendere l'uso delle risorsi testuali in Java facile e sicuro, MokaByte, settembre 2004

Yury Fedorov laureato in Tecnologie Informatiche, lavora da più di 6 anni nel settore IT. Dal 1999 si occupa di Java ed in particolare dello sviluppo di applicazioni web J2EE. Dopo diverse esperienze di disegno e sviluppo ora si occupa in particolare di aspetti architetturali per progetti rivolti al mercato e-business. Ha numerosi certificati di Brainbench e in particolare Master Java, Internet Professional Web Developer Client-side e Internet Professional Web Developer Server-side.


MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it