jueves, 31 de diciembre de 2009

UI Binding Con GWT 2.0

Una de las características nuevas de GWT es la posibilidad de crear interfaces de usuario definidas en un archivo XML, y luego vincular dicha definición con una clase, la cual incluirá el comportamiento de dicha interfaz, todo esto se realiza gracias al nuevo UiBinder.
En el siguiente ejemplo muestro como hacer una simple calculadora de enteros, definiendo la interfaz de usuario en un archivo xml y el comportamiento en una clase. Luego de todo eso podremos utilizar nuestra pantalla como si fuera un simple Widget de GWT.

El ejemplo funcionando se encuentra disponible bajo el enlace "Calculadora" del appspot de este blog.

Para empezar mostraré la pantalla definida en el xml. El archivo es "WebCalc.ui.xml"

<?xml version="1.0" encoding="UTF-8"?>
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:DockPanel>
<g:Dock direction="SOUTH">
<g:HorizontalPanel>
<g:Button text="Suma" ui:field="botonSumar" />
<g:Button text="Resta" ui:field="botonRestar" />
<g:Button text="Multuplicación" ui:field="botonMultiplicar" />
<g:Button text="División" ui:field="botonDividir" />
</g:HorizontalPanel>
</g:Dock>
<g:Dock direction="CENTER">
<g:HTMLPanel>
<p>Operador 1: <input type="text" ui:field="operador1" /></p>
<p>Operador 2: <input type="text" ui:field="operador2" /></p>
<p>Resultado: <span ui:field="resultado"/></p>
</g:HTMLPanel>
</g:Dock>
</g:DockPanel>
</ui:UiBinder>

Podemos ver que es bastante sencillo, primero definimos declarativamente un DockPanel, para la botonoera utilizamos un HorizontalPanel, el cual contiene 4 botones, vinculados por el atributo "ui:field" con ciertos métodos de la clase controladora que veremos más adelante.
Para la entrada, y en el centro del dock panel, utilizamos un panel html con tags html estándar (lo cual resalta el poder del UiBinder). Dandole el formato que a nosotros nos plazca y aún así pudiendo vincular elementos en la clase, de la misma forma que lo hicimos con los botones.

En este ejemplo no se muestra pero es posible también incluir estilos personalizados que se aplican sólo para el xml que estamos definiendo; otra muestra del gran poder de esta herramienta.

A continuación mostramos la clase que define el comportamiento de nuestra calculadora, el archivo "WebCalc.java".

public class WebCalc extends Composite {

interface Pantalla extends UiBinder<Widget, WebCalc> { }
private static Pantalla pantalla = GWT.create(Pantalla.class);

@UiField
InputElement operador1;
@UiField
InputElement operador2;
@UiField
SpanElement resultado;

public WebCalc() {
initWidget(pantalla.createAndBindUi(this));
}

@UiHandler("botonSumar")
public void sumar(ClickEvent evt) {
int op1 = leerOperador(operador1);
int op2 = leerOperador(operador2);
resultado.setInnerText("" + (op1 + op2));
}

@UiHandler("botonRestar")
public void restar(ClickEvent evt) {
int op1 = leerOperador(operador1);
int op2 = leerOperador(operador2);
resultado.setInnerText("" + (op1 - op2));
}

@UiHandler("botonMultiplicar")
public void multiplicar(ClickEvent evt) {
int op1 = leerOperador(operador1);
int op2 = leerOperador(operador2);
resultado.setInnerText("" + (op1 * op2));
}

@UiHandler("botonDividir")
public void dividir(ClickEvent evt) {
int op1 = leerOperador(operador1);
int op2 = leerOperador(operador2);
resultado.setInnerText("" + (op1 / op2));
}

private int leerOperador(InputElement tb) {

if (tb == null) {
Window.alert("No es posible leer un valor");
return 0;
}
try {
return Integer.parseInt(tb.getValue());

} catch (NumberFormatException ex) {
Window.alert("No es posible convertir a entero: " + tb.getValue());
}
return 0;
}
}

Como podemos ver es bastante simple:
Para realizar el vínculo con el archivo declaramos la interfaz interna, a la cual podemos ponerle el nombre que mas nos convenga, utilizando como sus parámetros de generics el tipo de componente resultante que deseamos y el tipo de componente que tiene el "dueño" de la interfaz generada.
Posteriormente creamos el componente utilizando el mecanismo de "Deferred Binding" que nos provee GWT.

En el constructor de nuestro manejador le indicamos a nuestro componente recien creado que se vincule con la instancia actual de la clase mediante el llamado al método "createAndBindUi".

Finalmente utilizamos los annotations @UiField y @UiHandler para vincular componentes y las acciones de los botones.
Los botones pueden vincularse con cualquier método que devuelva void, y reciba un ClickEvent.

Bueno, espero haber podido ilustrar un poco el uso de esta gran herramienta que nos provee GWT. Si se desea ampliar la lectura, recomiendo leer el siguiente tutorial.

Saludos!

Debugeando Proyectos con GWT 2 y EJB 3

Algo lindo de la forma nueva de debugear proyectos con gwt 2 es que ya no nos encontramos atados de pies y manos cuando queremos desarrollar con glassfish y ejbs. Una prueba de esto es el siguiente video.



Espero que lo disfruten.
Saludos!

lunes, 28 de diciembre de 2009

PowerThirst Sparta!

Prueben la nueva bebida energética ahora para los espartanos!



Saludos!

Google Web Toolkit 2.0

Acá les dejo un video que explica brevemente las características nuevas de GWT 2.0



Saludos!

Google App Engine

Recientemente me han activado mi cuenta de Google App Engine para complementar un poco con ejemplos en funcionamiento las cosas que voy publicando acá en este blog.

Para quienes no sepan lo que es, trataré de definirlo de la siguiente forma: Es un servicio de google, gratuito al principio (podemos pagar si necesitamos subir las prestaciones) donde podemos hostear nuestras aplicaciones web, sin publicidades, y con prestaciones como utilización de mails y bases de datos (entre muchas otras).

App engine permite cargar aplicaciones web hechas en python y en java. Es realmente simple de habilitar, necesitamos una cuenta de google (como todos los servicios de google) y un celular, ya que habilitamos el servicio a través de sms. En mi caso, mi proveedor de servicio no estaba soportado por google app engine, sin embargo llené un formulario y 1 semana después me lo habilitaron.

Para desarrollar en Netbeans con app engine, necesitamos instalar el plugin mediante esta guia, y además descargar el SDK para java de google app engine.



Con el plugin para netbeans podemos probar las aplicaciones, debugearlas, cargarlas dentro de google y además manejo gráfico de todas las configuraciones para app engine.

La dirección de app engine para este blog es http://juancavallotti.appspot.com e iré incluyendo ejemplos de cosas que desarrolle para este blog.

Espero que les sea de utilidad.

Saludos!

miércoles, 16 de diciembre de 2009

Videos KDE 4.4

Dejo acá unos videos que demuestran algunas de las características nuevas de Kde 4.4, realmente va a estar muuuuuy bueno.

Saludos!

jueves, 10 de diciembre de 2009

Piratería: Una forma de destrucción.

Hoy voy a hablar de un tema que me preocupa pero lamentablemente es un mal que no desaparecerá: La piratería.

Ésta es la era digital, todo lo que estimula nuestras mentes se encuentra ya en formato digital: Los libros, la música, las películas, etc.

En décadas anteriores a los 90, una persona tenía generalmente 2 alternativas a la hora de escuchar música: O bien compraba el disco que quería escuchar luego de un proceso de selección, o bien grababa en cassettes discos que poseían sus amigos. La diferencia de calidad era sumamente notoria, lo mismo podía apreciarse con los libros fotocopiados y en menor forma con las películas en video-cassette, en todos los casos había un factor importante que potenciaba o bien la compra o bien copia de contenidos: la calidad.

Con el advenimiento de la era digital y las comunicaciones no sólo la calidad de las copias aumentó significativamente sino que también nuestra capacidad de compartir contenidos.

Ahora bien, lo que en un principio era una pérdida de utilidades extra para escritores, músicos, etc, con la evolución esa pérdida de utilidades se convierte día a día en una forma de destrucción y, si esto sigue así, en un futuro a los escritores de libros de todo tipo no les será rentable convertir en masivo el conocimiento, a los músicos no les será rentable producir música nueva y así, algunas áreas más golpeadas que otras se irá frenando cada vez más la producción de todo tipo de contenidos.

Las personas que hoy crecen y estimulan su intelecto descargando de la red los contenidos pirateados serán mañana afectados por la no-producción de los mismos.

En pocas palabras pirateando hoy, estamos destruyendo aquello que nos estimula y no progresará mañana. Terminaremos todos escuchando música vieja, leyendo libros con conocimientos anticuados, utilizando software de baja calidad y que por ser pirateado no se puede actualizar, etc.

Una frase que uno debe tener en cuenta a la hora de piratear contenidos es la siguiente: LA PIRATERÍA ES UN ROBO. ¿A quien estamos robando? A todas las personas involucradas en el proceso de elaboración de los contenidos.

¿Que se puede hacer?
Bajo el paradigma original la forma de soportar la creación de contenidos era comprar dichos contenidos en el soporte. Hoy en día dichos soportes resultan, en algunos casos, menos que convenientes, en pocas palabras, para muchos casos, la digitalización es necesaria, pero las personas se rehusan a comprar contenidos digitales que resultan "intangibles" y ni siquiera produce cargo de conciencia el hecho de piratearlos.
Es evidente que para la producción de contenidos, debe haber dinero involucrado pues quien produce contenidos también es una persona y necesita un sustento para su vida, sin contar que dicha producción es su trabajo.

Posiblemente una solución que deje contentas a muchas personas podría ser la puesta a disposición para descarga libre de contenidos y un sistema de donaciones mediante el cual, la gente que pueda hacerlo, le de soporte al proceso y el arte no muera.

Dicho esto, me despido del post y espero opiniones para el asunto.
Saludos y por favor, no pirateen en la medida de lo posible! no maten aquello que disfrutan!

sábado, 5 de diciembre de 2009

Pruebas de Unidad: JUnit 4 y Netbeans IDE

Muchas veces en la incansable labor de desarrollo de software, nos vemos en la necesidad de probar lo que hemos hecho. La forma que primero se nos viene a la cabeza es correr la aplicación, cargar los datos, y ver que todo ande bien.
Eventualmente no tendremos la posibilidad de ejecutar la aplicación completa, o la ejecución de ésta es algo que consume mucho tiempo y es muy laborioso, sin contar que a veces dependemos de necesitar listo el trabajo de otras personas para probar nuestro código. Ahí es donde cobra sentido la automatización de las pruebas de unidad.

La herramienta propuesta por Netbeans IDE y que ciertamente es la más utilizada en el ambiente es jUnit. En este post presentaré las nociones básicas de uso de la versión 4 de jUnit, basado en Annotations.

Utilizar esta herramienta es realmente sencillo, utilizaré la siguiente clase (realmente trivial) como sujeto de pruebas:

public class Matematica {
public int dividir(int a, int b) {
return a / b;
}
}

Para comenzar, creo dentro de mi proyecto de netbeans, en test packages, mi clase que será la Suite de pruebas (o conjunto de pruebas seleccionadas). Cada prueba se realiza dentro de un método y este deberá estar anotado con @Test.

Nuestra primera clase de prueba es esta:

import org.junit.Test;
import org.junit.Assert;

public class PruebaMate {

@Test
public void pruebaCero() {
int valor = new Matematica().dividir(4, 2);
Assert.assertEquals(2, valor);
}

}

A esta clase le iremos agregando cosas a medida que vayamos avanzando.
Para comenzar la prueba en netbeans, click derecho a la clase de prueba dentro del explorador de proyectos y le damos la opción "Run".

Presentando la siguiente salida:

Testsuite: PruebaMate
Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0,089 sec

test:
BUILD SUCCESSFUL (total time: 1 second)

Esto nos dice que la prueba se ejecutó, y no sólo eso sino que se realizó correctamente y el tiempo que tardó.

Ahora agregaremos el siguiente método para probar como se comporta con la división por 0:

@Test
public void pruebaUno() {
new Matematica().dividir(4, 0);
}

Y al correrlo obtenemos la siguiente salida:

Testsuite: PruebaMate
Tests run: 2, Failures: 0, Errors: 1, Time elapsed: 0,061 sec

Testcase: pruebaUno(PruebaMate): Caused an ERROR
/ by zero
java.lang.ArithmeticException: / by zero
at Matematica.dividir(Matematica.java:3)
at PruebaMate.pruebaUno(PruebaMate.java:14)


Test PruebaMate FAILED
test:
BUILD SUCCESSFUL (total time: 0 seconds)

Ahora vemos que en realidad la segunda prueba no debió haber fallado ya que en java la división por cero causa esa ArithmeticException. Para decirle a jUnit que realmente esa excepción no es mala sino que debería considerarse como resultado exitoso de la prueba, lo hacemos a través de el annotation @Test, el método quedará de la siguiente forma:

@Test(expected=ArithmeticException.class)
public void pruebaUno() {
new Matematica().dividir(4, 0);
}

Y al ejecutar la prueba vemos lo siguiente:

Testsuite: PruebaMate
Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0,049 sec

test:
BUILD SUCCESSFUL (total time: 0 seconds)

Nota: En caso que nuestra excepción necesitara ser declarada, agregamos la cláusula throws a nuestro método de prueba.

Ahora posiblemente antes de cada prueba necesitemos realizar un setup del entorno para que se adapte al entorno de producción, esto lo realizaremos con métodos anotados con @After y @Before, por ejemplo realizaremos la instanciación de la clase matemática antes de cada prueba y sugeriremos la recolección de basura después. La clase de pruebas modificada se ve de la siguiente forma:

import org.junit.After;
import org.junit.Test;
import org.junit.Assert;
import org.junit.Before;

public class PruebaMate {

@Test
public void pruebaCero() {
int valor = m.dividir(4, 2);
Assert.assertEquals(2, valor);
}

@Test(expected=ArithmeticException.class)
public void pruebaUno() {
m.dividir(4, 0);
}

private Matematica m;

@Before
public void iniciar() {
System.out.println("Inicio la prueba");
m = new Matematica();
}

@After
public void terminar() {
System.out.println("Termino la prueba");
m = null;
System.gc();
}
}


Y al ejecutar la prueba vemos el resultado:


Testsuite: PruebaMate
Inicio la prueba
Termino la prueba
Inicio la prueba
Termino la prueba
Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0,1 sec

------------- Standard Output ---------------
Inicio la prueba
Termino la prueba
Inicio la prueba
Termino la prueba
------------- ---------------- ---------------
test:
BUILD SUCCESSFUL (total time: 0 seconds)


Ahora, instanciar la misma clase una y otra vez por cada prueba no es barato, como se puede observar en los tiempos de ejecución. Si queremos realizar algo antes de todo y luego algo después de todo utilizamos los annotations @AfterClass y @BeforeClass, modificamos la clase de pruebas de la siguiente forma:

private static Matematica m;

@BeforeClass
public static void iniciar() {
System.out.println("Inicio la prueba");
m = new Matematica();
}

@AfterClass
public static void terminar() {
System.out.println("Termino la prueba");
m = null;
System.gc();
}

Cambiando a static ya que las anotaciones requieren que los métodos sean static. Y los resultados de la ejecución son los siguientes:

Testsuite: PruebaMate
Inicio la prueba
Termino la prueba
Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0,073 sec

------------- Standard Output ---------------
Inicio la prueba
Termino la prueba
------------- ---------------- ---------------
test:
BUILD SUCCESSFUL (total time: 0 seconds)


Con lo que terminamos este tutorial introductorio para realizar pruebas de unidad, las cuales nos ahorran mucho tiempo de introducción de datos y a medida que pasa el tiempo y las pruebas se acumulan nos sirven para verificar que los cambios introducidos en el mantenimiento de las aplicaciones, no tengan efectos adversos sobre la funcionalidad existente.

Espero que les sirva. Saludos!