Contacto

Nos puedes enviar un artículo a publicar (si te fue útil, seguro que a otros también).
Nos puedes sugerir temas/profundidad de interés.
correo-e - perfil

Busquedas

ladyjava-javazone

Simplemente ... genial :-D.
LadyJava Una adaptación de "Bad Romance" de Lady Gaga para el evento de JavaZone



La clasica y ampliamente conocida pantalla azul de error que se muestra en el video, tiene varias cosas interesante / divertidas:
Leer más...

Session en SimpleFormController de Spring mvc

 En el artículo Formulario con Spring MVC se utilizó un controlador que extiende la clase SimpleFormController de Spring.

 En el ejemplo que se hizo en ese artículo, reescribimos el método onSubmit(command, errors) de la clase SimpleFormController, para el manejo del request del formulario.

 El método "onSubmit" tiene varias firmas (está sobrecargado), y nosotros seleccionamos uno, según la necesidad de la aplicación.

 Las diferentes firmas de onSubmit son:
Leer más...

El comando history en linux

 Ver la lista de comandos ejecutados en linux.

 Para poder ver una lista de los comandos ejecutados desde la shell (bash), simplemente se tiene que teclear en una terminal el comando "history", por ejemplo:

    history

...
 497 sudo apt-get install gwenview
 498 ls *.png
 499 gwenview imagen.png
 500 exit
 501 history


 Esta es la lista que se nos muestra cuando (uno a la vez), estando en la shell apretamos las flechas arriba/abajo, o " CTRL + r " y comenzamos a escribir el comando.
 Seguro que esto no es novedad, ya que es de los primeros comandos que se aprenden.

 Lo que me motiva a escribir este pequeño artículo/'recordatorio', es que normalmente veo ejecutar "history", y a continuación "copiar y pegar" con el ratón, de esa lista, el comando que se quiere ejecutar nuevamente.

 Lo interesante del comando "history" en la shell bash, es que podemos ejecutar fácilmente cualquier registro de esta lista (sin tener que "copiar y pegar").
Leer más...

Como redireccionar la entrada y salida en linux

 Redirección en Linux

 Al ejecutar algún comando en el shell de Ubuntu (linux en general), el resultado, por defecto, se muestra en la consola (salida estándar).
 Si se necesita, por ejemplo, guardar el resultado de un comando (como ser la ejecución de grep) en un archivo, es necesario redirigir la salida estándar al archivo, en lugar de a la pantalla.

 Tenemos tres flujos para redireccionar (Salida estandar, Error estandar, Entrada estandar), y varios operadores para la tarea.
 A continuación una descripción de los operadores que vamos a usar en los ejemplos.
Leer más...

Problema con wifi en ubuntu 10.04

 Luego de actualizar un par de portátiles (Un Dell y otro Toshiba) a la nueva versión de Ubuntu (lucid - Ubuntu 10.04), en ambos tuve el mismo problema, no me era posible conectar a las redes wireless.

 El gestor de red por defecto es network-manager. Ya había tenido problemas con este gestor en versiones mas antiguas de ubuntu, al necesitar usar ip fija en un equipo.

 Logre conectar con wifi-radar, pero no en todas las redes.

 Dada la experiencia anterior, recurrimos a un "viejo" ( y muy mejorado) conocido: wicd.

 WICD es un network manager, y actualmente se encuentra en los repositorios de ubuntu, por lo que, como vemos a continuación, hace muy sencillo su instalación.

Leer más...

Encriptar password en JBoss

 Cómo encriptar contraseñas - y usar contraseñas encriptadas - en JBoss.

 Normalmente, en las aplicaciones que realizamos para correr en jboss, es necesario conectarse a una base de datos.
 Los datos de conexión a la base, incluso la contraseña de acceso, suelen estar en un archivo de texto plano ( "datasource", -ds.xml).
 En este artículo, vamos a describir la forma de encriptar las claves usadas en los archivos datasource, por medio de bibliotecas disponibles en JBoss, y cómo configurar el acceso a la base de datos, con la contraseña encriptada desde JBoss.
 Para más información, ver la documentación de JBoss sobre JAAS, y es interesante el capítulo 5 del libro: "JBoss: A Developer's Notebook" de O'Reilly.

Configurando un datasource seguro:
 1) Ejemplo de datasource con contraseña en texto plano.
 A continuación, un archivo datasource sencillo, con la contraseña sin cifrar.
Leer más...

Ajax en java - un ejemplo con dwr

 En el artículo anterior (Ajax en java - dwr) se configuró el framework DWR en un proyecto web.
 Continuando con la introducción a dwr, vamos a ver algunas acciones que pueden ser comunes en un proyecto web, como ser:
   Ejecutar (por ajax) un método con parámetros en el servidor (esto lo hacemos usando dwr).
   Acceder a un objeto en sesión con dwr.
   Desde el servidor, retornar al cliente un array de String .
   En el cliente, cargar un combo usando funciones javascript de dwr.
  Para el ejemplo, asumimos que:
Leer más...

Ajax en java - dwr

 Ajax en java fácil usando DWR

  El objetivo de esta primera entrega, es hacer una breve introducción al framework DWR, y que esté instalado / configurado en nuestro proyecto web.

 Por medio de Ajax ( Asynchronous JavaScript and XML ), es posible transferir datos entre el el cliente (el navegador web) y el servidor en "background".
 Esto permite generar un comportamiento dinámico, sin cargar (o refrescar) todo el contenido de la pantalla. Como ejemplo sencillo, podemos imaginar un formulario en el cual hay un combo con una lista de países. Al hacer click en uno de los países, se carga otro combo con sus ciudades.
 Para esta sencilla tarea aparente, es necesario escribir 2 bloques de datos bien diferenciados:
  1) En el cliente: En javascript el código que captura la acción del usuario, envía al server los datos requeridos por esa acción, y espera la respuesta (de forma asincrónica) para generar el nuevo combo (o el comportamiento que corresponda).
  2) En el server escribir un servlet que captura la petición http, y retorne los datos al cliente.

 Bienvenido DWR
  DWR (Direct Web Remoting - http://directwebremoting.org/dwr) es un framework open source en java, que permite escribir aplicaciones AJAX, unicamente escribiendo código java en clases comunes (POJOS), sin necesidad de conocer detalles de ajax, como ser la forma de enviar objetos/datos por medio de javascript desde el cliente al servidor, la captura y lectura de la respuesta.
  De esta forma reducimos casi al mínimo el código nativo en javascript, y tampoco tenemos que escribir los servlets.
  DWR incluye un servlet principal que se tiene que configurar (funciona como controlador), y varias bibliotecas de javascrip necesarias por el propio framework, y que nos son útiles para diferentes tareas.

 Configurar dwr en pocas palabras :)
  Montar el framework en nuestros proyectos web, probablemente no podría ser mas fácil.

  Asumimos que tenemos un proyecto web (en el ejemplo se llama: "DWREjemplo"), y la biblioteca dwr.jar ( http://directwebremoting.org/dwr/download.html ).
    Nota: En los ejemplos usamos la versión estable 2.X. En el momento de escribir el artículo, está disponible también la versión 3 no estable .

 La configuración se puede hacer en dos archivos.
  En web.xml se configura el servlet que funciona como "controlador" en el framework.
  El otro archivo es dwr.xml, aquí se se indica varias configuraciones, como ser las clases java usadas y el nombre lógico con el que se accede a estas clases desde javascript (será el nombre de la libreria javascript a importar en las páginas). También se indica lo métodos a los que se puede acceder, tipos de datos personalizados...

  Básicamente, lo que hace el framework es convertir las clases java configuradas, en bibliotecas javascript. El nombre de la biblioteca es parte de la configuración que tenemos que hacer.

  1) Incluir la biblioteca de dwr al proyecto web (dwr.jar)
     Incluir las bibliotecas commons de apache ( http://commons.apache.org/ ). Algunos servidores ya incluyen estos jars. Puedes arrancar la aplicación, y si tienes algún mensaje del tipo: java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory, agregar commons-logging.jar (y los jars necesarios, según los mensajes).

  2) Agregamos la configuración del servlet de dwr. Para esto agregamos el siguiente contenido en el archivo web.xml.

    <servlet>
     <servlet-name>dwr-invoker</servlet-name>
     <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
     <init-param>
       <param-name>debug</param-name>
       <param-value>true</param-value>
     </init-param>
    </servlet>
    <servlet-mapping>
     <servlet-name>dwr-invoker</servlet-name>
     <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

 3) En WEB-INF se crea el archivo dwr.xml.
 En el primer ejemplo, vamos a configurar una clase que llamamos: SaludoAjx (en el paquete dwrjs). En esta clase vamos a tener un método público "getSaludoSimple" que retorna un String. A esta clase, desde javascript, vamos a acceder con el nombre del objeto "SaludoJS".

     WEB-INF/dwr.xml
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
  "http://getahead.org/dwr/dwr20.dtd">
  <dwr>
    <allow>
        <create creator="new" javascript="SaludoJS">
            <param name="class"
                   value="dwrjs.SaludoAjx"/>
            <include method="getSaludoSimple" />
        </create>
    </allow>
  </dwr>

 4) Creamos la clase y el método indicado en el paso anterior (la clase SaludoAjx en el paquete dwrjs, y el método getSaludoSimple)
    Esta clase tiene que tener el constructor por defecto sin argumentos.

   dwrjs.SaludoAjx.java
package dwrjs;
public class SaludoAjx {
  public String getSaludo()
    { return "Hola Mundo con DWR"; }
  }

 Ya tenemos configurado el ambiente, ahora, a probar si está funcionando.
 Ejecutamos el proyecto, y en el navegador vamos a la url: host:puerto/proyecto/dwr
 En mi caso: http://localhost:8080/DWREjemplo/dwr/index.html

 Si todo funciona bien, se nos presenta una página con las clases conocidas por DWR, en nuestro ejemplo:
   SaludoJS (dwrjs.SaludoAjx).
   Al hacer click en el link de la clase, se muestra otra página con los métodos disponibles.

   Nota: Para tener esta pantalla de test de dwr, es necesario que esté habilitado en la configuración del serlvet ( paso 2), el parámetro "debug".

 5) Vamos a crear una página sencilla, en el cuál hay un botón que, al hacer click, nos muestra el saludo (el texto desde el server)

     index.html
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <script type='text/javascript' src='/DWREjemplo/dwr/util.js'></script>
        <script type='text/javascript' src='/DWREjemplo/dwr/engine.js'></script>
        <script type='text/javascript' src='/DWREjemplo/dwr/interface/SaludoJS.js'></script>

        <script type="text/javascript">
            function cargarSaludo(){
                SaludoJS.getSaludo(setMsgSaludo); }

            function setMsgSaludo( strRetorno){
                divTxt=dwr.util.byId("txtDinamico");
                divTxt.innerHTML=strRetorno; }
        </script>
    </head>

    <body >
        <h1>Ejemplo DWR!</h1>
        <button onclick="cargarSaludo();" >Ver Saludo</button>
        <div id="txtDinamico" />
    </body>
</html>

 Descripción de la página
  a) En la etiqueta 'button', indicamos que al hacer 'click' llame a la función de javascript "cargarSaludo()"

 Dentro de la etiqueta "head"
  b) Las primeras 2 lineas cargamos bibliotecas necesarias por dwr (y nosotros)
  c) En la tercer linea importamos nuestra propia libreria SaludoJS.js
       notar la ruta de las bibliotecas, en las propias de dwr están de la forma:
          /proyecto/dwr/biblioteca.js, y las que corresponden a nuestras clases están de
          la forma:  /proyecto/dwr/interface/biblioteca.js

  d) Creamos la función de javascript "cargarSaludo()" (ejecutado al hacer "click" desde el botón).
    En nuestro caso particular, solo tenemos una línea:
          SaludoJS.getSaludo(setMsgSaludo);
    Lo que estamos haciendo es llamar en nuestra biblioteca (SaludoJS), el método que queremos ejecutar (getSaludo), y como parámetro, lo que indicamos
 es el método que se tiene que ejecutar cuando llegue la respuesta del servidor (aquí es donde aparece la "magia" de dwr, y nos abstraemos de todos los detalles de esta comunicación).
  
    En caso de que el método en nuestra clase tenga parámetros, primero se agregan los parámetros necesarios, y por último, el nombre del método a ejecutar al retorno del servidor.

 e) Se crea el método javascript "setMsgSaludo", con un parámetro, que va a contener los datos de la respuesta del servidor.
    Cuando se obtiene la respuesta del server (pto anterior), se ejecuta automáticamente este método, y se agrega como argumento la respuesta del servidor.
    En nuestro ejemplo, lo que hacemos es, al 'div' cuyo id es "txtDinamico", le agregamos directamente la respuesta del servidor.

  Como resultado, al hacer click, tendremos bajo el botón una linea con el texto: Hola Mundo con DWR

  Dejo el paquete con el proyecto de prueba (fuentes y war) bajar ejemplo DWR
  En la página oficial tienen muy buena documentación:  http://directwebremoting.org/dwr/index.html

Leer más...

Permisos en Linux

 Manejo de permisos de archivos en linux
      Todos los archivos en linux (los directorios y dispositivos también son archivos), tienen un conjunto de permisos, que determinan qué usuarios pueden acceder a estos archivos, y qué es lo que pueden realizar.
 Los permisos que se otorgan son de lectura (r), escritura (w) y ejecución (x).

 En cada archivo, estos permisos se asignan a tres categorías de usuarios, de forma independiente. Estas categorías de usuarios son:
   Propietario (owner): Es el usuario al que pertenece el archivo. Por defecto, el usuario que crea un archivo es el propietario (puede ser cambiado).
   Grupo (group): Es un conjunto de usuarios asociados a un grupo, a los cuales se les quiere asignar permisos para el archivo.
   Otros (other): Son todos los usuarios que no pertenecen a las dos categorías previas.

 Al asignar los permisos de forma independiente, permite que el propietario tenga, por ejemplo, permiso de leer y escribir un archivo, mientras que
los miembros del grupo solo pueden leerlo, y el resto de usuarios no puedan acceder.

 Para ver la información detallada de un archivo en linux, usamos el comando "ls -l". En el siguiente ejemplo, se muestra un directorio y un archivo de texto.
   drwxr-xr-x 2 dlix lectores 4096 2010-01-10 17:55 doc
   -rw-r----- 1 dlix lectores  192 2010-01-10 17:55 log.txt

 Recorriendo el resultado de 'ls -l' de izquierda a derecha, vamos a describir las diez posiciones iniciales:

1) Tipo de archivo: El primer carácter indica el tipo de archivo. Alguno de los caracteres (y su significados) posibles son:
    "-" : representa un archivo (como un txt, html, pdf)
    "d" : indica que el archivo es un directorio.
    "l" : indica que el archivo es un enlace simbólico
    "c" : indica que es un archivo especial de caractéeres (ej.ttyS0 )
    "b" : indica que es un archivo especial de bloques (ej. sda1 )

   En el ejemplo anterior, "doc" es un directorio, y "log.txt" es un archivo de texto.

 2) Los siguientes nueve carácteres representan los permisos (rwx), agrupados por la categoría de usuario.
    Los permisos no concedidos (por ejemplo, no se tiene permiso de ejecución), se representa con un guión (-).

 2.1) El primer conjunto de tres caracteres representan los permisos que se otorga al propietario (owner) del archivo.
   
    En el ejemplo, para el directorio "doc" el propietario "dlix" tiene permiso de lectura, escritura, ejecución (rwx).
    Para el archivo "log.txt", el propietario tiene permisos de lectura y escritura (rw-). No se otorgó permiso de ejecución (-).

 2.2) El segundo conjunto de tres caracteres representan los permisos otorgados al grupo (group) del archivo.
   
    En el ejemplo, para el directorio "doc", el grupo "lectores" tienen permiso de lectura y ejecución (r-x).
    Para el archivo "log.txt", el grupo "lectores" solo tiene permiso de lectura (r--).

 2.3) El tercer y último conjunto de tres caracteres representan los permisos otorgados a la categoría de otros usuarios (others).
   
    En el ejemplo, para el directorio "doc" estos 'otros' usuarios tiene permiso de lectura y ejecución (r-x).
    Para el archivo "log.txt", estos 'otros' usuarios no tienen ningún permiso (---), por lo que no pueden realizar ninguna acción.

 3) Vamos a saltear el siguiente carácter (que representa el numero de enlaces al archivo), con lo que luego tenemos el propietario y
a continuación el grupo del archivo, en nuestro ejemplo, 'dlix' y 'lectores' respectivamente.

 Permisos en Directorios
  Como se puede ver en el ejemplo, los permisos en el directorio son los mismos que en un archivo (rwx).
  Es importante comprender el significado que estos tienen en el directorio.

  El permiso de lectura en el directorio permite ver los archivos que hay en él.
  El permiso de ejecución, permite ingresar en él ( hacer 'cd ').
  El permiso de escritura, permite crear archivos en el directorio, y eliminar los propios.

 Representación de los permisos en linux
   Los permisos pueden representar de dos formas.
   Una es mediante símbolos de permisos, como se han visto hasta ahora en este artículo: r w x (lectura, escritura, ejecución).
  Otra forma es mediante código numéricos, expresado en notación octal. Este método es muy útil en el momento de modificar permisos.
  En la representación numérica:
    4  => representa el permiso de solo lectura (r).
    2  => representa el permiso de solo escritura (w).
    1  => representa el permiso de solo ejecución (x).

  Para representar combinación de permisos, se suman los códigos que están presentes.
  Por ejemplo, si se quiere representar un archivo que tiene permisos de lectura y ejecución, mediante símbolos: r-x. Mediante código numéricos,
 simplemente sería 5 ( 4 + 1 == lectura + ejecución ). Un archivo con todos los permisos (rwx) en código numérico es 7 (4 + 2 + 1  == lectura + escritura + ejecución  ).

 Modificación de Permisos en linux: comando chmod
  El comando chmod nos permite modificar los permisos de los archivos en linux.
  Los permisos se pueden representar por sus símbolos (conocido como método relativo), o mediante la codificación numérica (conocido coo método absoluto).

 Para el método relativo (o simbólico), a los símbolos ya mencionados (rwx) se tiene que agregar la siguiente lista:
  u : Agrega o elimina un permiso al propietario del archivo.
  g : Agrega o elimina un permiso al grupo del archivo.
  o : Agrega o elimina un permiso la categoría de usuarios 'otros'. (recordamos, no es el propietario, ni pertenecen al grupo).
  a : Agrega o elimina un permiso a todas las categorías de usuarios ( ugo ).
  + : Significa que se agrega el permiso.
  - : Significa que se elimine el permiso.

 El modo de empleo es, indicar la categoría de usuario al cual se quiere asignar el permiso, el símbolo +/- (agregar/eliminar), y los símbolos de los permisos.

 Algunos ejemplos:
  De acuerdo a esto, si se quiere eliminar el permiso de escritura a todos los usuarios del archivo log.txt:
      chmod a-w log.txt
  Si se quiere dar permisos de escritura y ejecución al directorio doc, para los usuarios 'otros':
      chmod o+xw doc/
  Si se quiere dar permiso para los usuarios 'otros' de lectura, y eliminar los permisos de escritura y ejecución en el archivo log:
      chmod o+r-wx log.txt

 Para asignar permisos por medio de caracteres numéricos (método absoluto), siempre se hace referencia a las tres categorías de usuario.
 Se utilizan 3 dígitos, en donde cada dígito representa los permisos (rwx) de cada categoría.
 El primer dígito corresponde a los permisos para el propietario, el segundo para el grupo, y el tercero para otros.

 Algunos ejemplos:
  Si se ejecuta el siguiente comando:  chmod 764 log.txt
   el primer dígito asigna permisos para el propietario. El 7 significa que se dan todos los permisos (rwx == 4+2+1).
   el segundo dígito asigna permisos para el grupo. El 6 significa que se da permiso de lectura y escritura (rw == 4+2).
   el tercer dígito asigna permisos para otros. El 4 significa que se da permiso de lectura (r == 4).
  Si hacemos ahora: ls -l log.txt  obtenemos:  -rwxrw-r-- 1 dlix lectura 0 2010-01-10 00:30 log.txt

 Que método usar depende de la situación, y en particular, lo que sea más cómodo de forma personal.
 Cuando se tiene que modificar los permisos de todos los grupos, el método absoluto resultaría el más cómodo. Cuando tengo que cambiar un permiso concreto para
una de las categorías de usuario, el método simbólico resulta más intuitivo.

 Aplicar modificación de permisos de forma recursiva.
   Cuando se quiere realizar cualquier modificación de permisos (como vimos en los ejemplos anteriores), de forma recursiva a todos los archivos y directorios, se usa la opción "-R".

  Por ejemplo, para dar todos los permisos al propietario, permiso de lectura y ejecución al grupo, y ningún permiso a otros, para todos los directorios y archivos dentro del directorio doc, se puede hacer mediante:
  chmod -R 750 doc  ==> Resultado:  drwxr-x---  (para el directorio doc, y todos sus subdirectorios y archivos)


Leer más...

Expresiones Regulares - Metacaracteres

 Expresiones Regulares

   Una expresión regular es un conjunto de caracteres que se lo conoce como "patrón". Por medio de aplicaciones que soporten expresiones regulares, es posible buscar o sustituir estos patrones dentro de un texto, evitando tener que escribir código específico para esa tarea.
   Si bien las expresiones regulares son una herramienta muy potente para la manipulación de texto, puede dificultar el mantenimiento y/o localización de errores, cuando se generan patrones complejos. En estos casos, la clásica recomendación ... documentar.
   Un ejemplo de patrón que suele estar en los textos que tocan el tema, es la búsqueda de un archivo desde linea de comando, por ejemplo:
     ls m*.txt  ( o en DOS:  dir m*.txt)  :  este patrón busca todos los archivos que comienzan con la letra "m", continúan con cualquier carácter, y terminan con ".txt".

 Metacaracteres en expresiones regulares:
   Algunos caracteres en una expresión regular tienen un comportamiento específico. A estos caracteres se los conoce como "metacaracteres". En la siguiente lista, se explica algunos de estos importantes caracteres, que usaremos en diferentes ejemplos:

Operador Descripción Ejemplo
\ Es el carácter de escape. Modifica el comportamiento "normal" del carácter que le sigue. Por ejemplo, si se quiere buscar el propio carácter "\", se tiene que hacer por medio de "\\"
^ Indica una coincidencia al comienzo de la cadena (ver diferencia cuando se usa con parentesis rectos) ^Linux Indica que comienza con la frase "Linux"
$ Indica una coincidencia al final de la cadena. Ubuntu$ Indica que termina con la frase "Ubuntu"
. Usado cuando se quiere representar cualquier carácter (sin incluir el salto de linea '\n').
| Funciona como el "OR" para las expresiones regulares. Coincide con la expresión en un lado u otro del carácter "|" Por ejemplo, lin(ux|terna) coincide con linux y linterna (luego veremos el metacarácter "(...)"
[ ] Se busca coincidencia con cualquier carácter incluido dentro de los paréntesis rectos. EN "Linu[xsr]" hay coincidencia con: Linux Linur Linus
[ - ] El "-" se usa para indicar un intervalo de caracteres [a-z] representa cualquier carácter alfabético en minúscula. [2-4] representa cualquier dígito entre 2 y 4.
doc[2-4] coincide con doc2 doc3 doc4
[^ ] Con "[^" se indica "clase exclusiva" o negativo. Se usa cuando el patrón de búsqueda coincide con cualquier carácter, EXCEPTO éstos. En doc[^24], NO coincide con doc4 o doc2, sí con doc3, docu . También usado con intervalos de caracteres
( ) Representa un grupo de caracteres que son tratados como una única expresión En doc(24|umentos), Coincide con doc24 y documentos (Ver que se uso el carácter "|" en el ejemplo)
Representación de caracteres que se repiten
* Indica que la expresión anterior al carácter puede repetirce cero o más veces. "ub*" indica que el carácter "b" puede no existir, por lo que va a coincidir la expresión con todas las 'u',
y si existe, coincide con todas las repeticiones de 'b' luego de una 'u'. Por lo que va a coincidir con:
ubuntu, ubbbuntu incluso solo con ucualquierCosa
+ Indica que la expresión anterior al carácter se repite una o más veces. "li+" coincide con linux , con liinux , pero no "lalgo" o "l" (tiene que estar el carácter 'i')
? Indica que la expresión anterior a éste símbolo es opcional, por lo que puede estar una sola vez, o ninguna "Linux?" coincide con Linux o con Linu
{N} Indica que se encuentra coincidencia cuando la expresión anterior se repite N veces. x{2} coincide con xx. Si indicamos sustituir x{2} por Z, en xxxx por defecto, el resultado será ZZ
{N,} Indica que se encuentra coincidencia cuando se repite como mínimo N veces (sin máximo). x{2,} coincide con xx (y todas las x que estén luego). Si indicamos sustituir x{2,} por Z, en xxxx por defecto el resultado será Z
{N,M} Indica que la expresión anterior se repite como mínimo N veces, y no más de M veces. x{2,3} coincide con xx y con xxx.
Notas: En estos casos, si N es el único valor, N >=1. En el resto de los casos, N >= 0, y si se usa M, N <= M
<patronRepetición>? Si se agrega ? luego de alguno de los cuantificadores anteriores " *, +, ?, {N}, {N,}, {N,M})", se genera una versión "lazy".
Lo que hace es coincidir con la mínima expresión posible. Este concepto es importante y suele generar confusiones con el comportamiento por defecto,
en donde la coincidencias se expanden a la mayor expresión posible.
Si en: "<b>asljlj</b> <b>tarja</b>" queremos reemplazar todo el texto que hay dentro de los
tags "<b>...</b>" por ZZ, tenemos que usar este modo "lazy", la solución sería:
"<b>.*?</b>", de esta forma coincide con el texto dentro de cada bloque, y tendríamos:
"<b>ZZ</b> <b>ZZ</b>".
Si no se usa el modo lazy ("<b>.*</b>") el comportamiento seria modificar TODO el texto desde el primer tag
"<b>" (incluso otros tags <b> y </b>) hasta llegar al último tag "</b>", con el resultado:
"<b>ZZ</b>"
A continuación un grupo de metacaracteres que representan un "atajo" en representación de patrones.
 \w   Representa a cualquier carácter alfanumérico, incluyendo el guión bajo. Equivale a [a-zA-Z0-9_]'.
 \W  Representa a cualquier carácter que no sea alfanumérico. Equivale a [^a-zA-Z0-9_] .
 \d Representa cualquier dígito. Equivale a [0-9]. doc\d es igual a doc\d
 \D Reprecenta a cualquier carácter que NO sea un dígito. Equivale a [^0-9].
 \s Coincide con cualquier carácter que represente espacio en blanco, incluido nueva línea. Equivale a [^ \n\r\f\t\v].
 \S  Representa a cualquier carácter excepto aquellos que sean espacio en blanco. Equivale a [^ \n\r\f\t\v].
Algunos caracteres de texto no imprimibles
  \n   Representa el carácter de nueva línea.
\r Representa el carácter de retorno de carro.
\t Representa el carácter de tabulación.
\v Representa el carácter de tabulación vertical.
\f Representa un salto de página.


Muchos lenguajes y programas soportan expresiones regulares, como ser java, oracle, .net, perl, entre muchos otros, con sus particularidades. Hemos visto algo en los artículos dedicados a grep y el editor vi. En próximos post veremos algunas herramientas que nos faciliten la creación y pruebas de nuestras expresiones regulares, y el uso en java.
Leer más...

Conocer la Distribucion de linux

 Cómo saber la distribución de linux instalada ?

 En ocasiones, es necesario conocer información sobre la distribución de linux que se tiene instalada, no solo la versión del kernel.
 Muchas veces me han preguntado en el trabajo como saber la versión de ubuntu, y normalmente no lo recuerdo (mi respuesta inmediata es uname -a ... pero no es lo que necesitan).

 Para tenerlo presente la próxima vez que me consulten, y tal vez, para que sea de utilidad a otros, dejo varias formas posibles por las que se puede obtener esta información.

 1) lsb_release -a
Leer más...

Comando grep

 Comando grep en GNU / Linux

 El comando grep permite buscar un patrón de texto en un archivo (o en la entrada estándar cuando no se indica un nombre de archivo), línea por línea.
 Por defecto, grep imprime en la salida estándar (en la consola) las líneas que contienen el patrón buscado.

 La sintaxis del comando (ver el man de grep), es:

     grep [OPCIONES] PATRON [ARCHIVO...]
     grep [OPCIONES] [-e PATRON | -f ARCHIVO] [ARCHIVO...]

 Este comando tiene versiones para varios sistemas, y las diferentes versiones pueden variar sutilmente, en particular algunas opciones.
 Para las diferentes pruebas en este artículo, se usa GNU grep, y se probo en la distribución de linux Ubuntu .

 Buscar un texto / palabra dentro de un archivo.
  En su forma más simple, para buscar una palabra en un archivos hacemos:
Leer más...

El editor vi

 Vi es el editor de texto más común en equipos con linux / unix. Hasta el momento, no he encontrado un equipo con alguno de estos sistemas operativos, que al teclear "vi" en la linea de comando, tenga la desagradable respuesta de "orden no encontrada".
 Por esto es importante tener algunos conocimientos básicos de esta maravillosa herramienta. Si bien forma parte en todo curso de linux, pienso que hay que conocerlo, aunque no se trabaje directamente sobre sistemas unix* (todavía no has tenido que conectarte por ssh a un server de producción, y modificar un html, jsp, css o cualquier archivo de configuración ? es cuestión de tiempo :-) )

 Antes de ingresar al fantástico mundo de vi con ejemplos, algunos conceptos previos que son importantes.
Leer más...

Validar datos de formulario con Spring mvc

 Continuando con los ejemplos de spring mvc, al formulario del artículo anterior (Formulario con Spring MVC) le agregamos validación de los datos.

  1) Para esto agregamos un campo adicional en el formulario (la edad del usuario), para validar un entero como ejemplo, por lo que incluimos en la página usuario.jsp la siguiente línea:
    Edad: <form:input path="edad"/>

  2) En la clase que se mantiene los datos del formulario, test.bean.Usuario.java, se tiene que incluir el atributo "edad", con el get/set correspondiente.

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


  3) Creamos una nueva clase, que será la encargada de la validación de los campos del formulario. Se tiene que implementar la interface Validator (org.springframework.validation.Validator), junto con los métodos 'supports' y 'validate'.

 Usamos ValidationUtils.rejectIfEmptyOrWhitespace, que verifica que el campo que indicamos (segundo parámetro, por ejemplo "nombre") no este vacío, ni contenga solo espacios en blanco.
 Si se cumple la condición, genera un error con un código (tercer parámetro, por ejemplo 'error.usuario.nombre', el cuál se busca en el archivo de resource bundle configurado (si se hizo), para desplegar el texto que corresponda con ese código.
 En caso de no encontrar el código, se muestra el mensaje por defecto (cuarto parámetro, por ejemplo 'Error en nombre').

test.bean.validator.UsuarioValidator.java
   package test.bean.validator;
   import org.springframework.validation.Errors;
   import org.springframework.validation.ValidationUtils;
   import org.springframework.validation.Validator;
   import test.bean.Usuario;
     /** @author dlix */
   public class UsuarioValidator implements Validator {
     public boolean supports(Class type) {
       return Usuario.class.isAssignableFrom(type);
     }
     public void validate(Object command, Errors errors) {
       Usuario form = (Usuario) command;
       ValidationUtils.rejectIfEmptyOrWhitespace(errors, "nombre", "error.usuario.nombre", "Error en nombre");
       ValidationUtils.rejectIfEmptyOrWhitespace(errors, "apellido", "error.usuario.apellido", "Error en apellido");

      validateEdad(form.getEdad(), errors);
      validateApellido(form.getApellido(), errors);
   }
      // tiene que ser mayor de 18
   private void validateEdad(int edad, Errors errors) {
       if( edad < 18){ errors.rejectValue("edad", "error.usuario.edad", "Error en  edad"); } }

      // El apellido solo puede tener letras 
   private void    validateApellido(String apellido, Errors errors) {
      if (!apellido.trim().matches("[a-zA-Z]*") ) {
           errors.reject("error.usuario.apellido.nomatches", 
               "El apellido solo tiene  que tener letras"); } } 
}

 4) Se le tiene que indicar al framework, la clase encargada de validar el formulario.
  Una de las formas de hacer esto, es en la configuración del Dispatcher Servlet. En el archivo dispatcher-servlet.xml, en el bloque donde se configuró el controlador (<bean id="usuController" ...), se agrega:
   <property name="validator">
     <bean class="test.bean.validator.UsuarioValidator"/>
   </property>


 5) Se tiene que modificar la página nuevamente, en esta oportunidad para mostrar los mensajes de error.
  Para esto tenemos varias posibilidades, según la forma que se quiera desplegar los mensajes al usuario.
 En la página tenemos que tener el taglibs 'core' <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>, y recordamos que ya tenemos el 'form' de spring (<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" % > )

  Los errores pueden representar un campo del formulario (al validar, cuando se indica, por ejemplo, errors.rejectValue("edad", ...) ).
  En este caso, podemos ver el error mediante: <form:errors path="edad" />. Con la propiedad 'path' se indica el campo del formularo que representa el error.

  Pueden haber errores que no representen un campo en particular, por ejemplo, al validar, errors.reject("error.usuario.apellido.nomatches",...).
  En la página podemos desplegar todos estos errores mediante: <form:errors />

  Con <form:errors path="*"> estamos indicando todos los errores ('path=*' matchea con todos los valores), y de esta forma podemos reccorrer todos los mensajes (en la variable 'messages') de error, de la siguiente forma:

  <form:errors path="*">
     <c:forEach items="${messages}" var="message">
        <c:out value="${message}"/><br />
     </c:forEach>
  </form:errors>


 En este momento podemos ejecutar la aplicación, y verificar que se realizan las validaciones correctamente.

 Si en el campo de 'edad', que corresponde a un entero, ingresamos un valor que no puede ser convertido a Integer, en la página se desplega el error:
'Failed to convert property value of type [java.lang.String] to required type [int] for property 'edad'; nested exception is java.lang.NumberFormatException: For input string: "5AA"

 Por último configuramos ResourceBundleMessageSource, para tener fuera del código los mensajes de error, y agregar un mensaje amigable al usuario, para la exception de NumberFormatException.

 6) Configuración de mensajes.
  6.1) Se crea dentro del paquete "test.resource" (obviamente, puede tener la ruta y nombre de nuestra preferencia), el archivo "messages.properties" en donde se va a ingresar los mensajes de error a desplegar en la página.

     messages.properties
  error.usuario.nombre=Se tiene que ingresar nombre valido.
  error.usuario.apellido=Se tiene que ingresar apellido valido.
  error.usuario.edad=Se tiene que ingresar edad.
  error.usuario.apellido.nomatches=El apellido solo puede contener letras, sin espacios.
  typeMismatch.usuario.edad=Edad solo puede tener Nros. enteros.


 Nota: con typeMismatch contolamos el mensaje del error NumberFOrmatException

 Se puede agregar caracteres especiales en el texto. Por ejemplo, si tienes que incluir tildes y eñes, agrega estos caracteres con su código unicode.
 Los códigos unicode para tildes y eñes se pueden obtener en el articulo Caracteres Html y Unicode en español.
 Por ejemplo, se pudo haber indicado el siguiente error:
  "error.usuario.edad=N\u00famero inv\u00e1lido para edad." para indicar :"Número inválido ..."

  6.2) Se modifica 'dispatcher-servlet.xml' para configurar el archivo que contiene los mensajes, agregando el siguiente bloque:

  <bean id="messageSource"   class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename">
       <value>test.resource.messages</value>
    </property>
  </bean>


Al ejecutar la aplicación con estos nuevos cambios, y generar los errores, podemos ver los diferentes textos que que incluimos en el archivo "messages.properties", en lugar de los mensajes por defecto "hardcodeados" en el código.

(El proyecto TestSpring para descargar fuentes y .war)

Leer más...

Formulario con Spring MVC

 Vamos a modificar el proyecto anterior con spring mvc (Implementar Spring MVC) para incluir un formulario de ejemplo.
 Para esta tarea, vamos a crear nuestra propia clase que actúa como controller, que hereda de SimpleFormController. Usamos dos páginas (vistas), una encargada de mostrar el formulario, y otra para los resultados.

1) Primero modificar el archivo de configuración del servlet que funciona como Front Controller ( Dispatcher Servlet), en nuestro proyecto, el archivo: dispatcher-servlet.xml

1.1) Lo primero que indicamos en la configuración del 'Handler Mapping', cuál es la url del formulario, y el nombre del controlador responsable de manejar esa url. Para esto, se agrega la siguiente línea: <prop key="usuario.htm">usuController</prop>
 Básicamente, lo que estamos indicando en esta línea es: Las consultas a la url 'usuario.htm' redirigir al Controller con nombre: 'usuController'.

EL bloque completo de la configuración del HandlerMapping :
<bean id="urlMapping"  
 class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
   <property name="mappings">
      <props>
         <prop key="index.htm">indexController</prop>
        <prop key="usuario.htm">usuController</prop>
      </props>
   </property>
</bean>

Leer más...

Implementar Spring MVC

 La idea es dar una presentación sencilla de Spring MVC (usamos Spring MVC 2.5), y poder avanzar en ejemplos posteriores.

 Spring MVC es un framework open source que forma parte de Spring Framework. Provee una implementación del patrón Model View Controller (MVC - modelo vista controlador) en java.
 Al ser parte de Spring Framework, es posible utilizar fácilmente las ventajas que éste nos aporta, como ser la Inyección de Dependencia.
 La Inyección de Dependencia hace posible que el framework se encargue del trabajo de incluir las dependencias necesarias por la aplicación, eliminando de las clases la creación de objetos.

 Una explicación muy breve y generalizada del funcionamiento de spring mvc sería:
=> todas las peticiones de los usuarios/clientes pasan por un servlet (Front Controller - Dispatcher Servlet), cuyo comportamiento se configura en un archivo xml. Este servlet envía el request a ser procesado por un 'Controller', el cual encapsula los datos resultantes (Model), y por último se muestran los resultados en una 'vista' (View, la cual puede ser una página, un documento pdf, etc).

 En Spring MVC, la responsabilidad para el manejo de los request realizados por los usuarios, se delegan a controladores (Controllers).
 Se tiene que configurar (mapear) de alguna forma, a qué controlador se envía un request en particular. El encargado de manejar esta tarea es un servlet que funciona como Front Controller, al que se le da el nombre de 'Dispatcher Servlet'.
 Este mapeo entre request y controller se configura mediante el Handler Mapping.
 Spring nos provee de varios Handler Mapping entre los que podemos seleccionar, dependiendo como indicamos el controlador a usar (ej. SimpleUrlHandlerMapping, BeanNameUrlHandlerMapping). Es posible configurar varios de estos tipos de Handler Mapping en la misma aplicación, indicando el orden de preferencia (se usa la propiedad 'order', ej: <property name="order"> <value>1</value> </property> ).

 Las clases que se implementen para realizar la tarea de controlador, tienen que heredar de alguna de las clases Controller que dispone Spring. Estos Controller disponibles, nos facilitan la tarea para diferentes funcionalidades, como pueden ser, un controller orientado a mostrar datos (View Controller), un controller que nos facilita el trabajo con formularios (Form Controller), uno que nos permite el manejo de varias pantallas (Wizard Controller), etc.
 Esta clase no es responsable (directamente) de mostrar en algún medio el resultado. De esto se encarga un tipo de clase 'View'.

 Como parte de la lógica del controller, se puede tener como resultado un grupo de datos que representen la respuesta y que se tendrán que mostrar de alguna forma. Estos datos son conocidos como 'Model'.
 Una vez que el contoller implementado realiza la lógica requerida, se tiene que pasar estos datos a una 'vista' (View), que será lo siguiente a ver por el usuario, donde se mostrará los datos (Model) de la consulta.
 En el Controller se encapsula en una clase de tipo ModelAndView, la combinación del los objetos Model y el objeto View.
 Para mantener un bajo acoplamiento, el Model es un Map de objetos, y normalmente el View se indica por medio de un nombre lógico.

Comenzando con un ejemplo
----------------------------
 A continuación vamos a realizar un ejemplo práctico para ver la configuración de las diferentes partes de spring mvc. Para esto voy a usar el ide NetBeans (http://netbeans.org/), el cuál es sumamente sencillo de instalar, y trae todo lo necesario para las tareas a realizar aquí.
 Es posible usar el ide que cada uno prefiera, incluso es suficiente con tener ant, las bibliotecas necesarias ( http://www.springsource.org/download), y un editor de texto como 'vi', 'emacs', etc. Si tu elección es ant + vi ... vas a tener una tarde un poco más divertida :-)

A 'picar' código ;-)
1) Lo primero es tener un proyecto web.
 Si estamos comenzando con el proyecto, desde NetBeans seleccionamos "nuevo proyecto", en la ventana que se despliega, buscamos en la categoría de proyectos "java web", y en seleccionamos la opción "aplicación web".
 Se completa los pasos siguientes, como ser, dar un nombre y ubicación física al proyecto, seleccionar el server a usar (en mi caso Apache Tomcat 6.0.20), y la versión de java (en mi caso, Java EE 5).
 Por último podemos seleccionar el/los frameworks a incluir en el proyecto. Seleccionamos "Spring Web MVC 2.5", finalizando la creación del proyecto.
Se deja la configuración por defecto que ofrece NetBeans para el nombre del servlet dispatcher ('dispatcher'), y mapping ( *.htm).

1.2) En caso tener un proyecto web en el que queremos agregar el Spring MVC , seleccionamos "propiedades" en el proyecto. En la ventana de propiedades seleccionamos la opción de "Frameworks" -> "Agregar ...", y "Spring Web MVC 2.5" (tener en cuenta que se va a modificar el proyecto, y se agrega configuración el el archivo web.xml.

2) Una vista de la estructura del proyecto.
 Lo que obtenemos al terminar nuestra creación / configuración del proyecto web + spring con NetBeans es una estructura, con los archivos y configuración mínima que necesitamos
 -imagen estructura directorios-

Configuración de web.xml
-----------------------------------------------
 En el archivo WEB-INF/web.xml se declara el nombre del servlet que funciona como Dispatcher (o Front Controller), en este caso 'dispatcher', y se configura
el mapeo de las url's a este servlet.

web.xml (fragmento de la configuración usada para spring-mvc)
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
    <listener-class> 
       org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>
       org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.htm</url-pattern>
</servlet-mapping>

 Otra sección importante que podemos ver aquí es el 'contexto de la aplicación', configurado por medio del listener-class 'ContextLoaderListener', y el nombre del archivo a usar -applicationContext.xml-. Aquí se configura, por ejemplo, la inyección de dependencias.

Dispatcher Servlet
-------------------
 Se tiene que crear (en nuestro caso lo hizo NetBeans) el archivo WEB-INF/dispatcher-servlet.xml. El nombre de este archivo esta determinado por el dado en <servlet-name> en el archivo web.xml, seguido de '-servlet'.
 En este archivo configuramos lo necesario por 'dipatcher servlet'. Veamos lo que agrego netbeans en este archivo.

<?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

 <bean id="urlMapping"   class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
 <property name="mappings">
    <props>
        <prop key="index.htm">indexController</prop>
    </props>
 </property>
</bean>

<bean id="viewResolver"     class="org.springframework.web.servlet.view.InternalResourceViewResolver"
     p:prefix="/WEB-INF/jsp/"
     p:suffix=".jsp" />
   <!-- The index controller. -->

<bean name="indexController"    class="org.springframework.web.servlet.mvc.ParameterizableViewController"
    p:viewName="index" />
 </beans>

 Primero se define el manejo del mapeo request con controller. Se usa SimpleUrlHandlerMapping, y se indica que el request a "index.html" se delega al controller con nombre 'indexController'.

 Luego se declara el 'viewResolver', esto es una forma de realizar un mapeo entre vistas (view) y el nombre lógico dado a estas vistas. En el ejemplo, se usa InternalResourceViewResolver. Indicamos el directorio donde se almacenan las vistas por medio de la propiedad 'prefix'. En nuestro proyecto, las vistas (las páginas) están en el directorio '/WEB-INF/jsp' ( p:prefix"/WEB-INF/jsp/" o <property name="prefix" value="/WEB-INF/jsp/" /> ).
 Se indica el tipo de vistas que se usan para mostrarcon la propiedad 'p:suffix', como ser paginas jsp's (p:suffix=".jsp").

 Por último se definió la implementación del controlador. En 'bean name' se indica el nombre del controlador, el cual es igual al usado en la propiedad 'mappings' en el HandlerMapping al comienzo del archivo. Luego se tiene que indicar la clase concreta que implementa el controller.
 Dado que solo vamos a mostrar un mensaje en una página, sin realizar ninguna lógica, se define un controller de spring usado cuando solo se quiere mostrar información: 'ParameterizableViewController'. La vista a la que se tiene que retornar el modelo (model) es 'index' (p:viewName="index").

=> "Traduciendo" esta simple configuración, lo que se dice es: Los request a index.htm, pasarlos al controlador indexController, cuya clase que implementa este controlador es ParameterizableViewController, y retornar el resultado a la pagina "index.jsp", que se encuentra en el directorio /WEB-INF/jsp/ .

Creación del View ( la página index.jsp)
----------------------------------------
 Se tiene que crear la página index.jsp, dentro del directorio /WEB-INF/jsp/ , la cual será mostrada al consultar por index.htm. Si bien netbeans nos ha ahorrado esta tarea, vamos a ingresar un texto mas breve, como ser: "Hola Spring!!"

WEB-INF/jsp/index.jsp
 <%@page contentType="text/html" pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
      "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     <title>Welcome to Spring Web MVC project</title>
  </head>
  <body>
      <p>Hola Spring!</p>
  </body>
</html>

 Con lo realizado hasta aquí, ya podemos ejecutar la aplicación web, y ver el resultado al teclear en el navegador 'index.htm', en mi caso: http://localhost:8080/TestSpring/index.htm.
 Si el proyecto se ha realizado desde netbeans, tenemos un archivo extra. En la raíz de la aplicación ('Web Pages' en el ide), se creó una página redirect.jsp, la cual solo redirecciona a la url: index.htm
   <%@page contentType="text/html" pageEncoding="UTF-8"%>
   <% response.sendRedirect("index.htm"); %>
y es configurada como página de inicio en web.xml
   <welcome-file-list>
      <welcome-file>redirect.jsp</welcome-file>
   </welcome-file-list>
De esta forma en el navegador solo hacemos: http://localhost:8080/TestSpring

 En el próximo articulo (Formulario con Spring MVC), vamos a modificar un poco el ejemplo, para armar un formulario con validación.
 En este otro artículo (Validar datos de formulario con Spring mvc ), el código con el ejemplo disponible para bajar.

 La documentación de spring es muy completa
http://static.springsource.org/spring/docs/2.5.x/reference
y la pagina de spring downloads : http://www.springsource.org/download
Leer más...

Filtros en jsp y servlets

 Los filtros - filters - en una aplicación web, nos permiten interceptar el request antes de que éste llegue al servlet o jsp correspondiente, y también nos permite interceptar el response del servlet o jsp antes de que llegue al cliente.

  -------------------     request      -----------                   -----------------
 |    Cliente        |  ------------->  | FILTRO |   -------->  | Contenedor  |
 |    Navegador  | <-------------- |              | <--------   | jsp servlet    |
  ------------------      response    ------------                 -----------------

 Los filtros pueden estar encadenados. Para un request dado pueden ejecutarse más de un filtro. FILTRO_1 --> FILTRO_2 --> FILTRO_n --> CONTENEDOR

 Los filtros tienen que declararse en el Deployment Descriptor (el archivo web.xml). En este lugar se indica el/los filtros a ejecutar para un request, y el orden.

 La clase donde creamos el filtro tiene que implementar la interface Filter, e implementar tres métodos de esta interface, siendo "doFilter()" el que contiene  la lógica principal, y es llamado cada vez que se ejecuta el filtro.
 Dentro de este método, cuando se quiere ejecutar el siguiente filtro, se invoca a "doFilter" del objeto FilterChain (es uno de los parámetros de doFilter), si no hay más filtros, entonces el request llega al servlet/jsp invocado (si ninguno de los filtros interrumpió el proceso).

 Los otros dos métodos que se tiene que implementar son "init()" (se ejecuta una vez al iniciar el filtro por el contenedor), y "destroy()" (se ejecuta una vez, cuando se destruye el filtro).

 A continuación, un ejemplo simple para ver el funcionamiento de los Filtros, que imprime una línea en la salida estándar.

==> Primero, la clase que implementa el filtro.
FiltroEjemplo.jsp
  package filtros;
import java.io.IOException;
import java.util.Date;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/* Se tiene que implementar Filter */
public class FiltroEjemplo implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
throws IOException, ServletException {

 /* El codigo antes de llamar a chain.doFilter() se ejecuta antes de enviar el
   request al servlet o jsp correspondiente */

        HttpServletRequest reqst = (HttpServletRequest) request;
        System.out.println("Antes de doFilter(): " + new Date() + " - " + getClass().getName() + " "
                + reqst.getRequestURL());

        chain.doFilter(request, response);

 /* El codigo luego de chain.doFilter() se ejecuta después de la respuesta del servlet o jsp,
   y antes de llegar al cliente */
        System.out.println("Luego de doFilter(): " + new Date() + " - " + getClass().getName() + " "
                + reqst.getRequestURL());
    }

    public void destroy() {
    }
    public void init(FilterConfig filterConfig) {
    }
}

==> Se declara el filtro en el archivo web.xml
 web.xml 

<?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">
    <filter>
        <filter-name>filtro1</filter-name>
        <filter-class>filtros.FiltroEjemplo</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filtro1</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>SrvltFiltroTst</servlet-name>
        <servlet-class>servlet.SrvltFiltroTst</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SrvltFiltroTst</servlet-name>
        <url-pattern>/SrvltFiltroTst</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

 Los dos elementos usados para declarar el filtro son: filter y filter-mapping

 En el elemento 'filter' se tiene que indicar el nombre del filtro con filter-name (cualquier nombre válido),
y la clase (nombre totalmente cualificado de la clase) que implementa el filtro.
     <filter>
        <filter-name>filtro1</filter-name>
        <filter-class>filtros.FiltroEjemplo</filter-class>
    </filter>

 Una vez que se le dio el nombre al filtro, se tiene que indicar cuando se ejecuta. Para esto usamos filter-mapping, en donde se tiene que indicar el nombre del filtro que estamos 'mapeando' con filter-name, y luego tenemos dos opciones, asociar el filtro con un patrón url con url-pattern, de esta forma es posible asociar el filtro con paginas, grupos de servlets, etc.
  En nuestro ejemplo usamos el patron "/*", por lo que se ejecuta el filtro toda vez que se invoca la aplicación ya que se mapea con cualquier url ingresada, (por ejemplo, se ejecuta el filtro al ingresar url's del tipo: /index.jsp  /reportes/nuevo.jsp   /SrvltFiltroTst )
    <filter-mapping>
        <filter-name>filtro1</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 También es posible asociar el filtro con un servlet específico usando el elemento servlet-name.
 Para el web.xml indicado anteriormente, se podría escribir el filter-mapping de la siguiente forma:
    <filter-mapping>
        <filter-name>filtro1</filter-name>
       
<servlet-name>SrvltFiltroTst</servlet-name>
    </filter-mapping>
 En este caso, solo se ejecuta el filtro al invocar el servlet "SrvltFiltroTst".

 Al ejecutar la aplicación web con el filtro y configuración anterior (también imprimiendo una línea de el servlet y la pagina usada para la prueba), podemos ver en la salida estándar:

 Antes de doFilter(): Fri Jul 10 23:09:36 UYT 2009 - filtros.FiltroEjemplo http://localhost:8084/FiltroTestBlog/SrvltFiltroTst
  Fri Jul 10 23:09:36 UYT 2009 - servlet.SrvltFiltroTst
  Fri Jul 10 23:09:36 UYT 2009 - org.apache.jsp.index_jsp
 Luego de doFilter(): Fri Jul 10 23:09:36 UYT 2009 - filtros.FiltroEjemplo http://localhost:8084/FiltroTestBlog/SrvltFiltroTst

 Con este sencillo ejemplo podemos comprobar el proceso normal que se menciono al comienzo: cliente -> filtro -> jsp/servlet ->filtro ->cliente

Orden de ejecución de filtros en cadena.
  Cuando un request concuerda con varios filter-mapping, todos los filtros se ejecutan en un orden dado, según la siguiente regla.
 1) Todos los filtros que concuerden con el url-pattern , son colocados al comienzo de la cadena, y en el orden como fueron declarados en el archivo web.xml.
2) Luego se agregan a la cadena los filtros que concuerden con servlet-name , en el orden como fueron declarados.


 En otra oportunidad vamos a dar algún ejemplo más complejo, y ver la opción del elemento 'dispatcher' dentro de filter-mapping

 un recurso para ver más sobre este tema:  http://java.sun.com/products/servlet/Filters.html
Leer más...

Caracteres Html y Unicode en español

 El siguiente listado son algunos de los caracteres especiales en español, y sus equivalentes unicode y equivalente por nombre y por valor numérico, que normalmente podemos necesitar al estar escribiendo una página web (html, xml, javascript ...).
 El objetivo es poder tenerlos juntos, para evitar estar buscando en un libro o la web cada vez que no recuerdo alguno de ellos ( ... siempre).
 Si alguien ve necesario / útil que agregue algún otro carácter, me lo hace saber y lo incluyo a la lista.
 Espero sea de utilidad, esta es la lista de caracteres:

Símbolo Numérico Nombre Unicode Descripción
" &#034; &quot; \u0022 Comillas dobles
$ &#036; \u0024 Símbolo Dolar/Peso
& &#038; &amp; \u0026 Ampersand
' &#039; &apos; \u0027 Apóstrofe
( &#040; \u0028 Paréntisis izquierdo
) &#041; \u0029 Paréntisis derecho
< &#060; &lt; \u003C Menor que
> &#062; &gt; \u003E Mayor que
@ &#064; \u0040 Arroba
&#128; &euro; \u20AC Euro
&#153; \u0099 Trademark (n.e)
&#160 &nbsp; \u0020 Espacio en blanco
© &#169; &copy; \u00A9 Copyright
® &#174; &reg; \u00AE Marca registrada
½ &#189; &frac12; \u00BD Fracción un medio
Á &#193; &Aacute; \u00C1 A mayúscula, acento agudo
É &#201; &Eacute; \u00C9 E mayúscula, acento agudo
Í &#205; &Iacute; \u00CD I mayúscula, acento agudo
Ñ &#209; &Ntilde; \u00D1 N mayúscula tilde (eñe mayúscula)
Ó &#211; &Oacute; \u00D3 O mayúscula, acento agudo
Ú &#218; &Uacute; \u00DA U mayúscula, acento agudo
Ü &#220; &Uuml; \u00DC U mayúscula, diéresis
á &#225; &aacute; \u00E1 a minúscula, acento agudo
é &#233; &eacute; \u00E9 e minúscula, acento agudo
í &#237; &iacute; \u00ED i minúscula, acento agudo
ñ &#241; &ntilde; \u00F1 n minúscula tilde, (eñe)
ó &#243; &oacute; \u00F3 o minúscula, acento agudo
ú &#250; &uacute; \u00FA u minúscula, acento agudo
ü &#252; &uuml; \u00FC u minúscula, diéresis
Leer más...

linux: ubuntu APT y DPKG, algunos comandos útiles

 apt y dpkg son dos de las herramientas que podemos usar en sistemas linux basados en debian (como ubuntu) para la administración del software.

 apt (ej, apt-get) se usa para bajar e instalar paquetes desde repositorios online (en la wikipedia: http://en.wikipedia.org/wiki/Advanced_Packaging_Tool)
 dpkg se usa con archivos .deb, configurar, instalar y obtener información del software instalado(en la wikipedia: http://en.wikipedia.org/wiki/Dpkg)

Usando APT 
------------------

 Los repositorios a los que se accede cuando usamos apt, se listan en el archivo: /etc/apt/sources.list
 Si necesitamos instalar un paquete desde un repositorio que no se encuentra en sources.list, tenemos que incluir este nuevo repositorio en la lista, editando sources.list, y agregando la ruta del repositorio. Luego es necesario bajar la clave de autenticación para los paquetes de ese repositorio, y agregarlo a nuestra lista de confianza: "sudo apt-key add nombreArchivo.pub" (donde: nombreArchivo.pub es el archivo con la clave de autenticación que bajamos).
 Por último, se actualiza la base de datos de paquetes mediante: "sudo apt-get update".

 Para buscar una aplicación a instalar, podemos usar: apt-cache search, por ejemplo:

  apt-cache search openvpn
   ebox-openvpn - eBox - OpenVPN server module
   network-manager-openvpn - network management framework (OpenVPN plugin)
   openvpn - Virtual Private Network daemon
   ...

 Para saber las dependencias de un paquete con apt.
  ej: apt-cache depends ebox-openvpn

 Para instalar un paquete con apt, usamos apt-get install
  ej: sudo apt-get install ebox-openvpn
 Si el paquete ya esta instalado en el sistema, se actualiza a la ultima versión encontrada.

 Para eliminar un paquete con apt, usamos 'remove'
  sudo apt-get remove ebox-openvpn

Usando dpkg.
------------------

 Usamos dkpg para manejar paquetes bajados previamente.
 Para extraer los archivos dentro de un archivo .deb con dpkg:
    sudo dpkg -x <archivo.deb>  <directorio_destino>

 Para instalar un paquete con dpkg, usamos la opción '-i'
    sudo dpkg -i <archivo.deb>

 Eliminar un paquete con dpkg, usamos la opción -P para eliminar el paquete y sus archivos de configuración.
    sudo dpkg -P <archivo.deb>
 o usamos la opción -r para eliminar solo el paquete.
    sudo dpkg -r <archivo.deb>

 Para imprimir en pantalla la lista de todos los paquetes instalados en el sistema, usamos -l
    dpkg -l
  podemos filtrar de esta lista, los paquetes que nos interesan,
    ej: dpkg -l | grep -i openvpn

 Conocer el paquete al que pertenece un archivo con dpkg, usamos -S
   ej: dpkg -S /usr/sbin/snmptrapd
   R: snmpd: /usr/sbin/snmptrapd 

 Para ver la lista de archivos instalados por un paquete, usamos -L
   ej: dpkg -L snmpd | less

 Un resumen de algunos comandos útiles:
  apt-key add <archivo>: Agrega la clave publica contenida en <archivo> a la lista de confianza de apt.
  apt-key del <keyid>: Elimina <keyid> de la lista de confianza de apt.
  apt-key list:   Imprime la lista de claves
  apt-get update:  Lee el archivo sources.list y actualiza la base de datos de paquetes disponibles. Se tiene que correr este comando toda vez que se modifique sources.list
  apt-get install:  Baja e instala un paquete dado, si este se encuentra en la base de datos
  apt-get auoclean:  Elimina paquetes que se descargaron y son antiguos.
  apt-get upgrade:  Actualiza todos los paquetes.
  apt-get dist-upgrade:  Actualiza la distribución.
  apt-get clean:  Elimina los archivos descargados (almacenados en cache)
  apt-get remove <paquete>: Elimina el paquete.
  apt-get purge:  Elimina y purga paquetes
  apt-get --purge remove <paquete>: Elimina el paquete y elimina sus archivos de configuración.
  apt-get -f install:  Hace un chequeo de los paquetes rotos. Se intenta corregir los menajes de error en las dependencias.
  apt-cache pkgnames:  Imprime la lista de todos los paquetes instalados.
 
  dpkg -x <archivo.deb><directorio>: Extrae los archivos que están contenidos en el archivo .deb, en el directorio indicado.
  dpkg -i <archivo.deb>: Instala en el sistema el archivo .deb.
  dpkg -P <paquete>: Elimina el paquete y sus archivos de configuración.
  dpkg -r <paquete>: Elimina solo el paquete indicado.
  dpkg -l:  Imprime la lista de paquetes instalados en el sistema.
  dpkg -S <nombre archivo>: Muestra los paquetes donde el nombre del archivo es encontrado.
  dpkg -L <paquete>: Muestra la lista de archivos instalados en el sistema que pertenecen al paquete dado.
Leer más...

Crear el primer Custom TagLib

 Cuando las funciones disponibles en JSTL (u otras bibliotecas de tag) no cubren nuestra necesidad, podemos crear nuestras propias funcionalidades.

 Para esto, creamos un archivo conocido como TLD ( Tag Library Descriptor ).
 Es un archivo xml en el cual se define las funciones, los atributos que tienen y cuales son obligatorios, la clase que realiza la tarea cuando se usa el tag, el identificador único del tag ( el URI, que se usa para importar la biblioteca de tag desde las páginas jsp's), etc.
 Este archivo tiene como extensión '.tld', y puede ser copiado en diferentes lugares en el proyecto web, como ser:
  Directamente bajo el directorio "WEB-INF".
  Dentro de un sub-directorio en "WEB-INF".
  Dentro del directorio "META-INF" en un archivo .jar, que está dentro de WEB-INF/lib.
  Dentro de un sub-directorio, dentro del directorio "META-INF" en un archivo .jar, que está dentro de WEB-INF/lib .

 Vamos a crear como ejemplo, un tag que imprime un mensaje (un saludo) en pantalla. El código para nuestro TLD es el siguiente :


  (archivo: primerctl.tld)
<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">

<tlib-version>1.2</tlib-version>
<short-name>MyPrimerTag</short-name>
<uri>MyPrimerTagURI</uri>

<tag>
 <name>saludo</name>
 <tag-class>ejemplos.SaludoTagHandler</tag-class>
 <body-content>empty</body-content>
 <attribute>
  <name>nombre</name>
  <required>true</required>
  <rtexprvalue>true</rtexprvalue>
 </attribute>
 <attribute>
  <name>apellido</name>
  <required>false</required>
  <rtexprvalue>false</rtexprvalue>
 </attribute>
</tag>
</taglib>


 Para cada atributo que soporte la función, se tiene que indicar el nombre del atributo (mediante la propiedad 'name'), si el atributo es obligatorio (required), y si el valor del atributo tiene que ser ingresado de forma explícita, o puede ser el resultado de una expresión (rtexprvalue, si no se define esta propiedad, el efecto es igual a rtexprvalue=false ).

 En el TLD indicamos la clase a usar (por medio de tag-class ), en nuestro caso es:  ejemplos.SaludoTagHandler.
 Una de las formas para realizar esta clase, es extender de SimpleTagSupport, en donde se tiene que implementar el método 'doTag()', donde se realiza el trabajo.
 También se tiene que crear los métodos set para los atributos que usamos, en nuestro ejemplo, setNombre() y setApellido().

 Creamos un proyecto java (java Class Library), un paquete llamado 'ejemplos', y en este paquete, la clase SaludoTagHandler.java con el siguiente código:

package ejemplos;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class SaludoTagHandler extends SimpleTagSupport {
    private String nombre;
    private String apellido;

    @Override
    public void doTag() throws JspException, IOException {
        String aSaludar = apellido == null ? nombre : nombre + " " + apellido ;
        getJspContext().getOut().write("Hola: " + aSaludar + "<br>");
    }

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


 Tenemos que crear un jar con esta clase, y agregamos en el directorio META-INF del jar, el archivo primerctl.tld que se hizo previamente.

 Por último, incluimos esta biblioteca en un proyecto web (dentro de WEB-INF/lib). De esta forma, ya podemos usarlo en las paginas jsp del proyecto web, por ejemplo, creamos la página: test.jsp

 <%@page contentType="text/html" pageEncoding="UTF-8"%>
 <%@ taglib prefix="pctl" uri="MyPrimerTagURI" %>

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <pctl:saludo nombre='MiNombre' apellido="Mi-Apellido" />
    </body>
</html>


 La salida en la página es:
   Hola: MiNombre Mi-Apellido

 Tener presente que se indico en el archivo primerctl.tld, que es obligatorio incluir el atributo "nombre", pudiendo ingresar su valor directamente como un String (como se hizo en el ejemplo), o por medio de una expresión (ej. <pctl:saludo nombre='${nmbre}' /> ).
 El atributo "apellido" no es obligatorio, y en caso de incluirlo, el valor tiene que ser un string ingresado directamente en el tag, ya que mediante rtexprvalue=false se indica que no es válido ingresar este valor como una expresión.

 Mediante el desarrollo estos tag reducimos el código java insertado en las páginas, y facilitamos el re-uso sin necesidad de "copiar y pegar".
 Los diseñadores de páginas, acostumbrados a código html/xml pueden usar estos tag's sin conocer java.
Leer más...

Introducción a JSTL - JSP Standard Tag Lib

 En esta  introducción a JSTL, no se explica como crear nuestra propia biblioteca de tag (tag lib).

 JSTL es una colección de funciones de uso común, cuando se desarrolla páginas dinámicas (como ser bucles, bloques condicionales, formateo de textos, internacionalización, etc), prontas para ser usados desde paginas JSP, y con una apariencia similar a tags de xml (ej: <c:out value="se muestra este texto en la pagina" />).
 El uso de estas funcionalidades (JSTL) permiten que las páginas sean mas fáciles de leer y de mantener, evitando agregar gran cantidad de código java insertado en las páginas. Están divididas en diferentes bibliotecas que cubren varias áreas, como ser procesamiento de xml,  Core, internacionalización y formateo de datos, acceso a base de datos relacional (sql).

Para poder usar JSTL en un proyecto web, primero es necesario copiar dos bibliotecas en nuestro proyecto, estos son: jstl.jar y standard.jar (en WEB-INF/lib).
En la aplicación de ejemplo que se baja con tomcat, se puede obtener estas bibliotecas (o podemos bajarlas desde la web).

Para poder usar una tag lib en una página, es necesario importarla usando el identificador asociado al tag (la uri ), y dar un nombre de prefijo, el cual es usado para llamar luego a las funciones disponibles.
 Para esto, en la pagina usamos:

  <%@ taglib uri="uri_taglib" prefix="myPrefix" %>

 A continuación, una lista de las librerias disponibles, con su URI, y el prefijo que se usa normalmente:

 XML    http://java.sun.com/jsp/jstl/xml    x
 Core     http://java.sun.com/jsp/jstl/core  c
 i18n      http://java.sun.com/jsp/jstl/fmt    fmt
 SQL     http://java.sun.com/jsp/jstl/sql     sql

Para poder usar en nuestra página, por ej. la funcionalidades dentro del Core, primero tenemos que importar el tag lib correspondiente:
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

nota: Es posible ver en paginas que usa una versión anterior de jstl, usar una uri diferente (no usa el "jsp" uri="http://java.sun.com/jstl/core" ).

 Sobre el lenguaje de expresión:
  Vamos a ver anotaciones del tipo: ${...}.
  De esta forma se indica que la información ingresada dentro de las llaves, no es leída literalmente, sino que se tiene que evaluar, y usar el resultado de esta evaluación.
  Como ejemplo simple, si tenemos: ${8+2}, el valor usado es "10".

  Si tenemos una expresión como: ${ valorEntero}, se busca en los diferentes alcances de variables disponibles para la jsp, esa variable, en el siguiente orden:
 page -> request -> session -> application. Se retorna el primer valor encontrado.
  En caso de ser necesario obtener el valor desde un alcance en particular, se indica dentro de la expresion:
 ${pageScope.valorEntero} || ${requestScope.valorEntero} ||${sessionScope.valorEntero} || ${applicationScope.valorEntero}

 Para acceder a los parámetros dentro de un request (por ejemplo, los datos desde un formulario), simplemente agregamos "param." antes del nombre del parámetro:  ${param.nombre}.
 En caso de que el parámetro pueda tener varios valores, en lugar de 'param' usamos: 'paramValues.'

 Vamos a crear una pagina para usar con ejemplos, y probar algunas funciones.

 <c:out> => Imprime texto en pantalla
uso: <c:out value="Prueba JSTL" />
------------------------
 Ejemplo: index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
    <head>
        <title>JSP Page</title>
    </head>
    <body>
        <c:out value="Prueba JSTL" />
    </body>
</html>

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

Para recorrer una lista con jstl podemos usar la etiqueta <c:forEach>
<c:forEach> Recorre cada elemento de una colección dada, indicando la colección a recorrer por la propiedad: 'items', el nombre para el item actual lo indicamos por la propiedad 'var'.

 Ej:  En la página anterior podemos agregar un array para probar esta funcionalidad.
  Antes del tag '<html>' agregamos:
  <%
  String[ ] equiposUy = {"Peñarol", "Defensor", "Danubio"};
  request.setAttribute("equiposUy", equiposUy);
  %>


 Luego, dentro del body, agregamos el loop.
 <c:forEach var="equipo" items="${equiposUy}" >
       ${equipo}
 </c:forEach>


A este mismo ejemplo, vamos a agregarle un par de elementos para probar la propiedad "empty" que verifica si una variable existe (y no esta vacía), vamos a usar el alcance de variables (requestScope y sessionScope), y al final, obtener un dato por parámetro.
 El nuevo código completo de la página index.jsp:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String[] equiposUy = {"Peñarol", "Defensor", "Danubio"};
request.setAttribute("equiposUy", equiposUy);
%>
<html>
    <head>
        <title>JSP Page</title>
    </head>
    <body>
        <c:out value="Prueba de JSTL"/><br/>
        <c:out value="Existe el array equiposUy en la session : ${!empty sessionScope.equiposUy}" /> <br>
        <c:out value="Existe el array equiposUy en el request : ${!empty requestScope.equiposUy}" /> <br>
        <c:forEach var="equipo" items="${requestScope.equiposUy}" varStatus="equipLoopTag">
            ${equipLoopTag.count} : ${equipo} <br/>
        </c:forEach>

        Nombre por parametro: <c:out value='${param.nombre}' default=" No se ingreso el nombre"/>
    </body>
</html>

La llamada a la pagina la hacemos con un parámetro ('nombre') que pasamos en la url, por ejemplo: http://localhost:8080/TestWeb/?nombre=MiNombre
salida:
 Prueba de JSTL
Existe el array equiposUy en la session : false
Existe el array equiposUy en el request : true
1 : Peñarol
2 : Defensor
3 : Danubio
Nombre por parametro: MiNombre


Si no pasamos el parámetro en la llamada a la pagina (por ejemplo, simplemente hacemos: http://localhost:8080/TestWeb), la última linea imprime el valor por defecto dado a <c:out>: "Nombre por parametro: No se ingreso el nombre"

Vamos a ver un par de funciones mas:

<c:if> Bloque condicional. Nota: Este elemento no tiene un equivalente a: 'else'
uso: <c:if test="${ 5 > 3}"> <c:out value="Dentro del if" /> </c:if>
Este tag evalúa la expresión de la propiedad 'test', si es verdadero ('true'), ingresa al bloque del if correspondiente.

Si se necesita un equivalente a "if ... else", tenemos que usar:
<c:choose>
  <c:when> ... </c:when>
  <c:otherwise> ... </c:otherwise>
</c:choose>


Como ejemplo, agregamos el siguiente código a nuestra pagina:
<c:choose>
  <c:when test="${param.nombre == 'dlix' }">
    <c:out value="Hola ${param.nombre}" />
  </c:when>
  <c:when test="${param.nombre == 'd-lix' }">
    <c:out value="Usas otro nick" />
  </c:when>
  <c:otherwise>
    <c:out value="No eres dlix" />
  </c:otherwise>
</c:choose>


Y hacemos las siguientes llamadas a la página, para ver los resultados
http://localhost:8080/TestWeb/?nombre=dlix       (salida: Hola dlix)
http://localhost:8080/TestWeb/?nombre=d-lix      (salida: Usas otro nick)
http://localhost:8080/TestWeb/?nombre=MiNombre   (salida: No eres dlix)

Captura de excepciones
<c:catch> Es similar al uso de try/catch. Si el código dentro de este bloque genera una excepción, es capturado, y en lugar de mostrar el error,  se pasa a la siguiente línea luego del bloque
uso: <c:catch> 
           <%= 10/0 %>
        </c:catch>
Sin el bloque '<c:catch>', al ejecutar <%= 10/0 %> tendríamos el error: java.lang.ArithmeticException: / by zero

 Todo sobre JSTL en su propio lugar: http://java.sun.com/products/jsp/jstl
Leer más...