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 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;

Chiaramente il metodo di definizione dell'interfaccia e' molto spartano, ma nulla vieta in futuro, se si dovesse decidere di portare avanti questo lavoro, di ridefinirlo in maniera appropriata.
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:

A questi si aggiungono i file di utilita' (di cui l'utente non deve preoccuparsi):
Che vengono tutti creati nella cartella "Counter".

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);

}

Le successive non le riporto poiche' sono abbastanza voluminose ed e' meglio guardarle nel proprio editor preferito:

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;
	}
}

Inoltre si deve realizzare la pagina che espone il servizio:

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();

Come si vede, e' sufficiente passare allo Skeleton l'oggetto che implementa l'interfaccia del servizio e chiamare il metodo processRequest() dello skeleton cosi' creato. La chiamata al parse_str(..) e' necessaria perche' GWT non formatta i dati passati con un oggetto XMLHTTPRequest in form-encoded, ma li passa come plain text. Questa chiamata inserisce i parametri nell'array superglobale $_POST.

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
	
	}

}

Da notare che l'indirizzo del servizio e' fornito al costruttore del proxy.
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: