martes, 30 de agosto de 2011

Java DAO Helper

Para mantener vivo el blog... :)
Este DAO Helper sirve para cualquier aplicación Java. La idea es tener algo de fácil uso para poder acceder a la base de datos de nuestra aplicación. Para poder utilizarlo necesitamos el driver específico para nuestra base de datos. En este ejemplo vamos a usar MySQL.

Modo de uso:

  1. Crear una aplicación Java.
  2. Añadir DaoHelper.java y DBConnection.java
  3. Personalizar la clase DBConnection.java con los datos de conexión de nuestra base de datos.
  4. Desde cualquier lado de nuestra aplicación podemos hacer lo siguiente...
try{
     
      QueryParameters params = new QueryParameters() {
         public void setParameters(PreparedStatement pst)
              throws SQLException {
              pst.setString(1, "Cristian");
         }
      };

      String query = "SELECT * FROM USERS WHERE USERNAME = ?";
      List< String > users = new DaoHelper< String >().executeQuery(
                query, params, new ResultReader< String >() {
          public String getResult(ResultSet result) 
                throws SQLException {
                return result.getString("nick");
          }
      });
   
   catch(SQLException e){
       e.printStackTrace();
   }

Link al proyecto: http://code.google.com/p/java-dao-helper/
Link para descargar los componentes: http://code.google.com/p/java-dao-helper/downloads/list

Saludos.

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.

miércoles, 17 de agosto de 2011

GWT Prototype App - Part 1

Buenas!!
   
     Hoy les traigo un prototipo de aplicación con GWT 2.3 que va a ir evolucionando con el tiempo... o eso espero.

     Esta entrega contiene:
  • Dispatcher (comunicación cliente-servidor)
  • DaoHelper (Base de datos)
  • Drag and drop
  • ClientBundle
La idea era armar un esqueleto para tener a mano cuando se necesite. Se le van a ir agregando más cosas, pero para una primer versión me pareció bastante completo :)
El Dispatcher y el DaoHelper no están implementados pero si disponibles ahi para el uso desde cualquier lado (Dispatcher -> client , DaoHelper -> server).
     Mas adelante voy a subir el ejemplito aislado del Dispatcher y del DaoHelper, el que se anima lo extrae de este ejemplo :)

Vista previa...  Sino, click acá para abrirlo en un browser...



El proyecto lo subí a un repo que tengo en GitHub para que puedan clonarlo con Git :)
URL del repo: click acá
Para la gente anti-git: click acá

Saludos :)

GWT-International

Es un ejemplo de internacionalización, basado en el ejemplo standard de gwt, con algunas cosas cambiadas al idioma aleman, pueden obviamente completarlo o cambiar lo que les parece. Es evolutivo ya que tanto este como el StockWatcher publicado usan el ClientBundle.



Se pueden bajar el proyecto acá

Drag and Drop :)

Encontré una librería muy piola desarrollada por Fred Sauer que permite tener widgets "draggables" en nuestras aplicaciones.


Link al proyecto hosteado en google code: http://code.google.com/p/gwt-dnd/


Abajo tiene un ejemplo que hice usando FlowPanels, no se quejen de los estilos :) 



     El código...


package ar.com.gwt.dnd.client;

import com.allen_sauer.gwt.dnd.client.PickupDragController;
import com.allen_sauer.gwt.dnd.client.drop.FlowPanelDropController;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Drag and drop example
 * 
 * @author Cristian
 */
public class GWTDnD implements EntryPoint {
	
	private static final String CSS_DEMO_FLOW_PANEL_EXAMPLE_DRAGGABLE = "demo-FlowPanelExample-draggable";
	private static final String CSS_DEMO_FLOW_PANEL_EXAMPLE_LABEL = "demo-FlowPanelExample-label";

	PickupDragController dragController;

	public void onModuleLoad() {
		
		AbsolutePanel abs = new AbsolutePanel();
		FlowPanel panel = new FlowPanel();
		panel.setStyleName(CSS_DEMO_FLOW_PANEL_EXAMPLE_DRAGGABLE);

		dragController = new PickupDragController(abs, false);

		// Building minitabs
		for (int i = 1; i < 7; i++) {

			FlowPanel flowPanel = new FlowPanel();
			FocusPanel focusPanel = new FocusPanel();
			Label label = new Label("Cris' Minitab #" + String.valueOf(i));
			label.addStyleName(CSS_DEMO_FLOW_PANEL_EXAMPLE_LABEL);
			flowPanel.add(buildObject(label));

			focusPanel.add(flowPanel);
			makeDraggable(focusPanel, label);
			panel.add(focusPanel);

		}

		//Registering drop controller
		FlowPanelDropController flowPanelDropController = new FlowPanelDropController(panel);
		dragController.registerDropController(flowPanelDropController);

		abs.add(panel);
		RootPanel.get("mainContainer").add(abs, 10, 10);

	}

	/**
	 * Builds the object to drag
	 * @param header
	 * @return
	 */
	public VerticalPanel buildObject(Label header) {

		VerticalPanel panel = new VerticalPanel();
		panel.add(header);
		panel.setStyleName(CSS_DEMO_FLOW_PANEL_EXAMPLE_DRAGGABLE);
		
		return panel;

	}
		
	/**
	 * Makes a widget draggable
	 * @param draggable
	 * @param dragHandle
	 */
	public void makeDraggable(Widget draggable, Widget dragHandle) {

		dragController.makeDraggable(draggable, dragHandle);

	}

}

     Un par de estilos...


.demo-FlowPanelExample-draggable {
  padding: 0.5em;
  margin: 0.5em;
  border: 1px solid blue;
  background-color: #B3FF87;
}

.demo-FlowPanelExample-draggable ,
.demo-FlowPanelExample-draggable DIV {
  display: inline-block;
}

.demo-FlowPanelExample-label {
  font-size: 1.2em;
  line-height: 1.3em;
}

El ejemplo completo lo pueden descargar de acá

Saludos.. :)

martes, 16 de agosto de 2011

El Efecto Hollywood

... No nos llames, nosotros te llamaremos..

Para el ejemplo de GIN que va a subir criss más adelante, no vendría mal leer un poco sobre el tema.

Acá dejo un post que explica bien clarito, qué es inversion of control, dependency injection y service locator, las diferencias y relaciones entre ellos y qué tener en cuenta a la hora de elegir utilizarlos.

Se puede leer el post en este link:


Además, para entender un poquito más sobre la sintaxis de GIN y de dónde proviene, no viene mal este videíto de una hora, de los muchachines de Google, Jesse Wilson y Dhanji R. Prasanna, quienes estuvieron trabajando en Google Wave y en GUICE y que de forma muy didactica y con la base de la lectura del link anterior, nos dan una idea muy concisa de como piensan la dependency injection.

Sasu :)

lunes, 15 de agosto de 2011

GWT + HTML5

     Otra excelente presentación de John LaBanca acerca de como enriquecer nuestras "GWT apps" con la magia de HTML5 y CSS3.

     Los temas tratados fueron:
  • Local Storage for performance
  • Visualizations via Canvas
  • Enrich your app with Audio
  • Embedding Video in your app
  • Drag and Drop support
  • Handling unsupported browser versions
  • CSS3 makes its way into GWT

     Para probar los ejemplos que muestra en el video recomienda descargar GWT 2.4 desde acá

     Link a las diapositivas mostradas: click acá


SmartGWT

SmartGWT es un API que permite usar desde Google Web Toolkit la librería Ajax SmartClient. Los widgets que lo integran son muy llamativos y van desde un Calendar tipo Google Calendar, animaciones, representaciones de árboles hasta componentes no visuales que auxilian a conectar tus aplicaciones con el servidor.




Pueden ver mas de 300 ejemplos y el código fuente en el Showcase que armaron.

Muy fácil de usar...

Sin duda le da un aspecto mucho mejor a una aplicación Web que el que provee GWT por default en sus widgets.

Saludos.

GWT... Blog + Book

Interesante blog con ejemplos e información sobre GWT, les dejo el link acá:


Y su Libro en safari:


:)

domingo, 14 de agosto de 2011

Google I/O 2010 - Measure in milliseconds: Meet Speed Tracer


     Excelente charla de Kelly Norton acerca de "Speed Tracer" (herramienta para identificar y solucionar problemas de performance en aplicaciones web). Además añade un par de tips muy útiles para mejorar la performance en nuestra aplicación.


     Para ver un video introductorio y poder probar con un par de ejemplos, CLICK ACÁ.

Utilizando Recursos con ClientBundle

¿Por qué utilizar ClientBundle para manejar recursos en mi aplicación?

Normalmente, una aplicación utiliza muchas imágenes. En HTML, cada imagen se almacena en un archivo separado y al navegador se le pide que descargue cada archivo desde el servidor web a través una transacción HTTP. Esta forma de manejar los recursos puede ser un desperdicio de varias formas:

  • Gastos innecesarios: En una aplicación convencional, por cada imagen se debe enviar una petición HTTP al servidor. A veces el tamaño de las imágenes es ínfimo (iconos o algo por el estilo). En ese caso, el tamaño de la imagen es a menudo más pequeña que la cabecera de la respuesta HTTP que se envía con los datos de imagen. Es decir, que la mayoría del tráfico es el contenido de los gastos generales que se requieren para obtener la imagen y no justamente de ella que sería lo normal.
  • Chequeos de cache innecesarios: Incluso cuando el cliente almacena en caché las imágenes, una solicitud 304 ("Not Modified") es enviada para comprobar y ver si la imagen ha cambiado. Dado que las imagenes cambian con poca frecuencia estos chequeos son innecesarios
     Todo esto hace que se retrase el inicio de nuestra aplicación. Es por eso que vamos a aprender como hacer uso de nuestras imagenes y estilos utilizando la interfaz ClientBundle.

     Supongamos que tenemos una aplicación básica de GWT y queremos llegar a algo como lo siguiente...


     ... utilizando estilos definidos en un css sobre los Labels y un par de imágenes como ejemplo.

     Lo primero que hay que hacer es crear el paquete "resources", dentro de este crear los paquetes "images" y "css". Dentro de este último ubicamos nuestra hora de estilos, en este ejemplo es "StylesCss.css". Dentro del paquete "images" ubicamos todas las imágenes que queremos utilizar dentro de nuestra aplicación.


        Nuestra hoja de estilos contiene algo como lo siguiente:

.crisStyle{
	color: blue;
	font-weight: bold;
	font-style: oblique;
	font-size: x-large;
}
.maxiStyle{	
	color: red;
	font-size: x-large;
}
.links{
	color: purple;
	text-decoration: blink;	
}

     Junto con la hoja de estilos vamos a crear la interfaz "StylesCss" donde vamos a mapear los estilos definiendo métodos que retornan un String.

package ar.com.gwt.test.client.resources.css;

import com.google.gwt.resources.client.CssResource;

/**
 * Styles CSS
 * @author Cristian N. Miranda
 */
public interface StylesCss extends CssResource{

	public String crisStyle();
	public String maxiStyle();
	public String links();
	
}

     Junto con las imágenes vamos a crear la interfaz "Images" mapeando las imágenes a utilizar:

/**
 * Images.java
 * @author Cristian N. Miranda
 */
package ar.com.gwt.test.client.resources.images;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ImageResource;

public interface Images extends ClientBundle{

    @Source("arrow_refresh.png")
    public ImageResource refresh();

    @Source("accept.png")
    public ImageResource accept();
    
}

     Al nivel del paquete "resources" creamos la interfaz "Bundle" con el siguiente contenido:

package ar.com.gwt.test.client.resources;

import ar.com.gwt.test.client.resources.css.StylesCss;
import ar.com.gwt.test.client.resources.images.Images;
import com.google.gwt.resources.client.ClientBundle;

public interface Bundle extends ClientBundle {
	
    @Source("css/StylesCss.css")
    public StylesCss css();
    
    public Images images();
    
}

     Luego lo único que queda por hacer es inyectar los estilos desde la clase "Resources" la cual vamos a utilizar para acceder a los estilos y a las imágenes.

package ar.com.gwt.test.client.resources;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.StyleInjector;

public class Resources {

	public static Bundle instance = GWT.create(Bundle.class);

	static {
		StyleInjector.inject(instance.css().getText());
	}

}

   Ya estamos en condiciones de emplear los estilos e imágenes en donde queramos... por ejemplo, para conseguir el resultado esperado hacemos lo siguiente...
  
package ar.com.gwt.test.client;

import ar.com.gwt.test.client.resources.Resources;
import ar.com.gwt.test.client.resources.css.StylesCss;
import ar.com.gwt.test.client.resources.images.Images;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Entry point classes define onModuleLoad().
 */
public class GWTTest implements EntryPoint {
	
	public static StylesCss css = Resources.instance.css();
	public static Images images = Resources.instance.images();
	
	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		
		HorizontalPanel words = new HorizontalPanel();
		HorizontalPanel main = new HorizontalPanel();
		VerticalPanel panel = new VerticalPanel();
		
		words.setSpacing(5);
		
		//Link to GWT Documentation
		Anchor a = new Anchor();
		a.setHref("http://somelink.com");
		a.setText("GWT Developer's Guide");
		a.setStyleName(css.links());
		
		//Labels
		Label maxiLabel = new Label("Using");
		maxiLabel.setStyleName(css.maxiStyle());
		
		Label crisLabel = new Label("Resources!");
		crisLabel.setStyleName(css.crisStyle());
		
		words.add(maxiLabel);
		words.add(crisLabel);
		
		//Images
		Image img1 = new Image(images.accept());
		Image img2 = new Image(images.refresh());
		
		main.add(panel);
		
		words.add(img1);
		words.add(img2);	
		
		panel.add(a);
		panel.add(words);
		
		RootPanel.get("mainContainer").add(panel);

	}
}

     Pueden descargar el ejemplo completo desde el siguiente link: http://code.google.com/p/gwt-client-bundle/downloads/list

viernes, 12 de agosto de 2011

Publicando código fuente en el blog

Buenas...
Esta entrada no tiene nada que ver con GWT. Pero va a resultar útil para los posts en el blog.
Cuando quieran poner código Java en una publicación tienen que hacerlo entre los tags <pre class="brush: java"></pre> 

Por ejemplo...
El siguiente código sin formato:

System.out.println("Esto es código Java!");

quedaría...

System.out.println("Esto es código Java!");

Abrazo :)

Stock Watcher Sample

Aca les dejo el link donde se pueden bajar el código del primer ejemplo que Google propone para empezar con GWT, tiene unos pequeños cambios incorporados, respecto al original, en lo que respecta al tratamiento de imágenes y lo que son estilos.

http://code.google.com/p/gwt-stock-watcher-sample/downloads/list

Getting Started

No voy a decir mucho.. pero para los que nunca se metieron en tema, acá les dejo el link con la documentación de Google acerca de GWT, como instalar los plugins necesarios en el eclipse y demás...

http://code.google.com/intl/es/webtoolkit/gettingstarted.html

Lo que viene son los proyectitos, pero nunca está demás pegarle una mirada a la documentación oficial :)
Abrazo.

miércoles, 10 de agosto de 2011

GWT Express Blog



   A ver cuanto dura esto... jaja :)

     La idea es que vayamos publicando acá todo lo que vayamos encontrando que nos resulte útil o nos parezca copado acerca de GWT, así como también creaciones propias. Ya tengo un par de proyectitos hosteados en google code que puedo ir subiendo, cuando tenga un rato lo hago. Mientras tanto los interesados me avisan y los doy de alta en el blog como admins o lo que sea que me diga Mr. Google para que puedan publicar.



Abrazo.