miércoles, 10 de agosto de 2011

Plantilla para web.xml (Servlet spec 2.5)

Solo porque es un recurso que es muy utilizado y continuamente lo tengo que buscar, aquí les pongo una plantilla vacía para un archivo web.xml de la especificación Java Servlets 2.5

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>

martes, 15 de febrero de 2011

Comandos básicos de MySQL para crear un usuario y darle permisos

Listaré rapidamente los comandos básicos para crear una base de datos, un usuario y asignarle permisos a ese usuario para acceder a dicha base de datos.

Cuando comenzamos con algun proyecto que requiera base de datos es importante:

  • Tener un usuario destinado unicamente a la aplicación para que la base de datos no sea accedida por cualquiera.
  • Que el usuario creado este restringido por host de origen para aumentar la seguridad

Los siguientes comandos son muy autodescriptivos asi que no incurriré en ninguna explicación. Simplemente busco que esta entrada sea una referencia rápida al comenzar a programar algo.

mysql> CREATE DATABASE projectdb;
mysql> CREATE USER 'projectuser'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON projectdb.* TO 'projectuser'@'localhost' WITH GRANT OPTION;

La documentación de estos comandos se encuentra en el sitio de MySQL.

martes, 19 de mayo de 2009

Instalar LJMT (Linux, Java, Maven, Tomcat)

En este post explicaré la forma mas rápida de instalar un entorno de desarrollo de aplicaciones J2EE muy básico usando Linux, Java, Maven y Tomcat.

Linux - Ubuntu

Escogí Ubuntu por las siguientes razones:

  • Es una distribución estable basada en Debian
  • Su documentación es excelente.
  • Tiene buen soporte en su foro.
  • Su herramienta apt.
  • Tiene buen soporte del hardware en las computadoras donde lo he instalado.
  • Si es que se utiliza como Desktop, los efectos del Compiz son muy buenos.

No ahondaré en detalles sobre la instalación de Ubuntu porque además de que es muy sencilla, hay muchos tutoriales por ahí que tratan este tema. Todos los pasos del resto de la guía serán realizados en la consola, así que pueden instalar la versión Desktop , Server o incluso una versión instalada en una máquina virtual sobre su amado Windows, da igual.

Links Ubuntu
Descargar - http://www.ubuntu.com/getubuntu/download
Solicitar el envío de un CD gratis - https://shipit.ubuntu.com/
Foro - http://ubuntuforums.org/
Documentación - https://help.ubuntu.com/

El unico detalle a considerar antes de trabajar con la instalación de Ubuntu es que, en caso de haber instalado la versión Server será necesario asegurarnos que el servidor SSH se haya instalado; esto para poder acceder al servidor remotamente. En caso de no haber sido instalado desde el wizard se puede instalar con la siguiente instrucción:

user@linuxbox:~$ sudo apt-get install sshd

Java - Sun JDK6

Aunque es posible instalar Java usando apt yo recomiendo hacerlo manualmente ya que se tiene más control sobre la instalación además de que es probable que alguna vez tengamos que instalar varios JDKs o JREs y de este modo es mas fácil switchear de una versión a otra.

Es necesario descargar una copia del JDK del sitio de Sun Microsystems. El archivo que utilizo como ejemplo en aqui es un binario (terminación .bin)

Si se utiliza una versión de Linux sin interfase gráfica se puede copiar al servidor usando SCP o algo similar. En caso de no tener un cliente SCP disponible (gFTP es mi recomendación) se puede copiar un archivo al servidor usando la siguiente instrucción de la línea de comandos:

user@linuxbox:~$ scp /ruta/del/archivo usuario@servidor:/carpeta/destino

Para descomprimir, solamente hay que asegurarse que se tengan permisos de ejecución en el archivo y ejectutar el bin. Esto solamente creará una carpeta con los archivos necesarios en el mismo folder.

user@linuxbox:~$ chmod 755 jdk-6u11-linux-x64.bin
user@linuxbox:~$ ./jdk-6u11-linux-x64.bin
Sun Microsystems, Inc.  Binary Code License Agreement
[puedes saltarte la licencia apretando 'q']
Do you agree to the above license terms? [yes or no]
yes
Unpacking...
Checksumming...
.
.
.
Done.
user@linuxbox:~$

Yo generalmente creo un folder /usr/java en donde guardo todos los archivos relacionados con Java (como diferentes JDKs, JREs, Application Servers, Maven, Ant, etc.).

Escribir el folder /usr requiere ser un super usuario asi que tenemos que usar sudo para crear el directorio. Después de esto lo único que hay que hacer es mover el folder con los archivos del JDK a esta nueva ubicación.

user@linuxbox:~$ sudo mkdir /usr/java
[sudo] password for linuxbox: [el password con que el que ingresaste]
user@linuxbox:~$ sudo mv jdk1.6.0_11 /usr/java

Finalmente es necesario agregar la variable JAVA_HOME en el archivo .profile en el home del usuario actual y agregar su carpeta bin al PATH

user@linuxbox:~$ vi ~/.profile
.
.
.
JAVA_HOME=/usr/java/jdk1.6.0_11
export JAVA_HOME
PATH=$PATH:$JAVA_HOME/bin
export PATH
user@linuxbox:~$ source ~/.profile

Para probar la instalación solamente hay que introducir:

user@linuxbox:~$ java -version
java version "1.6.0_11"
Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
Java HotSpot(TM) Client VM (build 11.0-b16, mixed mode, sharing)

Maven 2

Maven es un robusto gestor de dependencias distribuido con varios plugins (incluso el compilador es un plugin) que facilitan la tarea de gestionar, construir y hacer el deploy de proyectos J2EE. Maven basa las reglas para construir un proyecto en un archivo XML llamado POM (Project Object Model) el cual contiene los distintos plugins y su configuración a utilizar durante el ciclo de vida de la construcción de un proyecto. Muchas personas lo encuentran dificil de utilizar ya que se debe de tener una estructura específica en los archivos fuente; a pesar de que esto tiene algunos contras tiene la gran ventaja de que la estandarización tiene como consecuencia la agilización del mantenimiento del proyecto.

Proximamente escribiré una entrada sobre el uso de Maven, mientras tanto me remitiré a la instalación.

Al igual que Java, es posible instalar Maven utilizando el gestor de paquetes apt, sin embargo, prefiero el método manual ya que asi tenemos mas control sobre la instalación (además de que en este caso es aún más sencillo).

Para descargar Maven basta con dirigirnos a maven.apache.org y escoger algún mirror, el tipo de archivo que uso en este tutorial es un tar.gz. Después de obtener el archivo, es necesario descomprimirlo. Con esto obtendremos una carpeta llamada apache-maven-2.0.10, ahora solamente tenemos que copiar el folder a /usr/java (siguiendo la recomendación de poner todos los archivos de Java en un solo lugar).

Aqui presento los comandos para descargar, descomprimir y colocar la version de Maven 2.0.10

user@linuxbox:~$ wget http://archive.apache.org/dist/maven/binaries/apache-maven-2.0.10-bin.tar.gz
user@linuxbox:~$ tar -xvfz apache-maven-2.0.10-bin.tar.gz
user@linuxbox:~$ sudo cp apache-maven-2.0.10 /usr/java

Finalmente debemos editar nuestro archivo .profile para 'dar de alta' la variable de entorno M2_HOME apuntando al home de Maven (esta es opcional pero hace más claro el script) y agregar al PATH la ubicación $M2_HOME/bin.

user@linuxbox:~$ vi ~/.profile
.
.
.
M2_HOME=/usr/java/apache-maven-2.0.10
export M2_HOME
PATH=$PATH:$M2_HOME/bin
export PATH
user@linuxbox:~$ source ~/.profile

Para probar la instalación únicamente usamos mvn con el parámetro -version

user@linuxbox:~$ mvn -version
Maven version: 2.0.9
Java version: 1.6.0_11
OS name: "linux" version: "2.6.27-14-generic" arch: "i386" Family: "unix"

Intermedio

Hasta ahora debemos de tener una estación de trabajo preparada para poder programar y compilar proyectos Java, necesitamos únicamente un application server para poder hacer deploy de una aplicación Web. Con las herramientas que tenemos hasta ahorita podemos hacer el experimento de un 'Hello World' (en Web) usando solamente Maven y su plugin archetype.

user@linuxbox:~$ mvn archetype:create \
  -DgroupId=com.hartoingenio \
  -DartifactId=web-artifact \
  -DarchetypeArtifactId=maven-archetype-webapp
  .
  .
  .  
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 33 seconds
[INFO] Finished at: Tue May 19 16:41:13 PDT 2009
[INFO] Final Memory: 8M/14M
[INFO] ------------------------------------------------------------------------

user@linuxbox:~$ cd web-artifact/
user@linuxbox:~$ mvn clean war:exploded tomcat:run
  .
  .
  .
May 19, 2009 4:41:17 PM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080

Sólo pon en tu navegador el siguiente URL (en caso de que el proyecto no haya sido creado en el mismo equipo, reemplaza localhost por el nombre o dirección IP del servidor).

http://localhost:8080/web-artifact/

Esto que acabamos de hacer no instala Tomcat en el equipo, simplemente Maven descarga los JARs de Tomcat del repositorio y echa a andar una versión slim.

Apache Tomcat 6.0.18

La instalación de Tomcat muy sencilla, muy parecido a lo que hicimos con Maven. Para descargar Tomcat basta con dirigirnos a tomcat.apache.org y escoger algún mirror, el tipo de archivo que uso en este tutorial es un tar.gz. Después de obtener el archivo, es necesario descomprimirlo. Con esto obtendremos una carpeta llamada apache-tomcat-6.0.18, ahora solamente tenemos que copiar el folder a /usr/java (siguiendo la recomendación de poner todos los archivos de Java en un solo lugar).

user@linuxbox:~$ wget http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.tar.gz
user@linuxbox:~$ tar -xvfz apache-tomcat-6.0.18.tar.gz
user@linuxbox:~$ sudo cp apache-tomcat-6.0.18 /usr/java

Finalmente debemos editar nuestro archivo .profile para 'dar de alta' la variable de entorno CATALINA_HOME apuntando al home de la instalación de Tomcat y agregar al PATH la ubicación $CATALINA_HOME/bin.

user@linuxbox:~$ vi ~/.profile
.
.
.
CATALINA_HOME=/usr/java/apache-tomcat-6.0.18
export CATALINA_HOME
PATH=$PATH:$CATALINA_HOME/bin
export PATH
user@linuxbox:~$ source ~/.profile

Para probar la instalación simplemente introducimos:

user@linuxbox:~$ catalina.sh run
.
.
.
INFO: Server startup in 961 ms
user@linuxbox:~$ 

Y checamos en:

http://localhost:8080/

Listo!

lunes, 11 de mayo de 2009

Comandos más utilizados en Linux

Encontré este comando ingenioso que muestra los comandos más utilizados en la consola y el número de veces que los hemos ejecutado:

history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head -n 10

Aquí la explicación del script:

  • history - Obtiene la lista de comandos usados recientemente con el siguiente formato:
    100 cd project
    101 mvn clean install
    102 cd target
    103 cp project-1.0.jar /somewhere
    (no estoy seguro con que vigencia se 'guardan' los comandos; si lo encuentro actualizo).
  • awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' - Utiliza awk para incrementar los valores de un arreglo a, usando el comando introducido como llave (el segundo parámetro de la lista anterior).
    Después de haber recibido la lista, simplemente recorre el arreglo y lo imprime en pantalla.
  • sort -rn - Ordena la lista generada por el comando anterior de mayor a menor y usando la representación numérica de la cadena
  • head -n 10 - Muestra solo los primeros 10 elementos de la lista (si usamos solo head sin parametros muestra 10, agregué el -n 10 para hacerlo más claro).

Mi resultado fue:

vhuerta@vhuertat43:~$ history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head -n 10
111 svn
88 cd
83 ls
34 mvn
23 exit
19 man
16 ssh
15 cat
12 sudo
12 ps

Hmmm... Interesante

martes, 17 de febrero de 2009

Anotaciones en Java 5+

Cuando salió Java 5 el código se lleno de anotaciones. Para los que no las ubiquen son esas sentencias que comienzan con una @ y que se colocan antes de la declaración de una clase o de un atributo o de un método:

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

@Deprecated
public class AlgunaClaseTest {
    @Before
    public void setUp() {
    }

    @Test
    public void testAlgo() {
    }

    @After
    public void tearDown() {
    }
}

Al principio me disgustaban ya que a mi gusto ensuciaban el código y rompian con las reglas de sintaxis basicas de Java (the simpler the better), pero pasado de un tiempo es posible por fin tenerles agrado después de ver todas sus ventajas.

Una anotación se define asi en el código:

public @interface Anotacion {
}

O asi en caso de que quisieramos parametros:

public @interface AnotacionParametro {
    String parametro();
}
public @interface AnotacionParametros {
    int id();
    String valor();
}

Las anotaciones pasadas se podrian usar de este modo en una clase

@Anotacion
public class AlgunaClase {
    // Cuando es un solo parametro se puede omitir el nombre y el '='
    @AnotacionParametro("parametro")
    public void algunMetodo() {
    }

    @AnotacionParametros(id=1, valor="algo")
    public void algunOtroMetodo() {
    }
}

Es importante al ver el código el no confundir a la a anotación con una interface tradicional, las anotaciones no se heredan ni forman parte del diseño de clases de los sistemas, estas unicamente sirven para agregarle metadatos al miembro sobre el cual se colocan. Se podria decir que son 'comentarios avanzados'.

El ponerle anotaciones al código no cambiaria ABSOLUTAMENTE NADA en el comportamiento del mismo. La pregunta es entonces: Si no cambia nada, ¿Para qué las quiero?

Ejemplo

Supongamos que queremos crear un programa que permita correr clases tipo pruebas unitarias y que queremos que solamente se ejecuten los métodos que esten definidos como pruebas:

public class TestCase {
    @Test
    public void prueba() { }
 
    @Test
    public void excepcion() {
        throw new RuntimeException("Error aqui");
    }
 
    @Test
    public void otraPrueba() { }
 
    @Test
    public void otraExcepcion() {
        throw new RuntimeException("Otro error aqui");
    }
}

Para esto previamente tendríamos que haber definido una anotación llamada Test, la cual deberia de ser importada por todas las clases que se quisieran probar. Nuestra anotación debe de tener definida otra anotación para que funcione del modo que queremos (sí, las anotaciones pueden tener anotaciones :) ), esta es @Retention y tiene como atributo la política de retención RetentionPolicy.RUNTIME para que el compilador la mantenga ahi después de haber creado el archivo class, ya que por default son eliminadas al compilar el archivo. Otra anotación que es conveniente indicar es @Target(ElementType.METHOD) para evitar que sea colocada en otro elemento que no sea un método. Estas anotaciones y enumeraciones estan todas en el paquete java.lang.annotation

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {
}

Y ahora si, nuestro Test Runner quedaria del siguiente modo:

import java.lang.reflect.*;

public class TestRunner {
    public static void main(String[] args) throws Exception {
        int exito = 0;
        int fallas = 0;
        
        Class clazz = Class.forName(args[0]);
        Object obj = clazz.newInstance();
        
        for (Method m : clazz.getMethods()) {
            if (m.isAnnotationPresent(Test.class)) {
                try {
                    m.invoke(obj);
                    System.out.printf("Prueba %s ejecutado%n", m.getName());
                    exito++;
                } catch (Throwable t) {
                    System.out.printf("Prueba %s fallo: %s %n", m, t.getCause());
                    fallas++;
                }
            }
        }
        System.out.printf("OK: %d, Fallas: %d%n", exito, fallas);
    }
}

El código es muy sencillo, unicamente crea un objeto usando la clase pasada como primer argumento en la línea de comandos y ejecuta todos los métodos que tengan una anotación del tipo Test.class definida, hace un conteo de errores y finalmente muestra el resumen.

Conclusión

Muchos de los frameworks actuales utilizan reflection muchísimo (Spring, JUnit, Hibernate, JSF, etc, etc, etc...), la implementación de anotaciones desde Java 5 ha permitido que algunos de estos se mantengan alejados del comportamiento del código del sistema y unicamente utilicen los metadatos para llevar a cabo sus tareas, favoreciendo asi la limpieza y legibilidad del código.

Es importante que aunque sea rara la vez que tengamos que programar una nueva anotación, sepamos emplearlas correctamente y sacarles provecho para tener sistemas mas limpios y menos acoplados.

Links

Aqui se puede encontrar la referencia oficial de Sun (in english of course) sobre anotaciones, el ejemplo se tomo de aqui y fue mejorado en este post ;) - http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html