I Beans possono essere usati come oggetti incorporati o come componenti Microsoft ActiveX entro applicazioni come Microsoft Office, Internet Explorer, e Visual Basic usando il ponte JavaBeans-ActiveX. Questo articolo affronterà la costruzione di un semplice JavaBean

Introduzione.

Si vuole dare una panoramica su cosa sia un JavaBean e quale possa essere la sua utilità. L'articolo si compone dei seguenti argomenti:

1. Costruzione di un JavaBean 2. Aggiunta proprietà ed eventi al JavaBean. 3. Generazione del file jar contenente i files relativi al JavaBean 4. Test del JavaBean mediante l'ambiente di sviluppo scritto in java "BeanBox"

Costruzione di un JavaBean.

Per la costruzione del JavaBean si parte dalla semplice Applet "ImmBottone" (Il sorgente è qui) scritta con il JDK 1.0.2. L'Applet visualizza un bottone (MioBottone.class) con accanto 2 immagini, una associata all'evento MouseDown e una associata all'evento MouseUp. Cliccando sul bottone si vedono alternativamente le due immagini.

Ecco l'Applet in esecuzione.

Il codice che interessa è quello relativo al bottone MioBottone:

class MioBottone extends Button{

     Image imm;

     Image imm1;

     int Immagine = 1;

     String s;

     int x,y;

     public boolean mouseDown(Event evt, int x, int y){

          Immagine = 2;

          repaint(); 

          return true;

     }

     public boolean mouseUp(Event evt, int x, int y){

          Immagine = 1;

          repaint(); 

          return true;

     }

     public void update(Graphics g){ 

          paint(g); 

     }

     public void paint(Graphics g){ 

          if (Immagine == 1){ 

               g.drawImage(imm,x,y,this); 

               enable(); 

          } 

          else{

               g.drawImage(imm1,x,y,this); 

          } 

     }

     MioBottone(String s,int x,int y,Image imm, Image imm1){

          super(s); 

          this.s = s;

          this.imm = imm;

          this.imm1 = imm1;

          this.x = x;

          this.y = y;

          disable(); 

     }

}

Per la costruzione del JavaBean useremo le seguenti API:

Il pacchetto JDK 1.1.1. per la realizzazione e compilazione del programma.

Il pacchetto BDK 1.0. per la parte relativa alle specifiche del JavaBean e il test dello stesso.

La prima cosa da fare è rendere l'oggetto serializzabile, cosa che si ottiene implementando l'interfaccia bean.io.serializable, e pubblico. Naturalmente occorerà importare anche il package relativo. Si farà anche in modo che il JavaBean faccia parte di un package. Avremo quindi:

package dany.Bottoni; 

import bean.io.serializable;

public MioBottone extends Button implements serializable

Per semplicità utilizziamo un costruttore senza parametri "public MioBottone()" e impostiamo i parametri all'interno del codice.

Questo comporta:

L'impostazione diretta dei parametri s (label), x e y (coordinate iniziali della scritta).

Il caricamento diretto delle immagini imma.gif e imma1.gif che deve essere spostato dall'applet al javabean. A tale proposito dovremo usare la classe Toolkit e quindi importare altre classi di altri package :

import java.net.URL;

import java.awt.image.\*;

L'inserimento nel costruttore MioBottone anche dell'istruzione per abilitare gli eventi MouseDown e MouseUp nel JavaBean (necessaria nel JDK 1.1.,non era necessaria nel JDK 1.0.2.):

enableEvents(AWTEvent.MOUSEEVENTMASK);

Il costruttore diventa quindi:

public MioBottone() {

     super(" Cliccare qui'"); 

     enableEvents(AWTEvent.MOUSE_EVENT_MASK); 

     setFont(new Font("TimesRoman",Font.BOLD, 36)); 

     this.s = s;

     this.x = 5;

     this.y = 5;

     setEnabled(false); 

     Image imm = null; 

     Image imm1 = null;

     try {

          URL url = getClass().getResource("imma.gif");

          Toolkit tk = Toolkit.getDefaultToolkit();

          imm = tk.createImage((ImageProducer) url.getContent());

          java.net.URL url1 = getClass().getResource("imma1.gif");

          imm1 = tk.createImage((ImageProducer) url1.getContent());

     }

     catch (Exception ex){

          System.err.println("Errore di caricamento immagini"); 

     } 

     this.imm = imm;

     this.imm1 = imm1; 

}

Poiché la gestione degli eventi è cambiata rispetto al JDK 1.0.2. (vedere articolo di Massimo Carli relativo al JDK 1.1. su [](../../02/index.htm)), useremo al posto dei metodi MouseDown e MouseUp il metodo processEvent(AWTEvent evt) . Il codice relativo è il seguente:

protected void processEvent(AWTEvent evt) {

     switch (evt.getID()) {

     case Event.MOUSE_DOWN:

          Immagine = 2;

          repaint(); 

          super.processEvent(evt); 

          return; 

     case Event.MOUSE_UP:

          Immagine = 1;

          repaint(); 

          super.processEvent(evt); 

          return; 

     }

     super.processEvent(evt);

}

A questo punto dobbiamo inserire anche le seguenti proprietà :

1. background. Colore sfondo del bottone. 2. foreground. Colore dei caratteri del bottone 3. font. Tipo carattere. 4. label. Etichetta del bottone. 5. Posx. Posizione x nel bottone dell'immagine. 6. Posy. Posizione y nel bottone dell'immagine.

Faremo in modo anche che sia possibile cambiare queste proprietà

Secondo le specifiche per la costruzione di un JavaBean, nel caso che si decida di avere la possibilità di cambiare una proprietà, si devono implementare due metodi, uno per la lettura del valore della proprietà e uno per l'impostazione del nuovo valore. Il nome dei due metodi deve essere del tipo getNomeproprietà e setNomeproprietà.

Ad esempio

public String getValore(){

        return valore;

}

e

public void setValore(String nuovovalore) {

     int vecchiax = x;

     x = nuovax;

         ....

         .... 

         ....

     changes.firePropertyChange("valore", vecchiovalore, nuovovalore);

}

Dove changes è un'istanza della classe PropertyChangeSupport che è la classe usata per la gestione del cambiamento proprietà, e firePropertyChange è il metodo usato per cambiare il valore della classe. Rimangono da definire solo i metodi relativi a Posx e Posy, visto che per le prime quattro classi sono già previsti i metodi di set/get.

Avremo quindi:

// Ottiene il valore della proprietà Posx

public int getPosx(){

     return x;

}

// Ottiene il valore della proprietà Posy

public int getPosy(){

     return y;

}

// Imposta il valore della proprietà Posx

public void setPosx(int nuovax){

     int vecchiax = x;

     x = nuovax;

     changes.firePropertyChange("Posx", new Integer(vecchiax), new Integer(nuovax));

}

// Imposta il valore della proprietà Posy

public void setPosy(int nuovay){

     int vecchiay= y;

     y = nuovay;

     changes.firePropertyChange("Posy", new Integer(vecchiay), new Integer(nuovay));

}

Come ultima cosa diremo che, dovendo gestire i cambiamenti delle proprietà, abbiamo bisogno di due metodi: lo specificato metodo propertyChange dell'interfaccia PropertyChangeListener sarà chiamato ogni volta che il valore di una proprietà caricata (bound) è cambiato. Quindi abbiamo bisogno di un metodo per segnalare il cambiamento aggiungendolo nella lista apposita degli ascoltatori cambiamenti di proprietà, e di un metodo per rimuoverlo da tale lista.

public void addPropertyChangeListener(PropertyChangeListener l) {

     changes.addPropertyChangeListener(l); 

}

public void removePropertyChangeListener(PropertyChangeListener l) {

     changes.removePropertyChangeListener(l); 

}

Il codice sorgente totale risulta quindi:

package dany.Bottoni; 

import java.awt.*;

import java.net.URL;

import java.awt.image.*;

import java.util.*;

import java.io.Serializable;

import java.beans.*;

import java.awt.event.*;

public class MioBottone extends Button implements Serializable {

     private Image imm;

     private Image imm1;

     private int Immagine = 1;

     private String s="";

     private int x,y;

     private PropertyChangeSupport changes = new PropertyChangeSupport(this); 

     public void update(Graphics g) {

          paint(g); 

     } 

     public void paint(Graphics g) {

          if (Immagine == 1)

          { 

               g.drawImage(imm,x,y,this); 

               setEnabled(true); 

          } 

          else {

               g.drawImage(imm1,x,y,this); 

          } 

     } 

     public MioBottone() {

          super(" Cliccare qui'");

          enableEvents(AWTEvent.MOUSE_EVENT_MASK); 

          setFont(new Font("TimesRoman",Font.BOLD, 36)); 

          this.s = s;

          this.x = 5;

          this.y = 5;

          setEnabled(false); 

          Image imm = null; 

          Image imm1 = null;

          try {

               URL url = getClass().getResource("imma.gif");

               Toolkit tk = Toolkit.getDefaultToolkit();

               imm = tk.createImage((ImageProducer) url.getContent());

               java.net.URL url1 = getClass().getResource("imma1.gif");

               imm1 = tk.createImage((ImageProducer) url1.getContent());

          } catch (Exception ex) {

               System.err.println("Errore di caricamento immagini"); 

          } 

          this.imm = imm;

          this.imm1 = imm1; 

     } 

     public void addPropertyChangeListener(PropertyChangeListener l) {

          changes.addPropertyChangeListener(l); 

     } 

     public void removePropertyChangeListener(PropertyChangeListener l) { 

          changes.removePropertyChangeListener(l); 

     } 

     protected void processEvent(AWTEvent evt) {

          switch (evt.getID()) {

          case Event.MOUSE_DOWN:

               Immagine = 2;

               repaint(); 

               super.processEvent(evt); 

               return; 

          case Event.MOUSE_UP:

               Immagine = 1;

               repaint(); 

               super.processEvent(evt); 

               return; 

          } 

          super.processEvent(evt); 

     } 

     public int getPosx() {

          return x;

     } 

     public int getPosy() {

          return y;

     } 

     public void setPosx(int nuovax) {

          int vecchiax = x;

          x = nuovax;

          changes.firePropertyChange("Posx", new Integer(vecchiax), new Integer(nuovax));

     } 

     public void setPosy(int nuovay) {

          int vecchiay= y;

          y = nuovay;

          changes.firePropertyChange("Posy", new Integer(vecchiay), new Integer(nuovay));

     } 

}

Aggiunta proprietà ed eventi al JavaBean.

Ora ci occupiamo di rendere disponibili un minimo di informazioni su questo bean, in modo che un qualsiasi ambiente di sviluppo possa ricavare le caratteristiche principali interrogando appositi metodi. Lo standard per la costruzione di un JavaBean dice che la classe che contiene questo tipo di informazioni deve chiamarsi \<nome javabean\>BeanInfo.class.

Quindi creeremo il file MioBottoneBeanInfo.java, implementazione della classe SimpleBeanInfo fornita dalle API del bdk: tale kit fornisce un insieme di metodi per la costruzione di un semplice JavaBean.

Inoltre, per aggiungere proprietà al bottone, dobbiamo ridefinire il metodo getPropertyDescriptors() che restituisce un vettore di PropertyDescriptor\[\] contenente le informazioni sulle proprietà.

package dany.Bottoni; 

import java.beans.*;

public class MioBottoneBeanInfo extends SimpleBeanInfo {

public PropertyDescriptor[] getPropertyDescriptors() {

     try {

// Definizione delle proprietà collegate al JavaBean MioBottone. 

          PropertyDescriptor background =

               new PropertyDescriptor("background", MioBottone.class); 

          PropertyDescriptor foreground =

               new PropertyDescriptor("foreground", MioBottone.class); 

          PropertyDescriptor font =

               new PropertyDescriptor("font", MioBottone.class);

          PropertyDescriptor label =

               new PropertyDescriptor("label", MioBottone.class); 

          PropertyDescriptor Posx =

               new PropertyDescriptor("Posx", MioBottone.class);

          PropertyDescriptor Posy =

               new PropertyDescriptor("Posy", MioBottone.class); 

// Impostazione delle proprietà "Bound".

          background.setBound(true); 

          foreground.setBound(true); 

          font.setBound(true); 

          label.setBound(true); 

          Posx.setBound(true); 

          Posy.setBound(true); 

// Ritorno delle proprietà

          PropertyDescriptor rv[] = {background, foreground, font, label, Posx, Posy};

          return rv;

     } catch (IntrospectionException e) {

          throw new Error(e.toString());

     } 

}

Ora per aggiungere eventi al bottone ridefiniamo il metodo getEventSetDescriptors() che restituisce un vettore di EventSetDescriptor\[\] contenente le informazioni sugli eventi. Gli eventi che intendiamo gestire dall'esterno sono actionPerformed (evento che intercetta un'azione) e propertyChange (evento che intercetta il cambiamento di un'entità).

Avremo quindi :

public EventSetDescriptor[] getEventSetDescriptors() {

     try {

// Definizione degli eventi associati al JavaBean MioBottone. 

          EventSetDescriptor push = 

               new EventSetDescriptor(MioBottone.class, 

"actionPerformed",java.awt.event.ActionListener.class,"actionPerformed"); 

          EventSetDescriptor changed = 

          new 

EventSetDescriptor(MioBottone.class,"propertyChange",java.beans.PropertyChangeListener.class,"propertyChange"); 

// Etichette della proprietà. Servono ad un eventuale tool di sviluppo per poterle 

// presentare all'utente

          push.setDisplayName("button push");

          changed.setDisplayName("bound property change"); 

// Ritorno degli eventi

          EventSetDescriptor[] rv = { push, changed};

          return rv;

     } catch (IntrospectionException e) {

     throw new Error(e.toString());

     } 

}

Per finire dotiamo il JavaBean di un'icona per la sua rappresentazione in un tool :

public
java.awt.Image getIcon(int iconKind) {

    
java.awt.Image img = loadImage("imma.gif");

return
img;

}

Il parametro iconKind serve ad individuare numero di colori che il monitor può gestire. Può assumere i seguenti valori :

  • BeanInfo.ICONCOLOR16x16
  • BeanInfo.ICONCOLOR32x32
  • BeanInfo.ICONMONO16x16
  • BeanInfo.ICONMONO32x32

Volendo si può associare un'icona diversa per ogni valore. \##Concludendo il programma risultante è

package dany.Bottoni; 

import java.beans.*;

public class MioBottoneBeanInfo extends SimpleBeanInfo {

     public PropertyDescriptor[] getPropertyDescriptors() {

          try {

               PropertyDescriptor background =

                    new PropertyDescriptor("background", MioBottone.class); 

               PropertyDescriptor foreground =

                    new PropertyDescriptor("foreground", MioBottone.class); 

               PropertyDescriptor font =

                    new PropertyDescriptor("font", MioBottone.class);

               PropertyDescriptor label =

                    new PropertyDescriptor("label", MioBottone.class); 

               PropertyDescriptor Posx =

                    new PropertyDescriptor("Posx", MioBottone.class);

               PropertyDescriptor Posy =

                    new PropertyDescriptor("Posy", MioBottone.class); 

               background.setBound(true); 

               foreground.setBound(true); 

               font.setBound(true); 

               label.setBound(false); 

               Posx.setBound(true); 

               Posy.setBound(true); 

               PropertyDescriptor rv[] = {background, foreground, font, label, Posx, Posy};

               return rv;

          } catch (IntrospectionException e) {

          throw new Error(e.toString());

          } 

     } 

     public EventSetDescriptor[] getEventSetDescriptors() {

          try {

               EventSetDescriptor push = 

                    new EventSetDescriptor(MioBottone.class, 

"actionPerformed",java.awt.event.ActionListener.class, 

"actionPerformed");

               EventSetDescriptor changed = 

new 

EventSetDescriptor(MioBottone.class,"propertyChange",java.beans.PropertyChangeListener.class,"propertyChange"); 

               push.setDisplayName("button push");

               changed.setDisplayName("bound property change");

               EventSetDescriptor[] rv = { push, changed};

               return rv;

          } catch (IntrospectionException e) {

          throw new Error(e.toString());

          } 

     } 

     public java.awt.Image getIcon(int iconKind) {

          java.awt.Image img = loadImage("imma.gif");

          return img;

     } 

}

Generazione del file jar contenente i files che riguardano il JavaBean

Dopo aver compilato le nostre 2 classi possiamo dire che il nostro JavaBean è composto dai seguenti files:

1. MioBottone.class - Che è il JavaBean vero e proprio. 2. MioBottoneBeanInfo.class - Che è la classe che contiene informazioni sul JavaBean. 3. imma.gif - GIF presente sul bottone quando questo è up. 4. imma1.gif - GIF presente sul bottone quando questo è down.

Dobbiamo ora costruire un unico file compresso che contiene questi file, questo ci permetterà di lavorare con un file invece che con quattro, con conseguente miglioramento dei tempi di scaricamento in quei casi in cui il javabean dovrà lavorare sotto Internet/Intranet. Per fare ciò dobbiamo usare il comando jar (java archive). Prima di questo però dobbiamo creare una sorta di file indice (chiamato manifest) che contiene l'elenco dei files che faranno parte del jar.

Nel file manifest.mf scriveremo :

Name: dany/Bottoni/MioBottone.class 

Java-Bean: True

Name: dany/Bottoni/MioBottoneBeanInfo.class 

Name: dany/Bottoni/imma.gif

Name: dany/Bottoni/imma1.gif

A questo punto, supponendo di avere creato una directory c:\prova\dany\Bottoni dove sono presenti tutti i files riguardanti il jar, e supponendo inoltre che in c:\prova ci sia il file manifest, da questa seconda directory diamo il comando :

jar
cfm MioBottone.jar manifest.mf dany\Bottoni\MioBottone.class dany\Bottoni\MioBottone.class
dany\Bottoni\MioBottoneBeanInfo.class dany\Bottoni\imma.gif dany\Bottoni\imma1.gif

Verrà creato il file MioBottone.jar che rappresenta un componente utilizzabile in un ambiente di sviluppo che fa uso di JavaBean.

Test del JavaBean mediante l'ambiente di sviluppo scritto in java "BeanBox"

Passiamo ora a testare il JavaBean creato. Nel pacchetto BDK la Sun Microsystem fornisce un piccolo ambiente di sviluppo scritto in java per testare i JavaBean, chiamato Beanbox. Si presenta con tre frame :

1. Uno rappresenta la toolbar (barra degli strumenti) contenente i JavaBean forniti con il BDK come demo. Ogni JavaBean può essere preso e trascinato sulla maschera. 2. Uno rappresenta la maschera atta a contenere i JavaBean da testare la maschera è anche fornita di un menù per la selezione di determinate funzioni. 3. Uno rappresenta le proprietà del JavaBean da testare.

Dopo aver installato il pacchetto JDK 1.1.1. e il BDK 1.0., posizionarsi sulla directory c :\bdk\beanbox e lanciare il file di comandi run.bat. Ovviamente prima di lanciare run.bat assicurarsi che le impostazioni interne di PATH e CLASSPATH siano esatte.

Verranno visualizzati i 3 frame come mostrato nella figura 1.

Figura 1
Figura 1
Figura 2
Figura 2
Figura 3
Figura 3

A questo punto cliccare sul voce loadjar del menù file, cercare il file MioBottone.jar e caricarlo.

Il JavaBean verrà aggiunto con la sua icona nella toolbar come si vede in fondo alla lista nella figura 2.

Figura 4 - Trascinarlo sulla maschera , figura 3
Figura 4 - Trascinarlo sulla maschera , figura 3
Figura 5 - Il JavaBean entra subito in esecuzione ; infatti cliccando su di esso vedremo l'immagine cambiare. Come si può vedere dalla figura 4, il frame delle proprietà contiene esattamente le proprietà che abbiamo definito. Se cambiamo queste proprietà vedremo il loro effetto immediato sul JavaBean
Figura 5 - Il JavaBean entra subito in esecuzione ; infatti cliccando su di esso vedremo l'immagine cambiare. Come si può vedere dalla figura 4, il frame delle proprietà contiene esattamente le proprietà che abbiamo definito. Se cambiamo queste proprietà vedremo il loro effetto immediato sul JavaBean
Figura 6
Figura 6

Per esempio se cambiamo le coordinate dell'immagine Posx e Posy vedremo l'immagine spostarsi all'interno del bottone. Ora che abbiamo visto come funzionano gli eventi internamente all'oggetto (MouseDown e MouseUp), vediamo come funzionano gli eventi dall'esterno. Dobbiamo in pratica provare a usare l'evento che abbiamo incluso nel javabean e cioè ActionPerformed.

A tale scopo trascinare il JavaBean Juggler dalla ToolBar sulla maschera del BeanBox che siccome riguarda un'animazione entrerà subito in esecuzione mettendosi in movimento. Poi con il JavaBean MioBottone selezionato, cliccare sul menù Edit-\>Events-\>button push-\>ActionPerformed (Figura 5. ; notare che l'etichetta "button push" l'avevamo attribuita noi da programma).

Figura 7 - Apparirà una riga rossa che parte dal MioBottone. Cliccare sul Juggler mettendo così termine alla riga rossa (Figura 6)
Figura 7 - Apparirà una riga rossa che parte dal MioBottone. Cliccare sul Juggler mettendo così termine alla riga rossa (Figura 6)
Figura 8 - In questo modo abbiamo associato l'evento del click del MioBottone ad un'azione sul Juggler ; azione che psossiamo scegliere dalla lista che il programma ci mostra (Figura 7.)
Figura 8 - In questo modo abbiamo associato l'evento del click del MioBottone ad un'azione sul Juggler ; azione che psossiamo scegliere dalla lista che il programma ci mostra (Figura 7.)
Figura 9 - Scegliamo l'azione stopJuggling. A questo punto viene creata sotto la directory bdk\beanbox la directory tmp\sun\beanbox e viene generato e compilato il codice seguente contenuto in un file .java (il nome della classe viene generato automaticamente) :
Figura 9 - Scegliamo l'azione stopJuggling. A questo punto viene creata sotto la directory bdk\beanbox la directory tmp\sun\beanbox e viene generato e compilato il codice seguente contenuto in un file .java (il nome della classe viene generato automaticamente) :
// Automatically generated event hookup file.

package tmp.sun.beanbox;

public class ___Hookup_140a292f31 implements java.awt.event.ActionListener, 

java.io.Serializable {

     public void setTarget(sunw.demo.juggler.Juggler t) {

          target = t;

     } 

     public void actionPerformed(java.awt.event.ActionEvent arg0) {

          target.stopJuggling(arg0); 

     } 

     private sunw.demo.juggler.Juggler target;

}

Cliccando sul MioBottone, entrerà in esecuzione il codice compilato arrestando l'animazione.

Con questo concludiamo la dimostrazione del funzionamento di un JavaBean, sperando che l'esercizio sia stato utile a chiarire le idee a quanti volevano paragone questa tecnologia ad altre simili come ActiveX, VBX, OCX, ecc.