jueves, 18 de agosto de 2011

Dispatcher - Client/Server communication

Introducción al tema según Google...
All GWT applications run as JavaScript code in the end user's web browser. Frequently, though, you'll want to create more than just a standalone client-side application. Your application will need to communicate with a web server, sending requests and receiving updates.Each time traditional web applications talk to the web server, they fetch a completely new HTML page. In contrast, AJAX applications offload the user interface logic to the client and make asynchronous calls to the server to send and receive only the data itself. This allows the UI of an AJAX application to be much more responsive and fluid while reducing an application's bandwidth requirements and the load on the server.
     Resumiendo, lo que seguramente vamos a necesitar alguna vez, por ejemplo, es obtener información de una base de datos. Esto lo hacemos desde la capa server de nuestra aplicación con GWT. Lo que vamos a ver a continuación es una forma de efectuar la comunicación cliente-servidor para poder, luego de obtenidos los datos, manipularlos en la capa client.

     El ejemplo que armé lo único que hace es incrementar un contador cada vez que se clickea un botón, pero esta tarea la efectúa en la capa server.

Primero vamos a crear la clase IncrementCounterAction, la cuál nos va a servir de transporte para los parámetros.

/**
 * Action 
 * @author Cristian
 */
public class IncrementCounterAction implements Action< IncrementCounterResult > {
    private int amount;

    /** For serialization only. */
    IncrementCounterAction() {
    }

    public IncrementCounterAction( int amount ) {
        this.amount = amount;
    }

    public int getAmount() {
        return amount;
    }
}

Luego creamos la clase IncrementCounterResult, la cúal, como su nombre indica, va a contener los resultados de la operación.

/**
 * Result
 * @author Cristian
 */
public class IncrementCounterResult implements Result {
    private int amount;
    private int current;

    /** For serialization only. REQUIRED! **/
    protected IncrementCounterResult(){}

    public IncrementCounterResult( int amount, int current ) {
        this.amount = amount;
        this.current = current;
    }

    public int getAmount() {
        return amount;
    }

    public int getCurrent() {
        return current;
    }
}

Definimos nuestro IncrementCounterHandler, el cuál se encargará de realizar la operación de incremento al counter ya en la capa server.

/**
 * Handler 
 * @author Cristian
 */
public class IncrementCounterHandler implements ActionHandler< IncrementCounterAction ,  IncrementCounterResult > {

    private int current = 0;

    public Class< IncrementCounterAction > getActionType() {
        return IncrementCounterAction.class;
    }

    public synchronized IncrementCounterResult execute( IncrementCounterAction action, ExecutionContext context ) throws ActionException {
        current += action.getAmount();
        return new IncrementCounterResult( action.getAmount(), current );
    }

    public synchronized void rollback( IncrementCounterAction action, IncrementCounterResult result, ExecutionContext context ) throws ActionException {
        // Reset to the previous value.
        current = result.getCurrent() - result.getAmount();
    }
}

Luego registramos el Handler en la clase HandlerRegistry.

/**
 * Handler Registry 
 * @author Cristian
 */
public class HandlerRegistry {
	
	static InstanceActionHandlerRegistry register() {
		
		InstanceActionHandlerRegistry registry = new DefaultActionHandlerRegistry();
		
		registry.addHandler(new IncrementCounterHandler());
		
		return registry;
		
	}

}

Y ya estamos en condiciones de, desde la capa client, realizar el request.

/**
 * Main Module
 * @author Cristian
 */
public class GWTDispatcher implements EntryPoint {
	
	HorizontalPanel main = new HorizontalPanel();
	
	public void onModuleLoad() {
		
		main.setSpacing(10);
		
		Label label = new Label("Click 'Ok' to increment the counter");
		Button button = new Button("Ok");
		button.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				Dispatcher.execute( new IncrementCounterAction( 1 ), new AsyncCallback< IncrementCounterResult >() {
		            public void onFailure( Throwable e ) {
		                Window.alert( "Error: " + e.getMessage() );
		            }
		            public void onSuccess( IncrementCounterResult result ) {
		                Window.alert( "Incremented by " + result.getAmount() + ", new total is " + result.getCurrent() );
		            }
		        });
			}
		});
		
		main.add(label);
		main.add(button);
		
		RootPanel.get("nameFieldContainer").add(main);
		
	}
}



     Para verlo en acción pueden descargar el código desde acá

Saludos.

No hay comentarios:

Publicar un comentario