GWT Json PHP RPC
AUTORE: Roberto Bifulco - oltremago@gmail.com
Introduzione
Con GJPR si intende fornire un tool per realizzare un semplice
meccanismo di RPC fra GWT (Google Web Toolkit) e PHP, adoperando JSON
come formato di serializzazione dei dati. Allo stato attuale il progetto
e' una semplice prova, e non intende essere efficiente ne esaustivo riguardo
al problema affrontato.
L'idea fondamentale e' fornire la capacita' di sfruttare i metodi di una classe remota,
realizzata in PHP su di un web server, realizzando una chiamata locale dal punto di vista
della programmazione lato client.
Funzionamento
I passi della realizzazione sono i seguenti:
- Definizione delle interfacce;
- Creazione automatica, tramite il tool, del codice di supporto;
- Realizzazione della logica del servizio lato server, in PHP;
- Realizzazione di una pagina che esponga il servizio, in PHP;
- Utilizzo del codice fornito dal tool per la realizzazione del client, in Java (Tramite GWT).
Definizione dell'interfaccia
L'interfaccia viene al momento definita con un semplice file di testo, nel seguente formato:
Counter increase:=boolean add:int value=boolean getValue:=int;
Quella definita e' una semplice interfaccia: "Counter", dotata di 3 metodi con i propri argomenti (seguono i ":"), e del loro valore di ritorno (a seguito del "=").
Attualmente e' possibile definire soltanto tipi primitivi (int,long,float,double,boolean), il tipo String e solo per il parametro di ritorno il tipo speciale void. Non e' ancora realizzato il supporto ad array ed oggetti.
Generazione del codice
L'interfaccia viene interpretata dal tool per realizzare i seguenti file, rifacendosi al precedente esempio:
- Counter.java - interfaccia del servizio in Java;
- Counter.php - interfaccia del servizio in PHP;
- CounterProxy.java - Proxy del servizio in Java;
- CounterListener.java - interfaccia per la gestione asincrona del servizio in Java;
- CounterSkeleton.php - Gestore delle chiamate al servizio in PHP.
- SkeletonExceptions.php;
- JSONExceptionObject.php;
- HTTPRequestHandler.java;
- HTTPRequestHandlerListener.java;
- ServiceException.java.
Le classi necessarie all'utente, generate dal tool, sono presentate nel seguito:
Counter.java:
public interface Counter{
public boolean increase();
public boolean add(int value);
public int getValue();
}Counter.php:
interface Counter{
public function increase();
public function add($value);
public function getValue();
}
CounterListener.java
public interface CounterListener {
public void PROCESSincrease(boolean value);
public void PROCESSadd(boolean value);
public void PROCESSgetValue(int value);
}
CounterProxy.java
CounterSkeleton.php
Utilizzo
Dal lato server e' necessario realizzare la classe che realizza il servizio (Mi rendo conto di quanto e' fatta male!):
CounterImpl.php
require_once("Counter.php");
class CounterImpl implements Counter{
public function increase(){
$array = file("conto.txt");
$value = $array[0];
$value++;
$file = fopen("conto.txt","w");
return fwrite($file,$value);
}
public function add($value){
$array = file("conto.txt");
$valueF = $array[0];
$valueF = $valueF + $value;
$file = fopen("conto.txt","w");
return fwrite($file,$valueF);
}
public function getValue(){
$array = file("conto.txt");
$value = $array[0];
return $value;
}
}
counterService.php
require_once("CounterImpl.php");
require_once("CounterSkeleton.php");
$counter = new CounterImpl();
$skeleton = new CounterSkeleton($counter);
parse_str( file_get_contents("php://input"), $GLOBALS['_POST'] );
$skeleton->processRequest();
Dal lato client il processo e' anche piu' semplice, e' sufficiente implementare l'interfaccia CounterListener in una classe e richiamare i servizi tramite un oggetto CounterProxy:
Index.java
package it.robertobifulco.web.personal.client;
import it.robertobifulco.web.personal.client.services.counter.CounterListener;
import it.robertobifulco.web.personal.client.services.counter.CounterProxy;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
/**
* Entry point classes define onModuleLoad().
*/
public class Index implements EntryPoint, CounterListener {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
CounterProxy counter = new CounterProxy("counterService.php",this);
counter.getValue();
counter.increase();
counter.getValue();
counter.add(10);
counter.getValue();
}
public void PROCESSadd(boolean value) {
// TODO Auto-generated method stub
}
public void PROCESSgetValue(int value) {
RootPanel.get("content").add(new HTML("RICEVUTO VALORE: "+value));
}
public void PROCESSincrease(boolean value) {
// TODO Auto-generated method stub
}
}
Un ulteriore punto a cui si deve porre attenzione e' la definizione dei package java, che deve essere corretta manualmente (per ora!).
Ulteriori considerazioni
Allo stato attuale il tool e' molto spartano e semplice, il codice e' imperfetto e ancora pieno di bug e di
molti fattori di miglioramento dal punto di vista tecnico.
A mancare sono ancora:
- Supporto per array;
- Supporto per oggetti;
- Serializzazione delle eccezioni (e' tutto predisposto ma non realizzato);
- Revisione per la sicurezza (ci sono molte cose da fare, per ora mi sono limitato ad un controllo che il tipo dei dati trasferiti sia coerente con l'interfaccia).