Windows 7 - GWT - Eclipse - PHP - MySQL

Hola a todos

Hoy quiero compartir con ustedes un ejemplo simple de una aplicación desarrollada con GWT que se conecta a una Base de Datos MySQL a través de unas llamadas a unas páginas PHP utilizando JSON, todo esto es desarrollado en Eclipse y lo tengo actualmente sobre una máquina con Sistema Operativo Windows 7.

Lo primero que se debe tener en cuenta es que la máquina cuente con Java instalado o sino hay que instalarlo, yo utilicé la versión mas reciente de Sun que se obtiene del siguiente link:

http://www.java.com/es/download/windows_xpi.jsp?locale=es&host=www.java.com:80

Para esta aplicación estoy usando Eclipse IDE versión 3.5 Galileo, PHP 5, MySQL 5 y Apache 2

Lo primero que se debe hacer es crear la base de datos, para ello, nos podemos apoyar en la herramienta phpmyadmin y creamos la base de datos, para este ejemplo, arquitecto luego procedemos a crear una tabla, para este ejemplo:

CREATE TABLE `propuestas` (
`id_propuesta` int(11) NOT NULL auto_increment,
`cliente` varchar(100) NOT NULL,
`proyecto` varchar(200) NOT NULL,
`vendedor` int(11) NOT NULL,
`fecha_entrega` date NOT NULL,
`link_propuesta` varchar(100) NOT NULL,
PRIMARY KEY (`id_propuesta`)
);

Teniendo ya la tabla creada le insertamos algunos registros para que tengamos unos datos de prueba, pueden ser los siguientes:

INSERT INTO `propuestas` VALUES (3, 'Algun Cliente', 'Solucion', 3, '2009-10-11', 'D:\\Proyectos\\Algun Cliente\\Propuesta Técnica Solucion.doc');

Con esta información ya tenemos algunos datos de prueba para que sean mostrados en nuestra aplicación GWT, sin embargo antes de eso, debemos crear nuestros script PHP que se conecten a MySQL y obtengan la información. Dentro del directorio raíz de Apache, creé una carpeta, Arquitecto, para colocar allí la aplicación.


Eclipse
Continuando con el proceso de crear la aplicación, dentro de Eclipse (Con el plugin de PHP y el Plugin de GWT) vamos a ver lo que se debe implementar:

Crear la aplicación GWT

Para ello creamos una aplicación con el botón, New Web Application Project, colocamos en el campo Project name, arquitecto, y en el campo Package, com.arquitecto.Propuestas, Propuestas será el nombre de esta aplicación. Luego de crear la aplicación, en el workspace de Eclipse, en el panel izquierdo se nos muestran dos directorios principales, uno es src y el otro es war, el src contiene todo el código fuente de la aplicación y el war contiene los archivos resultantes, por llamarlos de alguna manera, que se colocarán en el Servidor para desplegar la aplicación.

Dentro del directorio src de Eclipse, encontramos un módulo llamado com.arquitecto.Propuestas y dentro de él un archivo llamado Propuestas.gwt.xml, a este archivo le agregamos lo siguiente:


De esta manera nos aseguramos que la aplicación utilice el paquete JSON que provee actualmente el SDK de GWT para que soporte las consultas y las respuestas al invocar, para este ejemplo, los script PHP.


Crear los script PHP
Este es el primer paso, ya que estos script son los que se encargan de interactuar con la Base de Datos y por ende, dar la funcionalidad y el acceso a los datos para la aplicación. Dentro del directorio war a la izquierda del Workspace de Eclipse crearemos un nuevo archivo, dando clic derecho sobre el directorio war, seleccionamos New->File, en el File Name colocamos insertarPropuestas.php y dentro de este archivo colocamos el siguiente código:

require_once("JSON.php");
include ("conexion.php");

$link = Conectarse();

$sqlInsert = "INSERT INTO propuestas(cliente,proyecto,vendedor,fecha_entrega) values('".$_POST['cliente']."','".$_POST['proyecto']."',".$_POST['vendedor'].",'".$_POST['fecha_entrega']."')";
mysql_query($sqlInsert,$link) or die(mysql_error());

?>

Posteriormente procedemos a crear uno de los archivos que incluimos en el script anterior, el archivo conexion.php, de la misma forma que el script anterior, y colocamos el siguiente código:


function Conectarse()
{
if(!($link=mysql_connect("localhost","root","my passwd")))
{
echo "Error conectando a la base de datos.";
exit();
}
if (!mysql_select_db("arquitecto",$link))
{
echo "Error seleccionando la base de datos.";
exit();
}
return $link;
}
?>

Por último, procedemos a crear el script de consulta de la Base de Datos, de igual forma que los anteriores, llamado stockPropuestas.php, con el siguiente código:


<?php

require_once("JSON.php");

include ("conexion.php");



$link = Conectarse();

//$conector = mysql_connect('localhost','root','doyan2009') or die(mysql_error());

//mysql_select_db('arquitecto') or die(mysql_error());

$sqlQuery = "SELECT * FROM propuestas where id_propuesta ='".$_REQUEST['tosearch']."%'";

//$sqlQuery = "SELECT * FROM propuestas where id_propuesta = 3";

$dataReturned = mysql_query($sqlQuery,$link) or die(mysql_error());

$i = 0;



while($row = mysql_fetch_array($dataReturned)){

$value{"item"}{$i}{"Id"} = $row['id_propuesta'];

$value{"item"}{$i}{"Cliente"} = $row['cliente'];

$value{"item"}{$i}{"Proyecto"} = $row['proyecto'];

$value{"item"}{$i}{"Fecha_Entrega"} = $row['fecha_entrega'];

$value{"item"}{$i}{"Ver_Propuesta"} = $row['link_propuesta'];

$i++;

}

$json = new Services_JSON();

$output = $json->encode($value);

print($output);



?>





De esta forma tenemos ya los script php que necesitamos para la transaccionalidad de nuestra aplicación, ahora necesitamos generar toda la capa de presentación y para ello comenzamos con GWT a diseñar la interfaz de usuario. En el directorio src encontramos un módulo llamado com.arquitecto.Propuestas.client, en el cual tendremos la clase Propuestas.java, en ella colocaremos el siguiente código:

package com.arquitecto.Propuestas.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;

/**
* Entry point classes define onModuleLoad().
*/
public class Propuestas implements EntryPoint {

/**
* This is the entry point method.
*/
public void onModuleLoad() {
// TabPanel tp = new TabPanel();
DockPanel dp = new DockPanel();
dp.setStyleName("Arquitecto de Soluciones");
dp.setSpacing(4);
dp.setHorizontalAlignment(dp.ALIGN_CENTER);
dp.add(new HTML("Menu"), dp.NORTH);
Consultar myJson = new Consultar();
Menu mn = new Menu();
dp.add(mn.initializeMainForm(), dp.CENTER);

RootPanel.get().add(dp);
}
public void pintarVentana(Widget ventana){
DockPanel dp = new DockPanel();
dp.setSpacing(4);
dp.setHorizontalAlignment(dp.ALIGN_CENTER);
dp.add(ventana, dp.CENTER);
borrarVentana(); //Limpio la ventana
RootPanel.get().add(dp); //Coloco la ventana nueva
}
public void borrarVentana(){
RootPanel.get().clear();
}
}

Luego dentro del mismo directorio, damos clic derecho, creamos una nueva clase llamada Consultar.java y colocamos el siguiente código:


package com.arquitecto.Propuestas.client;





import com.google.gwt.user.client.HTTPRequest;

import com.google.gwt.user.client.ResponseTextHandler;

import com.google.gwt.user.client.ui.Grid;

import com.google.gwt.user.client.ui.TextBox;

import com.google.gwt.user.client.ui.Label;

import com.google.gwt.user.client.ui.Button;

import com.google.gwt.user.client.ui.FocusPanel;

import com.google.gwt.user.client.ui.HTML;

import com.google.gwt.user.client.ui.ClickListener;

import com.google.gwt.user.client.ui.Widget;











public class Consultar {



/*

* The URL where we go to do the search.

*/

private String DEFAULT_SEARCH_URL = "http://localhost:90/Arquitecto/Propuestas/stockPropuestas.php";



/*

* Some widgets that we go to need.

*/



private Button b1 = new Button();

private Grid gdOut = new Grid(2,1);

private Grid childGrid = new Grid(5,2);

private TextBox txtPropuesta = new TextBox();

private Label lblPropuesta = new Label("Codigo Propuesta");

private int itemNumber = 0;





public Widget initializeMainForm() {



/*

* Here we initialize and setup a panel for use it as container for the search form and

* the results.

*/



FocusPanel fpn = new FocusPanel();

Grid gd = new Grid(3,2);



b1.setText("Ingresar");

b1.addClickListener(new SearchButtonClickListener());



gd.setWidget(0, 0, lblPropuesta);

gd.setWidget(0, 1, txtPropuesta);

gd.setWidget(1, 0, b1);



gdOut.setWidget(0,0,gd);



gdOut.setBorderWidth(1);

gdOut.setWidth("280px");



childGrid.setCellPadding(0);

childGrid.setCellSpacing(0);

childGrid.setWidth("490px");





fpn.add(gdOut);



return fpn;

}





private class SearchButtonClickListener implements ClickListener {

/*

* (non-Javadoc)

* @see com.google.gwt.user.client.ui.ClickListener#onClick(com.google.gwt.user.client.ui.Widget)

*/

public void onClick(Widget sender) {

/*

* When the user click the button we fetch the URL.

*/

itemNumber = 0;

doFetchURL();

}





private void doFetchURL() {

/*

* Here we fetch the URL and call the handler

*/

b1.setText("Validando ...");

if (!HTTPRequest.asyncGet(DEFAULT_SEARCH_URL + "?tosearch=" + txtPropuesta.getText(), new JSONResponseTextHandler())) {



b1.setText("Search");

}

}

}



private class JSONResponseTextHandler implements ResponseTextHandler {

/*

* (non-Javadoc)

* @see com.google.gwt.user.client.ResponseTextHandler#onCompletion(java.lang.String)

*/



public void onCompletion(String responseText) {

/*

* When the fetch has been completed we parse the JSON response and

* display the result

*/



JSONObject jsonObject;

try {

jsonObject = JSONParser.parse(responseText);

displayJSONObject(jsonObject);



} catch (JSONException e) {



}



b1.setText("Ingresar");



}







private void displayJSONObject(JSONObject jsonObject) {

/*

* Here we clear the grid and fill it with the new values.

*/

childGrid.clear();

requestChildrenGrid(jsonObject);

gdOut.setWidget(1,0,childGrid);



}



private void requestChildrenGrid(JSONValue jsonValue){



/*

* Here we fill the grid.

*/





JSONObject jsonObject;

if(jsonValue.isArray() != null){

for(int i = 0; i < jsonValue.isArray().size();i++){

requestChildrenGrid(jsonValue.isArray().get(i));

childGrid.setWidget(itemNumber,0,new HTML("<HR/>"));

childGrid.setWidget(itemNumber,1,new HTML("<HR/>"));





itemNumber++;

int resizeNumber = itemNumber + 1;

childGrid.resize(resizeNumber,2);

}

} else {



if ((jsonObject = jsonValue.isObject()) != null) {



String[] keys = jsonObject.getKeys();

int valida = 0;



for (int i = 0; i < keys.length; ++i) {

String key = keys[i];

childGrid.setWidget(itemNumber,0,new HTML("<B>"+ key +":</B>")); //Nombre Campo

childGrid.setWidget(itemNumber,1,new HTML(jsonObject.get(key).toString())); //Valor Campo



requestChildrenGrid(jsonObject.get(key));



itemNumber++;

int resizeNumber = itemNumber + 1;

childGrid.resize(resizeNumber,2);

valida = 1;

}

if(valida != 0){

Propuestas ps = new Propuestas();

ps.pintarVentana(gdOut);

//PSMenu mn = new PSMenu();

//mn.presentarVentana();

}



} else if (jsonValue != null) {

// Only JSONObject, and JSONArray do anything special with toString, so

// it is safe to handle all non-null cases by simply using toString

//



} else {

//

}







}





}



}



}





Esta clase se encarga de consultar la página PHP stockPropuestas.php y trae los datos que están formateados con JSON para presentarlos como resultado al usuario. Igualmente creamos la clase Menu.java en la cual colocaremos el siguiente código:


package com.arquitecto.Propuestas.client;



import com.google.gwt.user.client.ui.Widget;

import com.google.gwt.user.client.ui.FocusPanel;

import com.google.gwt.user.client.ui.Grid;

import com.google.gwt.user.client.ui.Button;

import com.google.gwt.event.dom.client.ClickHandler;

import com.google.gwt.event.dom.client.ClickEvent;



public class Menu {

public Widget initializeMainForm(){

FocusPanel fpn = new FocusPanel();

Button btnInsertar = new Button("Insertar", new ClickHandler(){

public void onClick(ClickEvent event){

Insertar ins = new Insertar();

Propuestas ps = new Propuestas();

ps.pintarVentana(ins.initializeMainForm());

}

});

Button btnConsultar = new Button("Consultar", new ClickHandler(){

public void onClick(ClickEvent event){

Consultar cons = new Consultar();

Propuestas ps = new Propuestas();

ps.pintarVentana(cons.initializeMainForm());

}

});

Grid gd = new Grid(2,2);

gd.setWidget(0, 0, btnInsertar);

gd.setWidget(0, 1, btnConsultar);

fpn.add(gd);

return fpn;

}

}






Esta clase se encarga de presentar al usuario las opciones de consultar las propuestas grabadas y la opción de grabar nuevas propuestas a la Base de Datos, para insertar datos en la base de datos, creamos la clase Insertar.java y colocamos el siguiente código:

package com.arquitecto.Propuestas.client;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ClickEvent;


public class Insertar {

private String DEFAULT_SEARCH_URL = "http://localhost:90/Arquitecto/Propuestas/insertarPropuestas.php";
private Button btnInsertar = new Button("Insertar", new ClickHandler(){
public void onClick(ClickEvent event){
insertarPropuesta();
}
});
private Grid gdOut = new Grid(2,1);
private Grid childGrid = new Grid(5,2);
private Label lblCliente = new Label("Cliente:");
private TextBox txtCliente = new TextBox();
private Label lblProyecto = new Label("Proyecto:");
private TextBox txtProyecto = new TextBox();
private Label lblVendedor = new Label("Vendedor:");
private TextBox txtVendedor = new TextBox();
private Label lblFechaEntrega = new Label("Fecha de Entrega:");
private TextBox txtFechaEntrega = new TextBox();


public Widget initializeMainForm(){

FocusPanel fpn = new FocusPanel();
Grid gd = new Grid(5,2);

gd.setWidget(0,0,lblCliente);
gd.setWidget(0, 1,txtCliente);
gd.setWidget(1, 0, lblProyecto);
gd.setWidget(1, 1, txtProyecto);
gd.setWidget(2, 0, lblVendedor);
gd.setWidget(2, 1, txtVendedor);
gd.setWidget(3, 0, lblFechaEntrega);
gd.setWidget(3, 1, txtFechaEntrega);
gd.setWidget(4, 1, btnInsertar);

gdOut.setWidget(0,0,gd);
gdOut.setBorderWidth(1);
gdOut.setWidth("500px");

childGrid.setCellPadding(0);
childGrid.setCellSpacing(0);
childGrid.setWidth("490px");

fpn.add(gdOut);

return fpn;
}

public void insertarPropuesta(){

RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,DEFAULT_SEARCH_URL);
builder.setHeader("Content-type","application/x-www-form-urlencoded");

try{
builder.sendRequest(URL.encodeComponent("cliente") + "=" + URL.encodeComponent(txtCliente.getText()) + "&" + URL.encodeComponent("proyecto")+ "=" + URL.encodeComponent(txtProyecto.getText()) + "&" + URL.encodeComponent("vendedor") + "=" + URL.encodeComponent(txtVendedor.getText()) + "&" + URL.encodeComponent("fecha_entrega") + "=" + URL.encodeComponent(txtFechaEntrega.getText()), new RequestCallback(){
public void onError(Request request, Throwable exception){
Window.alert("onError");
}
public void onResponseReceived(Request request, Response response){
if (response.getText() != ""){
Window.alert("onResponseReceived request:" + response.getText());
}else{
Window.alert("Registro insertado!!!");
Propuestas ps = new Propuestas();
ps.borrarVentana();
ps.onModuleLoad();
}
}
});
}catch(RequestException e){
Window.alert("Failed to send the request:" + e.getMessage());
}
}


}

Luego que tenemos todos los archivos creados, procedemos a compilar la solución, para ello hacemos clic en el botón con forma de caja de herramientas roja llamado GWT Compile Project, el cual creará las transformaciones respectivas y nos generará los archivos que debemos subir al servidor. Estos archivos en el caso de Eclipse quedan en el directorio Workspace->Propuestas->war, de allí copiamos todos los archivos, no necesitamos el directorio WEB-INF, y los pegamos en el directorio raíz de nuestro servidor Apache.

Luego probamos la aplicación digitando en el navegador, la url de nuestro servidor apuntando a nuestra aplicación, en mi caso es algo del siguiente estilo:

http://localhost:90/Arquitecto/Propuestas/propuestas.html

De esta forma tenemos nuestra aplicación funcionando y lista!

Saludos a todos.

Código fuente del proyecto:
Descargar






Comentarios

  1. Seria interesante que dejara un link con el código disponible para Descarga.

    Saludos

    ResponderBorrar
  2. Precisamente ahorita estoy haciendo un trabajo sobre las funciones de GWT, y esto era lo que me faltaba, realizar una conexion a una base de datos para demostrar su funcionalidad (y crear un pequeño CRUD a partir de eso)leyendo en estos instantes si esto funciona me habras ahorrado muchos dolores de cabeza sin contar que tendras mi completa gratitud =)

    ResponderBorrar
  3. Pues acabo de probar el codigo y tiene varios errores en lo que es el codigo de consultar, menu e insertar, no mencionas que version de GWT usas pero en la mas actual un par de prodecimientos estan obsoletos, y me queda la duda de donde sacas el archivo JSON.php, si puedes responder te lo agradesco de a mientras tratare de resolver esos problemas, saludos!

    ResponderBorrar
  4. Hola, en este momento estoy actualizando el código ya que en efecto como menciona Neo X, hay un inconveniente con la consulta, pero ya lo solucioné, les voy a dejar el código para que lo puedan descargar y adaptar a sus necesidades, solo por favor, No olviden de donde lo obtuvieron.

    ResponderBorrar
  5. Ok muchas gracias espero la descarga, tambien queria mencionar que logre arreglar la mayor parte de uno de los codigos, pero me sigue marcando con error la linea
    String[] keys = jsonObject.getkeys(); diciendo que el getkeys no esta definido dentro de jsonObject, tambien espero que resuelvas la duda sobre donde se obtiene el archivo json.php, ya que se menciona en los scripts de php pero no se genera y al menos en la distribucion que tengo de GWT (la 1.7.1) no aparece, de antemano muchas gracias

    ResponderBorrar
  6. Hola Neo X

    Ya subí el código fuente del proyecto Arquitecto. Por otra parte, la librería JSON, es una librería que puedes descargar de http://pear.php.net/pepr/pepr-proposal-show.php?id=198 ya que es un proyecto aparte que permite transformar la información en conjuntos de la forma nombre->clave para que lo podamos manejar con PHP, puedes encontrar mas información en www.json.org. La versión que uso actualmente de GWT es la 1.7.1, tanto en Windows como en Linux.

    Saludos

    ResponderBorrar
  7. Gracias por la actualizacion, descargue la libreria de JSON php y la importe al proyecto GWT, pero el codigo de Consultar.java me sigue marcando error a pesar de esto, sigue teniendo el mismo error con getkeys y con el jsonparser.parse(responseText) alguna configuracion que me este faltando?, de antemano gracias

    ResponderBorrar
  8. Te recomiendo que descargues el código fuente que puse y lo compares con el que tienes para que puedas detectar donde está tu error.

    ResponderBorrar
  9. en eso ando, pero me parece que el archivo que subiste es el codigo ya compilado, de antemano gracias espero encontrar el por que no puedo converitr de JSONValue a JSONObject.

    ResponderBorrar
  10. Hola no se si seria factible que pusieran los archivos fuentes del proyecto.
    Se los agradeceria mucho.

    ResponderBorrar
  11. Hola,

    El código fuente está al final del artículo, en el link Descargar, el proyecto se llama Arquitecto.zip.
    Ya estoy trabajando en una nueva versión de este proyecto con la nueva versión de GWT ya que en el proyecto actual hay unas funciones que se encuentran deprecated.

    Hasta pronto!

    ResponderBorrar
  12. Se espera con gran impaciencia este proyecto con la nueva version.

    Gran trabajo el tuyo!!!

    ResponderBorrar
  13. Jeisson

    hola, estoy trabajando con GWT y su ext, para mi proyecto de grado y necesito conectarlo a una base de datos mysql utilizando la arquitectura multicapa pero no puedo utilizar php por las condiciones del proyecto, me gustaria saber si pueden ayudarme con esta conexion ya que cuando me conecto y trato de comunicar la capa de presentacion con la logica me genera un error el de comunicacion con el modulo Logica no se si necesito alguna configuracion especial en el archivo gwt.xml o que es, les agradeceria me pudieran ayudar. mi correo es gufyjf@hotmail.com

    ResponderBorrar
  14. cuando descargue solo encontre el war descomprimmido

    ResponderBorrar

Publicar un comentario

Gracias por tus comentarios.

Entradas más populares de este blog

Project Management en la gestión del cambio

Primera Aplicación Sencilla con Django

El liderazgo en nuestro tiempo actual