lunes, 1 de febrero de 2010

RCP en Gwt (Netbeans gwt-ext)

Hola:

Para esta entrada es necesario que tengan configurado previamente un proyecto con gwt en Netbeans y también configurado en plugin de gwt-ext (jar).

Primero me gustaría hablar de las ventajas de Gwt y después hablar de las desventajas.

- Todo lo programas en Back End, lo que quiere decir que no tienes que aprender forzosamente html, css, javaScript solo tienes que saber java, el Front End lo programas en Back End aunque suene extraño asi es, el compilador de gwt se encarga de generar un codigo optimo en js para tu aplicación.

- La manera de hacer peticiones asíncronas se hacen de manera rápida por medio de RCP.

- La curva de aprendizaje es rápida.

- Las aplicaciones funcionan en la mayoría de los navegadores (IE,Firefox).

Bueno después de esta breve introducción vamos a crear una aplicación que de administre usuarios un CRUD.

Paso 1: Como siempre crear un bean que es parte del modelo para este ejemplo se llamara el clásico usuario, es muy importante que lo coloquen en el paquete donde van a poner su Gwt Modulo.

Para nuestro ejemplo tendremos que crear nuestro paquete del modelo y view al nivel de: org.aplication.client donde va todo en codigo que se convierte en Front End.

Despues creamos un clase de llamada Usuario dentro del paquete org.aplication.client.modelo


Creamos una clase llamada Usuario.

package org.aplication.client.modelo;

import com.google.gwt.user.client.rpc.IsSerializable;

/**
*
* @author isaac
*/
public class Usuario implements IsSerializable{

private String nombre;
private String apellido;
private int edad;
private int cve;

public String getApellido() {
return apellido;
}

public void setApellido(String apellido) {
this.apellido = apellido;
}

public int getCve() {
return cve;
}

public void setCve(int cve) {
this.cve = cve;
}

public int getEdad() {
return edad;
}

public void setEdad(int edad) {
this.edad = edad;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}



}

Esta clase implementa IsSerializable de gwt que es la que encargara de serializar nuestra clase y permite la comunicación entre en cliente y el servidor.

Paso 2. Creamos un paquete llamado view (org.aplication.client.view) y una clase llamada GuiUsuario, el diagrama de clase Uml para esta clase sera mas o menos como este aunque despues iremos agregando mas metodos o clases.



Bueno primero crearemos nuestro formulario y despues nuestro rcp.


package org.aplication.client.view;

import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.Position;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.MessageBox;
import com.gwtext.client.widgets.Window;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.form.FormPanel;
import com.gwtext.client.widgets.form.TextField;
import org.aplication.client.modelo.Usuario;

/**
*
* @author isaac
*/
public class GuiUsuario {

private Usuario usuario;
private Window window;
private FormPanel formPanel;
private TextField nombre;
private TextField apellido;
private TextField edad;

public FormPanel getFormPanel() {
formPanel = new FormPanel();
formPanel.setFrame(true);
formPanel.setTitle("Usuario");
nombre = new TextField("Nombre", "nombre", 230);
apellido = new TextField("Apellido", "apellido", 230);
edad = new TextField("Edad", "edad", 230);
formPanel.add(nombre);
formPanel.add(apellido);
formPanel.add(edad);
return formPanel;

}

public Usuario getUsuario() {
return usuario;
}
public Window getWindow() {
window = new Window();
window.setTitle("Layout Window");
window.setClosable(true);
window.setWidth(600);
window.setHeight(350);
window.setPlain(true);
window.setCloseAction(Window.HIDE);
window.add(getFormPanel());

Button buttonNewUser = new Button("Nuevo Usuario"); buttonNewUser.addListener(new ButtonListenerAdapter(){
@Override public void onClick(Button button, EventObject e) {

MessageBox.alert("prueba de evento");


}
} ); window.setButtonAlign(Position.CENTER);
window.addButton(buttonNewUser); return window; }

public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}



}

El metodo getWindow() se encarga de crear la ventana y tambien de crear el FormPanel por medio del metodo getFormPanel(), despues solo hace falta llamar a nuestra Gui desde el EntryPoint que sera la clase MainEntryPoint que esta en el paquete org.aplication.client.


package org.aplication.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.ClickListener;
import com.gwtext.client.widgets.Window;
import org.aplication.client.view.GuiUsuario;

/**
* Main entry point.
*
* @author isaac
*/
public class MainEntryPoint implements EntryPoint {
/**
* Creates a new instance of MainEntryPoint
*/
public MainEntryPoint() {
}

/**
* The entry point method, called automatically by loading a module
* that declares an implementing class as an entry-point
*/
public void onModuleLoad() {

final Button button = new Button("Click me!");

button.addClickListener(new ClickListener(){
public void onClick(Widget w) {
GuiUsuario guiUsuario = new GuiUsuario();
Window winUsu = guiUsuario.getWindow();
winUsu.show();
}
});

RootPanel.get().add(button);

}
}



winUsu.show(); Este metodo de la clase Window hace que la ventana se visualize en el navegador del cliente.

Depues damos run a proyecto y deberiamos tener algo como esto.



Paso 3. Crear el RCP damos click derecho en new / other depues aparecera la opcion de gwt y una lista donde esta gwtrcp damos click y despues nos pedira en nombre del servicio en paquete donde lo pondremos.


Creación del servio: Lo llamaremos GWTServiceUser y estará dentro del paquete org.aplication.client.servicio

Después tendremos una estructura como la siguiente:


Un rcp de gwt necesita de 3 clases principales y un mapeo en el web.xml que ya hace por defecto el ayudante de netbeans.

dentro del paquete org.aplication.client.servicio
- interface GWTServiceUserAsync
-interface GWTServiceUser
y del lado del servidor en el paquete org.aplication.server.servicio esta la clase:
-class GWTServiceUserImpl

El diagrama de clases para la creación de usuarios desde el cliente al servidor es la siguiente:

El código para cada clase es el siguiente:

package org.aplication.client.servicio;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import org.aplication.client.modelo.Usuario;

/**
*
* @author isaac
*/
@RemoteServiceRelativePath("servicio/gwtserviceuser")
public interface GWTServiceUser extends RemoteService {
public String nuevoUsuario(Usuario usuario);
}

---------------

package org.aplication.client.servicio;

import com.google.gwt.user.client.rpc.AsyncCallback;
import org.aplication.client.modelo.Usuario;

/**
*
* @author isaac
*/
public interface GWTServiceUserAsync {
public void nuevoUsuario(Usuario usuario, AsyncCallback callback);
}

--------------------------------------

package org.aplication.server.servicio;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import org.aplication.client.modelo.Usuario;
import org.aplication.client.servicio.GWTServiceUser;

/**
*
* @author isaac
*/


public class GWTServiceUserImpl extends RemoteServiceServlet implements GWTServiceUser {

private static List usuarios = null;
private static int contCve = 0;

public String nuevoUsuario(Usuario usuario) {
contCve++;
usuario.setCve(contCve);

if(usuarios==null){

usuarios = new ArrayList();
usuarios.add(usuario);

}else
usuarios.add(usuario);

for(Usuario u:usuarios){
System.out.println("usuario "+u.getNombre());
}

return "Se ha creado el usuario";
}




}

-------------------------------------------------------------


package org.aplication.client.view;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.Position;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.MessageBox;
import com.gwtext.client.widgets.Window;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.form.FormPanel;
import com.gwtext.client.widgets.form.TextField;
import org.aplication.client.modelo.Usuario;
import org.aplication.client.servicio.GWTServiceUser;
import org.aplication.client.servicio.GWTServiceUserAsync;

/**
*
* @author isaac
*/
public class GuiUsuario {

private Usuario usuario;
private Window window;
private FormPanel formPanel;
private TextField nombre;
private TextField apellido;
private TextField edad;
private static GWTServiceUserAsync service;

public FormPanel getFormPanel() {


formPanel = new FormPanel();
formPanel.setFrame(true);
formPanel.setTitle("Usuario");
nombre = new TextField("Nombre", "nombre", 230);
apellido = new TextField("Apellido", "apellido", 230);
edad = new TextField("Edad", "edad", 230);
formPanel.add(nombre);
formPanel.add(apellido);
formPanel.add(edad);


return formPanel;
}

public Usuario getUsuario() {
return usuario;
}

public Window getWindow() {

window = new Window();
window.setTitle("Layout Window");
window.setClosable(true);
window.setWidth(600);
window.setHeight(350);
window.setPlain(true);
window.setCloseAction(Window.HIDE);
window.add(getFormPanel());

Button buttonNewUser = new Button("Nuevo Usuario");
buttonNewUser.addListener(new ButtonListenerAdapter(){

@Override
public void onClick(Button button, EventObject e) {
Usuario u = new Usuario();
u.setEdad(Integer.parseInt(edad.getText()));
u.setNombre(nombre.getText());
u.setApellido(apellido.getText());

insertaUsuario(u);

}

}
);


window.setButtonAlign(Position.CENTER);
window.addButton(buttonNewUser);



return window;
}

public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}



public void insertaUsuario(Usuario usuario) {


// Create an asynchronous callback to handle the result.
final AsyncCallback callback = new AsyncCallback() {

public void onSuccess(Object result) {
String respuesta = (String) result;

MessageBox.alert(respuesta);

}

public void onFailure(Throwable caught) {
MessageBox.alert("Error " + caught);
}
};

getService().nuevoUsuario(usuario, callback);

}


public static GWTServiceUserAsync getService() {
service = (GWTServiceUserAsync) GWT.create(GWTServiceUser.class);
ServiceDefTarget endpoint = (ServiceDefTarget) service;
String moduleRelativeURL = GWT.getModuleBaseURL() + "servicio/gwtserviceuser";
endpoint.setServiceEntryPoint(moduleRelativeURL);
return service;
}



}

----------------------------------------

- La parte importante que debemos entender de los rcp de gwt es que podemos mandar beans desde los clientes hasta nuestro servidor de manera clara sin necesidad de ocupar
request.

La menera que se logra esto es atravez de del siguiente metodo de la clase
GuiUsuario.

public static GWTServiceUserAsync getService() {
service = (GWTServiceUserAsync) GWT.create(GWTServiceUser.class);
ServiceDefTarget endpoint = (ServiceDefTarget) service;
String moduleRelativeURL = GWT.getModuleBaseURL() + "servicio/gwtserviceuser";
endpoint.setServiceEntryPoint(moduleRelativeURL);
return service;
}

y para llamarlo ocupamos el metodo siguiente dentro de la misma clase:

public void insertaUsuario(Usuario usuario) {

// Create an asynchronous callback to handle the result.
final AsyncCallback callback = new AsyncCallback() {
public void onSuccess(Object result) {
String respuesta = (String) result;

MessageBox.alert(respuesta);

}

public void onFailure(Throwable caught) {
MessageBox.alert("Error " + caught);
}
};

getService().nuevoUsuario(usuario, callback);

}

Cuando se ejecuta este metodo llama directemente a metodo getService() el cual tiene un metodo llamado nuevoUsuario que ha este le mandamos como parametro el usuario y el callback que su tarea va ser recibir la respuesta del rcp del servidor en este caso de la clase GWTServiceUserImpl que sobreescribe el método nuevoUsuario que es donde creamos la lista y insertamos elementos a ella y esta responde con el mensaje return "Se ha creado el usuario" el cual es recibido por el callback en:

public void onSuccess(Object result) {
String respuesta = (String) result;

MessageBox.alert(respuesta);
.
.
.

Por ultimo necesitamos el evento del boton de la GuiUsuario para crear el usuario y llamar al método insertaUsuario

Button buttonNewUser = new Button("Nuevo Usuario");
buttonNewUser.addListener(new ButtonListenerAdapter(){

@Override
public void onClick(Button button, EventObject e) {
Usuario u = new Usuario();
u.setEdad(Integer.parseInt(edad.getText()));
u.setNombre(nombre.getText());
u.setApellido(apellido.getText());

insertaUsuario(u);

}

}
);

Después damos run al proyecto y nuestra aplicación esta lista para crear usuarios yo puse una lista estática de usuarios pero bien se pueden insertar en una base de datos con hibernate o con jdbc.


Bueno eso es todo despues crearemos un grid ....

Dedicado a mi princesita.


Segunda Parte


4 comentarios:

Anónimo dijo...

Muy Bueno tu blog.
Recien estoy probando GWT y me gustaria mucho saber como cargar los datos de una base en datagrid...
No se si me podrias ayudar con eso.

j. isaac legorreta dijo...

Si amigo estoy preparando una entrada de mi blog con un grid de Gwt-Etx, yo creo el lunes 22 de febrero la publico

Anónimo dijo...

Hola...
Otra vez pidiendote que xf publiques como llenar los datos de una base en un grid. La verdad que no tengo idea de como manejar los datos con GWT. De antemano gracias x todo. Y sigue adelante...

j. isaac legorreta dijo...

Hola ya estoy haciendo la entrada del grid puedes ir checandola y depus pongo el código del grid

http://isaacrobot.blogspot.com/2010/03/gwt-rcp-parte-ii-grid-gwt-ext.html