MokaByte Numero 10 - Luglio 1997
Foto
 
100% Pure Java
 
di
Daniela Ruggeri
Resoconto dalla conferenza organizzata a da Sun Italia  il mese scorso

 



La Sun Educational Services ha organizzato un seminario con tema 100% Pure Java tm Seminar che si è tenuto lunedi' 9 giugno a Milano e martedi' 10 giugno a Roma presso i suoi centri di formazione. In questo articolo parleremo degli argomenti che sono stati trattati.


 
 

Introduzione

Si è trattato di un incontro riservato a pochi programmatori che abbiano avuto gia' esperienza con il linguaggio Java e desiderino approfondire alcuni argomenti.
Lo scopo principale del corso, tenuto completamente in inglese, e' stato quello di illustrare come sviluppare soluzioni assolutamente compatibili con lo standard Java e certificabili 100% Pure Java, grazie ad Abstract Window Toolkit (AWT), Java Database Connectivity (JDBC) e JavaBeans.
Siccome gli argomenti presentati in questo articolo sono stati già trattati da Mokabyte, ogni capitolo tratterà brevemente l'argomento e sarà preceduto dal riferimento al numero di Mokabyte (con autore e titolo) dove trovare una maggiore trattazione dello stesso.
Si vuole quindi presentare un articolo che a partire dagli argomenti del seminario rappresenti una sorta di dizionario per quanti vogliano avere una visione sintetica del JDK 1.1., per poi dar loro la possibilità di approfondire ciò che interessa andando a leggere i riferimenti opportuni agli articoli su Mokabyte.
 

100% pure java

Argomenti trattati su MokaByte:

In questa sezione si è parlato dei benefici e vantaggi nell'utilizzo della tecnologia Java nello sviluppo di applicazioni. Sotto l'ormai famosa frase "Write once, Run Anywhere"Ô, che coinvolge sia Java che i JavaBeans, si cela l'indicazione ad ottenere applicazioni più economiche, perché permettendo di scrivere il codice una sola volta e di farlo girare ovunque, consentono di risparmiare tempo e denaro nelle fasi di manutenzione e test.
Per raggiungere tale fine la Sun Microsystem ha creato la 100% Pure Java Initiative nella quale fornisce un comune insieme di APIs che garantiscono la compatibilità delle applicazioni java nel passaggio da una piattaforma ad un'altra, e offrono servizi educativi,assistenza tecnica, test e certificazione, oltre che una serie di programmi ad uso degli sviluppatori Java.
Tutti i prodotti che superano i tests sono certificati e possono usare l'ormai famoso logo "100% Pure Java" sui loro pacchetti sofware e i loro materiali di marketing. Questo facilita il compito all'utente finale di accertarsi sulla piena compatibilità delle applicazioni java a girare su ogni piattaforma.
Altra iniziativa della Sun e' stata quella di stilare una serie di regole da seguire, oltre che una serie di "insidie" nascoste nell'uso di particolari funzioni java, raccolte in un documento nominato 100% Pure Java Cookbook.
Seguendo tali regole e evitando le insidie lo sviluppatore dovrebbe essere in grado di realizzare un'applicazione realmente portabile che a questo punto potrebbe essere dotata di certificazione.

Abstract Window Toolkit

Argomenti trattati su MokaByte:

Eventi

In questa sezione sono state affrontate le differenze tra la vecchia gestione degli eventi riguardante il package AWT 1.0 e la nuova (Delegation Event Model) riguardante il package AWT 1.1.
Nella vecchia gestione esiste solo un evento che viene intercettato ed elaborato da appositi metodi associati all'oggetto coinvolto (target).
I metodi riguardanti gli eventi in AWT 1.0 sono deliverEvent(), locate(), translate(), postEvent() e handleEvent() che gestiscono e spediscono l'evento all'oggetto.
Se l'oggetto gestisce l'evento il metodo restituisce true e tutto finisce, altrimenti il metodo restituisce false e l'evento viene spedito al contenitore dell'oggetto; questa fase si ripete fino a quando il metodo opportuno restituisce true o fino a quando non esistono più contenitori.
Con la nuova gestione degli eventi in AWT 1.1. esistono delle classi che hanno associata una lista di ascoltatori (ne esiste una specifica per ogni tipo di evento per esempio TextListener), ed esistono delle classi che si iscrivono a quella lista. In questo modo ogni evento trattato dalla lista che viene intercettato dalla prima classe, viene "sentito" da tutte le classi registrate nella lista. Un'altra cosa da sapere è l'esistenza di maschere per la abilitazione o meno dei gruppi di eventi (es. AWTEvent.MOUSE_EVENT_MASK), perché se si vuole che un evento venga intercettato dagli ascoltatori, bisogna anche abilitarlo.
C'è quindi una più completa libertà nella gestione degli eventi: immaginate per esempio di dover gestire una serie di Frame in cascata (è questa una situazione abbastanza comune nelle procedure) allora mentre è facile il passaggio da una finestra ad un'altra chiudendo la precedente mediante hide() e creando la seguente, non è più possibile tornare indietro in quanto non si "vede" la finestra precedente. Infatti l'unico modo per tornare indietro è costringere la seconda finestra a vedere la prima creando un costruttore apposito che preveda come parametro un Frame. Basterà quindi in fase di creazione della seconda finestra, richiamare il costruttore apposito (Es. newSecondaFinestra(this)). A questo punto quando il secondo Frame intercetta l'evento apposito (per esempio il Clic su un bottone "Annulla") può fare eseguire una routine appartenente al primo Frame.
Con la nuova gestione degli eventi invece basta che il primo Frame si registri nella lista di ascoltatori di un determinato tipo del secondo Frame. Dopo di che ogni evento del tipo prefissato intercettato dal secondo Frame viene anche "sentito" dal primo che puo' lui stesso eseguire il codice desiderato.
 

Componenti

Nella vecchia gestione per ogni componente esisteva un'interfaccia peer scritta con codice nativo che gestiva la sua visualizzazione e le sue funzionalità. Erano componenti cosiddetti "pesanti" (heavyweight components) e la loro elaborazione era molto lenta.
Nella nuova gestione invece non abbiamo più peer abbiamo così componenti "leggeri" (lightweight components), vengono supportati i componenti trasparenti e i componenti non rettangolari.
Per creare un componente leggero bisogna realizzare 6 passi:

  1. Definire il costruttore
  2. Gestire gli eventi interni (ascoltatori, per esempio mouse click = selezione)
  3. Gestire la grandezza (si utilizza getPreferredSize())
  4. Gestire la fase di disegno (si utilizza paint())
  5. In caso di componenti non rettangolari bisogna ridefinire il metodo contains().
  6. Gestire le liste di eventi esterni (per esempio spedire l'evento di tipo action quando intercettato).
Formato dei caratteri.

Tramite il file font.properties si possono aggiungere nuovi tipi di caratteri ai programmi Java descrivendone i tipi e le famiglie. Il file font.properties file dipendente dalla piattaforma .
Correntemente nel nuovo JDK vengono gestite di default le seguenti famiglie di caratteri:

JavaBeans

Argomenti trattati su MokaByte:

Generalità

Si può definire un javabeans come "un componente software riutilizzabile che può essere manipolato in un ambiente visuale generatore di codice".
Nel JDK 1.1. sono gestiti dal package java.beans. E' compunque messo a disposizione dello sviluppatore un pacchetto BDK (Beans Developement Tools), dove si trovano oltre che le API, anche un piccolo tools di sviluppo (BeanBox) che permette di testare i JavaBeans.
A sua volta un componente è un oggetto intelligente disegnato ed implementato in modo che altri oggetti possono :

  1. Determinare che metodi, proprietà ed eventi esso supporti.
  2. Cambiare le sue proprietà
  3. Connettere eventi tra più componenti
  4. Salvare o ripristinare il suo stato in un file o data stream.
Il vantaggio nell'uso dei JavaBeans sta nel loro facile utilizzo in ambienti di sviluppo GUI, nella completa riusabilità dell'oggetto e nella loro similitudine con le applet oltre che nella loro maggiore efficienza. Gli sviluppatori possono crearli, usarli in ambienti GUI o scrivere ambienti di sviluppo che li manipoli.
In base alla tipologia dei beans possiamo avere
  1. Beans leggeri (Lightweight Beans). Tutti i componenti AWT.
  2. Beans di medio peso (Middleweight Beans). Maschere, applet e applicazioni, parser java o HTML.
  3. Beans pesanti (Heavyweight Beans). Fogli elettonici, word processor.

  4.  

     
     
     
     

Eventi

I JavaBeans usano la nuova gestione degli eventi del JDK 1.1. (Delegation Event Model). E' quindi un modello basato sugli ascoltatori di eventi.
Gli eventi che riguardano i javabeans sono oltre ai normali eventi gestiti nel JDK 1.1., anche eventi di cambiamento di proprietà in un bean e ogni generale notifica da un oggetto ad un altro. Ogni evento (java.util.EventObject che tratta ogni tipo di evento e viene sottoclassato in sottinsiemi che trattano un derminato genere di eventi, per es. gli eventi Action) si propaga dalla sorgente fino agli ascoltatori (java.util.EventListener che tratta ogni tipo di evento ascoltato e viene sottoclassato in sottinsiemi che trattano un derminato genere di evento ascoltato, per es. gli eventi Action).
Esempio: Button (sorgente) àActionEvent (evento) à ActionListener (lista di ascoltatori)
Quindi l'oggetto origine dell'evento (target) deve implementare l'appropriata interfaccia di ascoltatori (es. ActionListener) e registrare se stesso come ascoltatore.
 

Proprietà

Le proprietà, sono attributi pubblici del bean responsabili della sua apparenza o comportamento.
Esempio : color, font, name, ecc.
Le proprietà sono usualmente persistenti e vengono trattate dai metodi che hanno questi modelli:
void setXXX(TYPE VALUE) ; per impostare il valore della proprietà

TYPE getXXX() ; per ottenere il valore della proprietà

 boolean isXXX() ; per interrogare una proprietà di tipo booleano.

Dove XXX è la proprietà (per esempio Name) e TYPE è il tipo della proprietà.
Fra tutte le proprietà esistono quelle bound che sono quelle utilizzate quando un bean vuole notificare ad un altro bean il cambiamento della proprietà. Per esempio 3 bottoni in una finestra condifidono la stessa proprietà font.
A queste proprietà è associata l'apposita lista di ascoltatori PropertyChangeListener che gestisce l'evento del cambiamento delle proprietà.
Diamo anche un accenno alle proprietà constrained cioè con condizione, che consistono in quelle proprietà che possono rifiutare eventuali modifiche.
Vengono gestite mediante queste regole :
 

  1. L'eccezione procurata in caso di fallimento è PropertyVetoException
  2. I metodi di lettura e di impostazione proprietà hanno questa sintassi

  3.  

     

    TYPE getXXX() ;
    void setXXX(TYPE value) throws PropertyVetoException
     

  4. Per quanto riguarda i cambiamenti utilizzano l'interfaccia lista ascoltatori VetoableChangeListener


Introspezione
 

Permette di ottenere informazioni circa i metodi, proprietà ed eventi trattati dal bean. Ci sono 2 livelli per ottenere informazioni :

1. Basso livello. E' quello che viene chiamato Riflessione che non è altro che un'estensione dell'introspezione. Viene gestito dal package java.lang.reflect e permette di ottenere informazioni circa i campi e i metodi delle classi. Vengono utilizzati per i JavaBeans e la serializzazione per ottenere informazioni sull'oggetto.
Le classi del package sono :
  • - java.lang.Class
  • - java.lang.reflect.Method
  • - java.lang.reflect.Field
  • - java.lang.reflect.Constructor
  • - java.lang.reflect.Array
  • - java.lang.reflect.Modifier
  •  Queste classi (tranne la prima) implementano l'interfaccia java.lang.reflect.Member che è composta dei seguenti metodi : 2. Alto livello. E' la riflessione specializzata sui beans. Viene utilizzata per creare la classe Java.beans.BeanInfo che serve a descrivere il bean in termini di proprietà, metodi ed eventi. Viene gestita dalla classe java.beans.Introspector.
    Quanto lo sviluppatore crea un bean, può creare una classe per personalizzare il bean estendendo la classe BeanInfo o la classe java.beans.SimpleBeanInfo messa a disposizione per facilitare il compito di personalizzazione, e secondo lo standard deve dargli un nome pari a: nomebeanBeanInfo (es. se nomebean = MioOggetto, allora il nome della classe sarà MioOggettoBeanInfo). Se nessuna classe di questo tipo viene creata la classe Introspector userà l'implementazione di default.
    Per ottenere informazioni dalla classe BeanInfo bisogna utilizzare il metodo getBeanInfo appartenente alla classe Introspector.
     Esempio :

     TextField tf = new TextField() ;
     BeanInfo bi = Introspector.getBeanInfo(tf.getClass) ;

    Persistenza

    Si intende per persistenza la possibilità di salvare e ripristinare le informazioni del Bean in un file usando le API Java Object Serialization.
    Il bean può usare la serializzazione per memorizzare un prototipo della sua istanza. A questo punto il prototipo può essere usato al momento della creazione dell'istanza del bean.
    La serializzazione può essere usata sia per la persistenza (scrittura di un file stream) che per la comunicazione tramite socket.
    Il default di per un file generato tramite la serializzazione e' .ser.
    Un classe per poter essere serializzata deve implementare l'interfaccia java.io.Serializable o l'interfaccia java.io.Externalizable (che estende l'interfaccia java.io.Serializable).
    La scrittura e la lettura in un file stream avvengono tramite i metodi writeObject della classe java.io.ObjectOutput e readObject della classe java.io.ObjectInput
    Tutti i campi del bean vengono memorizzati nel file stream tranne i campi dichiarati Transient. Dichiarando infatti il campo in questo modo si esplicita l'intenzione di voler mantenere il valore di questi campi alla fine dell'esecuzione della classe.
    A questo punto possiamo dire che un Bean può essere istanziato nei seguenti modi :
     

    1. Nella maniera classica :
      1.   MioBean b = new MioBean()
    2. Istanziando un prototipo serializzato memorizzato in un file .ser contenuto in un file .jar (file compresso contenenti le classi che compongono il bean oltre ad altre cose come immagini, suoni, ecc.) :
      1.  Beans.instantiate(null,"MioPackage.MioBean");
    1.  Per i Beans che hanno un prototipo bisogna usare quel prototipo :
      1.   Component c = (Component)Beans.instantiate(null,"java.awt.TextField");

     
    Risorse e File JAR

    I beans, come il restante codice java, spesso hanno bisogno di accedere a risorse che appartengono a file separati (grafici, immagini, suoni, file property, ecc.).
    Queste risorse vengono normalmente incluse in file .jar o in altri files (es. .zip) localizzati dalla variabile di ambiente CLASSPATH.
    Una delle risorse importanti sono i file property (es. font.properties contenente informazioni sui tipi di caratteri) che contengono delle liste di chiavi che rappresentano proprietà. Per ottenere il valore associato alla determinata chiave si utilizza il metodo getProperty.
    Per una questione di minimizzazione di spazio su disco e di tempo nel caso di trasferimento in rete del bean, si usa costruire un pacchetto compresso di tutti i files necessari al suo funzionamento. Questo pacchetto ha un estensione .jar (Java Archive) e può contenere  classi, oggetti serializzati .ser, file immagini, file suoni, e ogni altro tipo di risorse, tutti questi files possono riferirsi a più beans. Le classi possono anche essere presenti firmate, ossia associate ad un numero di identificazione.
    Per leggere e scrivere i file jar esiste il package java.util.zip.
    I file jar inoltre contengono un file testo di nome Manifest che è una sorta di indice del contenuto del .jar. Ad ogni classe corrispondente ad un bean avranno specificata la parola chiave Java-Bean : true.
     

    Java DataBase Connectivity

    Argomenti trattati su MokaByte:


    Dato che in questo numero di Mokabyte si parla già ampliamente di questo argomento, ci limiteremo a darne qualche spiegazione generale.
    JDBC è un'interfaccia basata sul linguaggio SQL per i database scritta in Java. Per la sua scrittura sono state adottate le specifiche standard ODBC.
    Esiste già nel JDK 1.1. ma ne può anche essere installata una versione che funziona con JDK 1.0.2.
    I suoi vantaggi consistono in una connessione "pure-java" a un database, permettendo di rimanere indipendente dalla piattaforma ("write once, run anywhere") e permettendo di funzionare con ogni database per il quale esiste il driver JDBC.
    Esistono vari modi di utilizzare JDBC :

    1. Oltre alle Api che gestiscono JDBC, esistono anche le Api che permettono di gestire il ponte JDBC-ODBC che permette di utilizzare i driver ODBC, permettendo di far girare un'applicazione java anche in assenza di driver JDBC. Questo metodo ha bisogno di codice nativo sulla client (per esempio la libreria JdbcOdbc.dll per piattaforma Microsoft Windows.). Per la connessione si utilizza il sottoprotocollo odbc, secondo la specifica jdbc :odbc :<nome fonte di dati>
    2. Mediante driver scritti in parte in codice nativo e in parte in java che convertono le chiamate JDBC nelle chiamate API native del database.
    3. Mediante driver di rete pure-java che converte le chiamate JDBC in un protocollo di rete (usando la connessione jdbc :<nome protocollo> :<path datatabase>) e un middleware di rete che converte nelle specifiche chiamate al database (per esempio dbANYWARE della Symantec)
    4. Protocolli nativi pure Java driver, che convertono le chiamate JDBC direttamente nel protocollo di rete del Database (connessione jdbc :<path datatabase>)

    5.  

       
       
       
       

     
     

    MokaByte rivista web su Java

    MokaByte ricerca nuovi collaboratori
    Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it