MokaByte Numero 21 - Luglio 1998
InfoBus
di
Daniela Ruggeri
Un'autostrada per i Beans 



In questo articolo analizziamo il pacchetto InfoBus che descrive la comunicazione tra classi appartenenti alla stessa JVM.



 

Introduzione
Architettura del flusso di dati tra i componenti
Tipi di componenti
Principali caratteristiche di InfoBus
Il protocollo InfoBus per lo scambio dei dati
Descrizione package javax.infobus
Descrizione esempio TimeSource-Clock



 

Introduzione.

Queste specifiche forniscono standards tramite i quali un grande numero di componenti Java possono scambiarsi dati (dai produttori dei dati ai consumatori). L'insieme di interfacce che realizzano questa operazione e che i componenti devono implementare prende il nome di InfoBus.

L'architettura InfoBus facilita la creazione di applicazioni costruite su Java Beans che si scambiano dati asincronamente. Questo può essere realizzato anche sia dalle applets presenti in una pagina HTML che da beans assemblati da un generatore di applicazioni java. InfoBus può anche essere usato da qualsiasi altra classe come per esempio le servlets.

Questa prima versione 1.1. InfoBus supporta il JDK 1.1. ma può essere usata con il JDK 1.2, anche se non sfrutta le nuove caratteristiche del JDK 1.2.
 
 

Architettura del flusso di dati tra i componenti.

InfoBus è stato progettato per componenti che lavorano nella stessa Java Virtual Machine (JVM).

In linea generale tutti i beans caricati da un singolo class loader possono vedere altri beans dello stesso loader e costruire metodi che realizzano chiamate dirette a quei beans.

I beans in genere usano l'introspezione per imparare o scoprire informazioni circa le classi peer dei beans al momento del run time. In tale caso un bean può dedurre un'API supportata dall'altro bean dall'analisi dell'insieme dei nomi dei metodi scoperti durante l'introspezione. Invece con le interfacce InfoBus nessuna deduzione è richiesta e le procedure possono essere chiamate direttamente perché esiste il mediatore InfoBus.

Le interfacce di InfoBus permettono al disegnatore delle applicazioni di creare flussi di dati tra i beans cooperanti. Al contrario del modello di risposta ad eventi, dove la semantica dell'interazione dipende dalla comprensione dello specifico evento collegato al bean e dalla chiamata dello specifico metodo supportato da quell'evento, le interfacce InfoBus hanno pochissimi eventi con un invariante insieme di metodi uguali per tutti i componenti. La semantica del flusso di dati è basata sull'interpretazione del contenuto dei dati che passa attraverso queste interfacce, e non dal nome o dai parametri degli eventi e neanche dal nome e dai parametri dei metodi richiamati.
 
 

Tipi di componenti
 

I Beans nelle applicazioni InfoBus possono essere di tre tipi: produttori (data producers), consumatori (data consumers) e controllori (data controllers). Un componente può essere sia produttore che consumatore. I flussi di dati visti come oggetti prendono il nome di elementi (data items). I controllori sono componenti specializzati che fungono da mediatori nell'appuntamento tra produttori e consumatori.
 
 

Principali caratteristiche di InfoBus

La struttura di un'applicazione InfoBus comporta di due principali caratteristiche:
 

Il protocollo InfoBus per lo scambio dei dati.

Passo 1. Partecipazione (Membership) — Stabilire la partecipazione ad un InfoBus dei componenti

Ogni componente Java può collegarsi ad un InfoBus. Questo è realizzato implementando l'interfaccia InfoBusMember, ottenendo un'istanza InfoBus, e unendosi (join) a tale istanza.
 

Passo 2. Ascoltare gli eventi riguardanti l'InfoBus

Una volta che l'oggetto è un elemento di un Infobus, esso riceverà notifiche del bus

Due interfacce ascoltatrici di eventi sono state create per supportare le tue tipologie di applicazioni InfoBus. Il consumatore riceve la notifica della disponibilità dei dati, mentre il produttore riceve la richiesta del dato.

Queste interfacce sono:

InfoBusDataConsumer

e

InfoBusDataProducer

Entrambe estensioni dell'interfaccia InfoBusEventListener

Inoltre esiste anche DataItemChangeListener che gestisce il cambiamento del dato, e visto che InfoBus è vista globalmente come una proprietà bound e soggetta a condizioni, vengono usate anche le liste ascoltatrici:

PropertyChangeListener

e

VetoableChangeListener
 

Passo 3. Appuntamento per il dato da trasmettere

Nel modello InfoBus, il produttore annuncia la disponibilità del nuovo dato appena il dato è pronto (per esempio dopo il completamento della lettura di un URL, il completamento di un calcolo ecc.)

I consumatori richiedono i dati al produttore al verificarsi di particolare condizioni (inizializzazione dell'applet, evento collegato al bottone, ecc.). L'appuntamento è stabilito tramite il nome del dato.

Quindi, tutti i produttori e consumatori devono fornire dei meccanismi nell'applicazione che possano specificare i nomi dei dati per l'appuntamento. Per esempio in un componente consistente in un foglio elettronico, l'utente può "dare un nome" agli intervalli nel foglio.

Questo nome è un naturale meccanismo per il riconoscimento dei dati che possono essere esportati dal foglio che assume il ruolo di produttore.
 

Passo 4. Navigazione dei dati strutturati

Differenti produttori spesso usano rappresentazioni dei dati che sono solo superficialmente simili.

Per esempio un foglio elettronico e un database ambedue lavorano con le tabelle, ma spesso memorizzano i dati in modo abbastanza differente.

In un foglio elettronico, la tabella dei dati potrebbe essere rappresentata come un output di un calcolo (come una matrice invertita), o come una matrice di formule, laddove in un database la stessa informazione potrebbe essere rappresentata come per esempio il risultato di una query join.

Un consumatore non ha bisogno di capire dettagliatamente la rappresentazione interna del dato preparato dal produttore.

Un componente che gestisce dati dovrebbe poter disegnare un grafico a partire da una tabella indipendentemente se questa è il risultato di un foglio elettronico o di un database.

In pratica questa condivisione di informazioni tra produttori e consumatori richiedono una comune codifica dei dati.

Sono quindi state disegnate una serie di interfacce per vari protocolli standard che sono usati per creare elementi di dati con comuni accessi.

In questo articolo non viene analizzato questo passo.
 

Passo 5. Ricerca della codifica per il valore del dato

Un elemento di dato può essere restituito come una String o come un oggetto Java.

Gli oggetti Java sono tipicamente classi che corrispondono ai vari tipi primitivi (per esempio Double che corrisponde al tipo primitivo double), oppure sono istanze di classi viste come collezioni di dati (array). L'obiettivo è la richiesta di specializzati e comprensibili formati dei dati da parte del consumatore.

Per questo vengono utilizzate l'interfaccia DataItem che forniscono informazioni sul dato e sui suoi DataFlavor, e l'interfaccia ImmediateAccess che fornisce informazione dirette su dati semplici trattando solo il formato String e Object.
 

Passo 6. Opzionale: La modifica del valore del dato

Un consumatore può cercare di cambiare il valore del dato.

Il produttore impone una politica su chi voglia cambiare il dato. Con il JDK 1.2, esso può anche gestire permessi per i vari consumatori.

La casse che gestisce tale operazione è DefaultPolicy che implementa l'interfaccia InfoBusPolicyHelper.

In questo articolo non viene analizzato questo passo.
 
 
 

Descrizione package javax.infobus

Interfacce
 
ArrayAccess DataItem  Questa interfaccia fornisce informazioni di identificazione e di descrizione del dato da trasmettere. 

I produttori implementano sempre questa interfaccia. 

DataItemChangeListener  Gestori di dati possono implementare opzionalmente DataItemChangeListener in modo da potersi registrare alla lista tramite i metodi contenuti nell'interfaccia DateItemChangeManager

Una classe che implementa DataItemChangeManager spedisce le notifiche del cambiamento del valore attraverso l'evento DataItemChangeEvents

 

DataItemChangeManager  Questa interfaccia permette di registrarsi e di rimuovere la registrazione dalla lista ascoltatrice DataItemChangeListener
DbAccess  Gestisce i dati provenienti da un data base
ImmediateAccess  Restituisce il dato semplice, non tratta quindi le collezioni di dati, e offre dei metodi per estrarre e per impostare il dato in formato String o Object.
InfoBusDataConsumer  Viene implementata dai consumatori, ed è la lista ascoltatrice che gestisce gli eventi di disponibilità e di revoca della disponibilità del dato, notificati dal produttore. 
InfoBusDataController  Personalizzazioni alle implementazioni di InfoBusDataController possono essere aggiunte per ottimizzare la distribuzione dell'evento InfoBusEvent gestito da InfoBusDataProducer

InfoBusDataConsumer. Viene utilizzata dalle classi che fungono da mediatori tra produttori e consumatori.

InfoBusDataProducer  Viene implementata dai produttori, ed è la lista ascoltatrice che gestisce l'evento di richiesta del dato, notificato dal consumatore. 
InfoBusEventListener  E' l'interfaccia comune di InfoBusDataConsumer e InfoBusDataProducer
InfoBusMember  E' necessario implementare questa interfaccia per poter gestire una proprietà con condizioni chiamata infoBus . Intorno a questa proprietà gira tutto il presente package.
InfoBusPolicyHelper  Interfaccia che pone un insieme di regole da adottare in caso di cambiamento del dato da parte dei consumatori.
InfoBusPropertyMap  Interfaccia temporanea adottata per fornire un meccanismo per l'uso dei componenti InfoBus 1.1 che desiderino fornire proprietà nell'evento DataItemChangeEvents. 

Fornisce il solo metodo get(Object key) che ritorna l'oggetto corrispondente allo specifico nome della proprietà key.

RowsetAccess  Metodi di supporto per la gestione delle righe di tabelle DB
ScrollableRowsetAccess  Metodi di supporto per la gestione delle righe di tabelle DB

Classi
 
 
DataItemAddedEvent  Evento che si verifica quando un elemento viene aggiunto ad una collezione di dati.
DataItemChangeEvent  Evento che si verifica quando avviene un cambiamento del dato.
DataItemChangeSupport  Classe di supporto per la gestione degli eventi che gestiscono il cambiamento dei dati.
DataItemDeletedEvent  Evento che si verifica quando un elemento viene cancellato da una collezione di dati.
DataItemRevokedEvent  Evento che viene notificato dal produttore quando il dato non è più disponibile.
DataItemValueChangedEvent  Evento che si verifica quando avviene un cambiamento nel valore del dato. E' una sottoclasse di DataItemChangeEvent
DefaultPolicy  Classe per la gestione della sicurezza in caso di cambiamento del dato da parte dei consumatori. 

Questa classe implementa l'interfaccia InfoBusPolicyHelper

InfoBus  Un oggetto InfoBus detiene una lista di InfoBusMember e abilita la comunicazione tra le classi che implementano gli InfoBusMember.
InfoBusEvent  Evento di base per la gestione di una comunicazione InfoBus. Viene gestito dalla lista ascoltatrice InfoBusEventListener

In genere questo evento non viene utilizzato, perché vengono utilizzate le sue sottoclassi specializzate (InfoBusItemAvailableEvent, InfoBusItemRevokedEvent, InfoBusItemRequestedEvent)

InfoBusItemAvailableEvent  Evento che notifica la disponibilità di un dato. Spedito dal produttore ad uso dei consumatori registrati alla lista ascoltatrice InfoBusEventListener.
InfoBusItemRequestedEvent  Evento che notifica la richiesta di un dato. Spedito dal consumatore ad uso dei produttori registrati alla lista ascoltatrice InfoBusEventListener.
InfoBusItemRevokedEvent  Evento che notifica la revoca della disponibilità di un dato. Spedito dal produttore ad uso dei consumatori registrati alla lista ascoltatrice InfoBusEventListener.
InfoBusMemberSupport  Questa classe implementa l'interfaccia InfoBusMember e serve a gestire le funzionalità del protocollo InfoBus protocol. Incapsula luna proprietà InfoBus e gli oggetti PropertyChangeSupport e VetoableChangeSupport dato che tale proprietà è bound e soggetta a condizione.
RowsetCursorMovedEvent  Descrive un cambiamento di valore in un elemento che può anche essere una collezione. 

Eccezioni
 
 
ColumnNotFoundException  Usata per la gestione dei DB, viene sollevata nel caso in cui la colonna non viene trovata.
DuplicateColumnException  Usata per la gestione dei DB, viene sollevata nel caso in cui si tenta di inserire una colonna già presente.
InfoBusMembershipException  Viene sollevata quando si tenta di fare una join su di un InfoBus ormai molto vecchio oppure quando non si ha il permesso di fare la join.
InvalidDataException  Viene sollevata da un DataItem quando si cerca di cambiarne il valore con un formato illegale. 
RowsetValidationException  Usata per la gestione dei DB, viene sollevata nel caso in cui la modifica di un valore fallisce per qualche ragione.
UnsupportedOperationException Può essere sollevata se il partecipante all'Infobus non supporta il metodo chiamato 

 

Descrizione esempio TimeSource-Clock

Analizziamo ora un esempio presente nel pacchetto scaricabile da Internet: la collaborazione tra un'applet che deposita il tempo in un Infobus ogni secondo, e un'altra applet che lo prende e lo utilizza.

In questo esempio si dimostra quindi la collaborazione tra un produttore, TimeSource.class che scrive un elemento rappresentante l'ora corrente (CurrentTime) in un InfoBus ogni secondo che passa. Il consumatore è l'applet Clock.class, che cerca l'ora corrente nell'InfoBus, si registra ad una lista che gestisce i cambiamenti del dato, e visualizza l'ora esatta, ogni volta che gli viene notificato il cambiamento di questa.

Ripeteremo i passi di cui abbiamo parlato sopra, mostrando e commentando il codice scritto.
 

Passo 1. Partecipazione— Stabilire la partecipazione ad un InfoBus dei componenti

Per stabilire la partecipazione ad un Infobus è necessario prima di tutto implementare l'interfaccia InfoBusMember,
 
 

Produttore TimeSource
 

public class TimeSource extends Applet implements InfoBusMember
Consumatore Clock

public class Clock extends Applet implements InfoBusMember

Dopo di che bisogna di far partecipare la classe TimeSource e Clock all'Infobus.

A tale scopo viene utilizzata la classe InfoBusMemberSupport che viene associata all'applet TimeSource o Clock e viene utilizzato il metodo joinInfoBus() dell'interfaccia InfoBusMemberSupport per unire l'interfaccia all'Infobus di default. Questa operazione che avviene nel metodo init() viene poi ritentata nel metodo start() se per caso precedentemente non c'era ancora un Infobus disponibile:

// definizione della classe InfoBusMemberSupport

private InfoBusMemberSupport m_InfoBusHolder = null;
 
 

// Associazione dell'applet TimeSource o Clock alla classe InfoBusMemberSupport

m_InfoBusHolder = new InfoBusMemberSupport( this );
 
 

// Operazione di join dell'Applet all'InfoBus di default

      try

      {

        m_InfoBusHolder.joinInfoBus( this );

      }

      catch ( InfoBusMembershipException e )

      {

          System.out.println("Clock.init warning: "+

              "joinInfoBus failed because InfoBus already set: " + e.toString());

      }

      catch ( PropertyVetoException pve )

      {

          System.out.println("Clock.init warning: "+

              "joinInfoBus failed because voter vetoed setInfoBus: " + pve.toString());

      }

Passo 2. Ascoltare gli eventi riguardanti l'InfoBus

Le liste ascoltatrici supportate sono:
 

Vengono intercettati i cambiamenti delle proprietà riguardanti l'InfoBus gestiti nel metodo ridefinito PropertyChange(). Il codice è lo stesso per produttore e consumatore, tranne per una istruzione presente nel metodo propertyChange() e riguardante la registrazione come produttore o consumatore della classe (istruzione verde=produttore e istruzione rossa=consumatore)
 

A tale scopo viene utilizzata la classe InfoBusMemberSupport

// Registrazione dell'applet TimeSource o Clock alla lista che intercetta i cambiamenti

// della proprietà dell'InfoBus.

// Istruzione definita nel metodo init()

m_InfoBusHolder.addInfoBusPropertyListener( this );
Per registrare e cancellare la registrazione di altre classi affinché vengano notificate dei cambiamenti delle proprietà, sono stati aggiunti i metodi:
 

public void addInfoBusPropertyListener(PropertyChangeListener l)

    {

        m_InfoBusHolder.addInfoBusPropertyListener ( l );

    }

public void removeInfoBusPropertyListener(PropertyChangeListener l)

    {

        m_InfoBusHolder.removeInfoBusPropertyListener ( l );

    }
 

Dopo di che è stato ridefinito il metodo propertyChange():

public void propertyChange ( PropertyChangeEvent pce )

    {

        String s = pce.getPropertyName();

        if ( ! s.equals("InfoBus") )

        {

            return;

        }
 
 

        Object oldVal = pce.getOldValue();

        Object newVal = pce.getNewValue();
 
 

        if ( oldVal == newVal )

        {

            return;

        }
 
 

        if ( oldVal != null && oldVal instanceof InfoBus )

        {

           ((InfoBus) oldVal).removeDataProducer ( this );

        }
 
 

        if ( newVal != null && newVal instanceof InfoBus )

        {

            try

            {

//             queste 2 istruzioni sono alternative a secondo se si parla di produttore

//             (TimeSource) o consumatore (Clock)

                ((InfoBus) newVal).addDataProducer ( this );

                ((InfoBus) newVal).addDataConsumer ( this );

            }

            catch ( InfoBusMembershipException e )

            {

            }

        }

    }

In questo metodo si vede chiaramente come venga gestita la sola proprietà InfoBus, viene rimossa la classe come produttore dal vecchio InfoBus e aggiunta nel nuovo.
  Questa lista gestisce i cambiamenti alle proprietà InfoBus soggette a restrizioni. Il codice è lo stesso per ambedue produttore e consumatore.

Per registrare e cancellare la registrazione di altre classi affinchè vengano notificate dei cambiamenti delle proprietà con restrizioni, sono stati aggiunti i metodi:

public void addInfoBusVetoableListener(VetoableChangeListener l)

    {

        m_InfoBusHolder.addInfoBusVetoableListener ( l );

    }
 
 

public void removeInfoBusVetoableListener(VetoableChangeListener l)

    {

        m_InfoBusHolder.removeInfoBusVetoableListener ( l );

    }

L'applet TimeSource implementa l'interfaccia InfoBusDataProducer e l'applet Clock implementa l'interfaccia InfoBusDataConsumer. Sono le liste ascoltatrici a cui bisogna registrarsi per segnalare la propria partecipazione come produttore o come consumatore.

Dopo aver ottenuto l'istanza di Infobus in questo modo:

InfoBus ib = m_InfoBusHolder.getInfoBus();
dove m_InfoBusHolder ricordiamo che è l'istanza della classe InfoBusMemberSupport, il programma nel metodo start() effettua la registrazione della classe e nel metodo stop() la sua rimozione:

// registrazione produttore

ib.addDataProducer(this);

// rimozione produttore

getInfoBus().removeDataProducer(this);
 
 

// registrazione consumatore

ib.addDataConsumer(this);

// rimozione consumatore

getInfoBus().removeDataConsumer(this);
Entrando in merito ai metodi contenuti nelle interfacce, possiamo dire che mentre l'interfaccia InfoBusDataProducer contiene il metodo per intercettare l'evento in cui viene richiesto il dato (dataItemRequested()), l'interfaccia InfoBusDataConsumer contiene il metodo per gestire l'evento che notifica la disponibilità del dato (dataItemAvailable()), e quello per gestire l'evento che notifica che il dato non è più disponibile(dataItemRevoked()). Il codice relativo per le due applet è quello che segue.

Produttore TimeSource

Se qualche classe richiede il dato CurrentTime viene richiamato il metodo dataItemRequested dell'interfaccia InfoBusDataProducer, ridefinito così:

public void dataItemRequested (InfoBusItemRequestedEvent e)

   {

      // Vengono prese in considerazione solo richieste per elementi chiamati "CurrentTime"

      if (!e.getDataItemName().equals("CurrentTime") )

         return;
 
 

      e.setDataItem(this);

   }

Consumatore Clock

Non appena il produttore rende accessibile il dato questo scatena l'evento InfoBusItemAvailableEvent, intercettato dal metodo dataItemAvailable():

public void dataItemAvailable (InfoBusItemAvailableEvent e)

   {

// Vengono prese in considerazione solo dati accessibili chiamati "CurrentTime"

      if (!e.getDataItemName().equals("CurrentTime") )

         return;
 
 

      // rimuove questa classe dalla lista ascoltatrice se aveva un vecchio CurrentTime

      if ( ( m_DataItem != null ) && ( m_DataItem instanceof DataItemChangeManager ) )

      {

          ((DataItemChangeManager) m_DataItem).removeDataItemChangeListener( this );

      }
 
 

      // ottiene il corrente CurrentTime passato dall'evento e si registra di nuovo

      // alla lista ascolatrice.

      m_DataItem = e.requestDataItem ( this, null );

      if (( m_DataItem != null ) && ( m_DataItem instanceof DataItemChangeManager ) )

      {

          ((DataItemChangeManager) m_DataItem).addDataItemChangeListener( this );

      }
 
 

   }
Non appena il produttore revoca la disponibilità del dato questo scatena l'evento InfoBusItemRevokedEvent, intercettato dal metodo dataItemRevoked ():

public void dataItemRevoked ( InfoBusItemRevokedEvent e )

   {

// Vengono prese in considerazione solo dati accessibili chiamati "CurrentTime"

      if (!e.getDataItemName().equals("CurrentTime") )

         return;
 
 

      revokeCurrentTime();

   }
 
 

void revokeCurrentTime()

   {

      if (null != m_DataItem)

      {

         // "CurrentTime" è stato revocato; rimuove la classe dalla lista ascoltatrice

         // e rilascia il puntarore al dato

         if ( m_DataItem instanceof DataItemChangeManager )

         {

            ((DataItemChangeManager) m_DataItem).removeDataItemChangeListener(this);

         }

         m_DataItem = null;

         repaint();  // repaint che indica che nessuna ora è accessibile.

      }

   }
 

DataItemChangeListener è la lista ascoltatrice che notifica l'evento del cambiamento del valore del dato gestito da InfoBus. In questo programma notifica il cambiamento del dato nominato CurrentTime. Viene implementato da entrambi le classi produttore e consumatore.

La sola applet TimeSource produttore implementa l'interfaccia DataItemChangeManager che contiene i metodi per registrarsi e cancellare la registrazione dalla lista ascoltatrice DataItemChangeListener, in quanto è TimeSource la classe detentrice della lista.

I metodi ridefiniti nel programma sono:
 

Produttore TimeSource
 

public void addDataItemChangeListener(DataItemChangeListener l)

{

      // m_changedListeners è un vettore che gestisce gli ascoltatori

      if (null==m_changedListeners)

         m_changedListeners = new Vector( 5,5 );
 
 

    m_changedListeners.addElement(l);

}
 
 

e
 
 

public void removeDataItemChangeListener(DataItemChangeListener l)

{

if (null!=m_changedListeners)

      {

         // rimuove la lista

         m_changedListeners.removeElement(l);
 
 

         // se rimosso l'ultimo elemento, cancella il vettore

         if (m_changedListeners.isEmpty())

            m_changedListeners = null;

      }

}
 

Dopo di che appena si desidera notificare il valore del tempo cambiato viene richiamato il metodo setTimeValue() e qui vengono avvisati tutti i consumatori del dato:

if (null!=m_changedListeners) {
 
 

         // Crea il change event

         DataItemValueChangedEvent dice =

            new DataItemValueChangedEvent(this, this, null);
 
 

         // Enumera gli elementi.

         Enumeration enum = m_changedListeners.elements();
 
 

         // Per ciascun ascoltatore registrato, spedisce il change event.

         while (enum.hasMoreElements())

         {

            DataItemChangeListener listener = (DataItemChangeListener)enum.nextElement();

            listener.dataItemValueChanged(dice);

         }

}
Consumatore Clock

Il consumatore è interessato a essere registrato alla lista ascoltatrice DataItemChangeListener perché in questo modo viene a conoscenza del fatto che il dato è cambiato. In tal caso viene richiamato il metodo dataItemValueChanged() ridefinito in questo caso come segue:

        public void dataItemValueChanged(DataItemValueChangedEvent event)

        {

                // Il metodo paintme ottiene il valore di CurrentTime

                // e visualizza la nuova ora nell'orologio.

                repaint();

        }

Nel metodo paint() (chiamato in seguito a repaint()) viene richiamato il metodo paintme() dove viene recuperato il valore del dato CurrentTime. Più avanti spiegheremo più dettagliatamente la modalità di come avviene.

Passo 3. Appuntamento per il dato da trasmettere

Abbiamo detto che l'appuntamento è stabilito tramite il nome del dato.

In questo programma il nome del dato è CurrentTime e consiste in una variabile Long che trasmette il tempo in millisecondi. Il valore di questa variabile viene trasmesso ogni secondo.
 

Produttore TimeSource

Per annunciare la disponibilità del dato viene utilizzato il metodo fireItemAvailable() appartenente all'interfaccia Infobus e utilizzato nel metodo run():

getInfoBus().fireItemAvailable("CurrentTime",null, this);
Una volta che il dato viene reso disponibile, vengono avvisati tutti i consumatori registrati alla lista ascoltatrice DataItemChangeListener. Nel passo 2. viene mostrato il codice.
 

Consumatore Clock

Nel metodo start() viene richiamato il metodo dove findCurrentTime() il consumatore prova subito a vedere se il dato è disponibile chiamando il metodo findDataItem() metodo dell'Infobus:

m_DataItem = getInfoBus().findDataItem("CurrentTime", null, this);
La richiesta di questa informazione provoca un evento DATA_REQUEST, in seguito al quale viene chiamato il metodo dataItemRequested() definito nel produttore.

Come detto prima quando il dato cambia valore il consumatore viene avvisato del cambiamento perché viene richiamato il suo metodo dataItemValueChanged()
 

Passo 5. Ricerca della codifica per il valore del dato
 

Produttore TimeSource

Questa classe implementa DataItem che fornisce informazioni sui dati da scambiare. In questo programma però si è deciso di non utilizzare i metodi di questa interfaccia che vengono ridefiniti e restituiscono null (tranne il metodo getSource() che restituisce this come InfoBusEventListener, cosa che indica TimeSource come la classe sorgente dell'evento InfoBusEvent)
 
 
 
 
 
 


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