Realizzazione del in Java del
GAME OF LIFE DI CONWAY,
cui analisi del dominio applicativo è stata svolta nello
Sprint 1
Nel presente
Sprint 3 la GUI deve essere realizzata attraverso una pagina HTML fornita da un Web-server, che costituisce
un componente esterno all'applicazione.
- dotare il gioco Life. di una pagina HTML come dispositivo di I/O
- la pagina deve costituire un componente esterno alla applicazione secondo la architettura riportata in IoJavalin
esterno alla applicazione
- il gestore del gioco sarà l'utente che ha aperto per primo (owner) una pagina HTML collegata al gioco. In altre
parole, solo la pagina dell'owner avrà pulsanti di comando START/STOP/CLEAN/EXIT attivi
- la pagina HTML deve essere aggiornata in modo automatico man mano il gioco procede
- un utente non owner che si collega mentre il gioco è in corso, dovrebbe vedere lo stato attuale della griglia in
modo corretto
- il deployment del gioco deve avvenire mediante Docker.
Requirement analysis
- Considerando quanto ottenuto dall'analisi conseguita Sprint 1, si vuole fare in modo che LifeController
sia pilotato tramite una pagina HTML. Tale pagina HTML deve essere fruita attraverso un browser
e pertanto veicolata attraverso un server.
- R2: Questo requisito impone di estendere il sistema sw in modo tale che la GUI venga erogata da un server Javalin,
come componente esterno all'applicazione, ovvero un server stand-alone, che fornisce la pagina HTML realizzando di fatto un
sistema distribuito.
Il componente che utilizza il server viene indicato col nome IoJavalin
IOJavalin è parte di un componente, ovvero un servizio, esterno all'applicazione che deve relazionarsi con LifeController.
Pertanto applicazione e Server Javalin devono poter comunicare scambiandosi messagg, nello svolgimento dei rispettivi servizi.
- L'interazione applicazione-servizio avvenire:
Utilizzando una connessione Websocket sulla porta 8080, ovvero la stessa aperta dal servizio che eroga la pagina, come specificato dal committente.
Tuttavia in linea di principio potrebbe avvenire anche con altri protocolli
Problem analysis
In quanto sistema distribuito, sono presenti due parti che devono interagire in modo opportuno scambiandosi messaggi:
- L'applicazione (conseguita nello Sprint 1), che chiamiamo lifectrl.
- Il server che eroga la pagina HTML, che chiamiamo guiserver
Lifectrl si deve manifestare al guiserver aprendo una connessione via webseocket sulla porta 8080.
La comunicazione tra browser e il server è bidirezionale e deve rimanere aperta per tutto il tempo necessario.
- Analisi della comunicazione pagina-server
La pagina comunica con il guiserver usando stringhe strutturate, in modo che guiserver possa ricavare dalla stringa,
oggetti coerenti con l'interfaccia IApplMessage:
msg( MSGID, dispatch, SENDER, guiserver, CONTENT, SEQNUM )
Ciò viene fatto in particolare per rendere il livello applicativo tecchnology-independent.
I messaggi inviati di tipo dispatch, ovvero fire and forget, in quanto non richiedono una risposta, ma
vogliono solo creare un'azione lato server.
Inizialmente la pagina ha come nome "unknown", che verrà usato come nome del sender alla prima connessione
msg( MSGID, dispatch, unknown, guiserver, CONTENT, SEQNUM )
Il Server risponde alla richiesta di connessione di una nuova pagina, creando ed assegnando alla pagina
un nuovo nome (pagename). Inoltre per far fede al Requisito R3, è necessario memorizzare la prima connessione
che prende il ruolo di owner.
msg( MSGID, dispatch, pagename, guiserver, CONTENT, SEQNUM )
Dopo la connessione possono essere inviati dei comandi dalla pagina al server, formalizzati come dispatch, sempre in ossequio al requisito R3,
solo il coller1 deve potre inviare i comandi. Il content varia a seconda del tipo di comando:
msg( do, dispatch, caller1, guiserver, CONTENT, SEQNUM )
CONTENT potrà essere una semplice String quale start/stop/clear/canvasready
Quando una pagina invia dispatch al guiserver dovrà inviare a sua volta un messaggio di comando a lifectrl.
Per semplificare il codice, i messaggi inviati dalla pagina al server possono avere come destinatorio
direttamente il nome lifeCtrl.
msg( do, dispatch, caller1, lifeCtrl, start, SEQNUM )
- Analisi della comunicazione Server-Pagina
Nella comunicazione tra il Server e la Pagina, i messaggi non sono Strutturati, come prima, per evitare di obbligare la pagina a
comunicare con messaggi strutturati in questo modo. Pertano il server invia alla pagina comandi espressi da semplici stringhe
ID:name //par dare il valore name al nome della pagina
cell(X,Y) //per commutare lo stato di una cella (griglia granulare)
[[false,false, ... ]] //per specificare lo stato di una griglia globale
Messaggi siffatti possno essere interpretati e gestiti direttamente in JavaScript dalla pagina
- Analisi delle comunicazioni guiserver-applicazione
Tutta la logica di interazione tra l'applicazione e il guiserver deve essere gestita dalla
classe OutInGuiInteraction, che implementa IOutDev
nel componente applicativo. Ereditando dallo sprint 2, il sistema applicativo si configura nel seguente modo:
LifeInterface life = new Life( 20,20 );
IOutDev iodevgui = new OutInGuiInteraction( ); //dispositivo di I/O
GameController cc = new LifeControllerAdhoc(life, iodevgui) ;
((OutInGuiInteraction) iodevgui).setController(cc); //iniezione del controller
OutInGuiInteraction implementa la classe IObserver per gestire comunicazioni bidirezionali asincrone. Tutti i messaggi
(ri)trasemssi dal guiserver verranno percepiti e gestiti atraverso i metodi update.
Il controller lifeCtrl viene pertanto opportunamente invocato dal metodo update, gestendo i
comandi in arrivo e inviando a sua volta messaggi di comando al guiserver.
Questi messaggi sono formalizzabili come dispatch che indicano al guiserver di modificare la visualizzazione
della griglia.
CommUtils.buildDispatch("lifectrl", "eval", msg, "guiserver" );
Test plans
Al fine di testare la corretta interazione tra i componenti, si possono realizzare caller specifici.
Si ipotizza pertanto l'esecuzione di un caller che implementa IObserver, cui routine è quella di aprire una connessione websocket alla porta 8080,
ed inviare il messaggio di comando al guiserver, simulando l'interazione guiserver-applicazione. In particolare si simula un comando di dispatch inviato da lifeCtrl a guiserver per
modificare lo stato della cella (5,7), indicando di modificare la visualizzazione della griglia, come farebbe il controller man mano che il gioco procede.
Ci aspettiamo pertanto che il guiserver ricevuto il messaggio, proceda a fare il forward a tutti i caller attualemnte attivi come pagine HTML, il messaggio per produrre l'aggiornamento corretto, modificando la cella cell(5,7).
public class CallerServerInteraction implements IObserver{
private String name;
protected void sendCellChange( ) throws Exception {
Interaction wsconn = WsConnection.create("localhost:8080", "eval", this);
//((Connection) wsconn).setTrace(true);
//build the dispatch message, switch cell 5, 7
IApplMessage cmdmsg = CommUtils.buildDispatch("lifeCtrl", "eval", "cell(5,7)", "guiserver" );
CommUtils.outblue(name + " sending " + cmdmsg);
wsconn.forward(cmdmsg);
CommUtils.delay(2000);
CommUtils.outblue("CallerServerInteraction | BYE " );
}
}
Project
- Comunicazione server - pagina:
Aprire la connessione webseocket per comunicare con guiserver, la pagina viene erogata dal server:
//se il server è nella stessa macchina, usa localhost:8080
socketToGui = new WebSocket("ws://localhost:8080/eval");
socketToGui = new WebSocket("ws://"+window.location.host+"/eval");
Come si diceva in analisi il server invia alla pagina comandi espressi da semplici stringhe, che verranno interpretate dal codice JavaScript scritto nella pagina.
Si specifica alla ricezione di un messaggio, 2 casi principali di dispatching:
Testing
Deployment
Maintenance
By studentName email: gregorio.bussolari@studio.unibo.it,

GIT repo: https://github.com/GregorioBussolari/iss2026Unibo.git