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

Mostrando entradas con la etiqueta java. Mostrar todas las entradas
Mostrando entradas con la etiqueta java. Mostrar todas las entradas

Caracteres especiales con StringEscapeUtils

En Java podemos usar StringEscapeUtils para convertir caracteres especiales a su equivalente html / unicode, y viceversa.

Para esto usamos los métodos "escapeHtml(...)", "escapeJavaScript(...)",unescapeHtml(...) y unescapeJavaScript(...)

StringEscapeUtils es una clase que pertenece al api commons-lang de apache ( http://commons.apache.org/lang/http://commons.apache.org/lang/ ).

Como ejemplo, veamos algunos caracteres en español que suelen dar problemas cuando comenzamos a crear formularios.

   String caracteres = "á é í ó ú ü ñ ½" ;
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...

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...

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...

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...

comenzando con log4j - logs en java

Esto es apenas una pequeña introducción a log4j, no un manual.
Espero ayude para comprender y comenzar a usar.

Suele ser normal cuando programamos, imprimir mensajes (en consola o un archivo), por diferentes motivos, como ser, saber si el programa esta pasando por algún punto en particular, conocer el valor de una variable, un mensaje de error, etc. No es extraño ver en el codigo líneas como: System.out.println("me conecto a la base ...");
También puede ser requerimiento de la aplicación, almacenar información de negocio, como ser datos de alguna transacción, fecha/hora cuentas involucradas y monto de una transferencia bancaria, etc.

Si bien resulta sencillo imprimir mensajes con: System.out.println(...) (sin considerar en esta oportunidad el costo de esa llamada), cuando queremos dejar de ver los mensajes (o activarlos nuevamente), se requiere modificar el código, y compilarlo.
La información de negocio se suele almacenar en un archivo, o en una bd (o en ambos), por lo que println() deja de ser una opción.

Es en estos casos donde log4j entra en acción.
Nos permite configurar en un archivo, los tipos de mensajes queremos imprimir (debug, info, error, etc), donde queremos dirigir los mensajes (consola, un archivo, una base de datos, ...), el formato como queremos mostrar la información.
También es posible realizar la configuración en el programa, con la necesidad de compilar con cada cambio.

Vamos a introducir algunos conceptos que vamos a usar en un ejemplo sencillo al terminar el artículo.

1) Nivel o prioridad de log:
En la configuración, indicamos el nivel de prioridad que se habilita.
Estos niveles son jerárquicos:
ALL < DEBUG < INFO < WARN < ERROR < FATAL < OFF.
ALL significa que se habilita todos los logs, mientras que OFF deshabilita todos los logs.
Como ejemplo, si habilitamos el nivel WARN, se van a guardar los mensajes que pertenecen a: WARN, ERROR y FATAL.

2) Logger: La propiedad Logger es donde se configura el elemento a enviar los mensajes (por ej, las clases dentro de un paquete dado).

3) Appender: Mediante los appenders indicamos el/los destino/s de salida de los mensajes.
Si bien podemos crear nuestros propios appenders, existen varios ya creados que podemos usar, como ser: ConsoleAppender (imprime log en consola), FileAppender o RollingFileAppender (para almacenar los mensajes en un archivo, en el último, se puede indicar, por ejemplo, tamaño máximo del archivo, y cantidad de archivos a almacenar), JDBCAppender (almacenar los mensajes en una base de datos), SyslogAppender (envía la salida al syslog en sistemas linux/unix).

4) Layout: Mediante el objeto Layout se formatea el estilo de la información  que se almacena en el log.

Configuracion log4j:
La configuración de log4j puede hacerse por programación, por medio de un archivo propertie de java, o por medio de un archivo xml.
Para nuestro ejemplo vamos a usar el archivo xml. Por defecto, este se tiene que llamar log4j.xml, y tiene que estar en el claspath usado
para la carga de las clases.

ejemplo log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- CONSOLA -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%p] [%d{dd/MM/yyyy HH:mm:ss}] [%c]:%L - %m%n" />
</layout>
</appender>
<!-- ARCHIVO -->

<appender name="logfile" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="/tmp/ejemplol4j/test.log" />
<param name="append" value="true" />
<param name="MaxFileSize" value="512KB"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %p [%c] - %m%n" />
</layout>
</appender>

<logger name="testl4j" additivity="false">
<level value="info" />
<appender-ref ref="console" />
<appender-ref ref="logfile" />
</logger>

<root>
<priority value="debug" />
<appender-ref ref="console" />
</root>
</log4j:configuration>

Descripción de log4j.xml
1.1) Indicamos un appender para enviar los mensajes a la consola
<appender name="console" class="org.apache.log4j.ConsoleAppender">
1.2) Le damos un formato a los mensajes
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%p] [%d{dd/MM/yyyy HH:mm:ss}] [%c]:%L - %m%n" />
</layout>

%p: muestra la prioridad del log que se imprime
%d: muestra la fecha en que se imprime el log, y en este caso, so formatea como se quiere ver la fecha/hora
%c: muestra el objeto que imprime el log.
%L: el número de línea donde se genera el log.
%m: el mensaje que se quiere imprimir.
%n: imprime un salto de linea.

2.1) Indicamos otro appender, en este caso, para enviar los mensajes a un archivo.
<appender name="logfile" class="org.apache.log4j.RollingFileAppender">
2.2) Configuramos algunos parámetros para este appender:
El archivo donde se almacena el log (en este caso, se usa un equipo con linux)
<param name="file" value="/tmp/ejemplol4j/test.log">
Indicamos que el archivo no se sobrescriba cada vez que comienza la aplicación.
<param name="append" value="true">
Indicamos el tamaño máximo de los archivos de log.
<param name="MaxFileSize" value="512KB">
2.3) El formato en el layout es similar al de consola, pero cambiamos el orden de la información de salida, y a la fecha no se le dio un formato en particular.

3) Configuramos el elemento 'logger'. Indicamos el elemento raíz que va a enviar mensajes (en este caso, objetos en el paquete testl4j)
Con additivity="false" los mensajes se imprimen 1 vez, sino se verá el mensaje por el propio logger, y luego por el "root".
<logger name="testl4j" additivity="false">
Indicamos el nivel de prioridad que se permite

<level value="info"></level>
Indicamos a donde se va a enviar los mensajes, en este caso, se envía a la consola y al archivo.
<appender-ref ref="console"></appender-ref>
<appender-ref ref="logfile"></appender-ref>
obviamente, podemos agregar tantos logger's como nos sea necesario.

4) Indicamos el log por defecto. Si un elemento envía un mensaje de log, y no está indicado ese elemento en el logger, se utiliza la esta configuración.
En nuestro ejemplo, se imprime a partir de la prioridad de debug (no es una buena opción en general, pero sí para nuestro ejemplo), y solo enviamos los mensajes a consola
<root>
<priority value="debug"></priority>
<appender-ref ref="console"></appender-ref>
</root>

La clase para la prueba de log4j.
Creamos la clase: Main, dentro del paquete: testl4j

Main.java
---------
package testl4j;
import org.apache.log4j.Logger;
public class Main {
private static Logger _log = Logger.getLogger(Main.class);
public static void main(String[ ] args) {
_log.info(" Iniciando prueba de log4j");
_log.debug(" Iniciando prueba de log4j");
}
}

En este caso enviamos 2 mensajes de log, uno de nivel "info", y el siguiente de nivel "debug".

1er Ejemplo)
-------------------
Al ejecutar el programa, obtenemos la siguiente salida:
1) Consola
[INFO] [10/01/2010 19:32:52] [testl4j.Main]:24 - Iniciando prueba de log4j
2) Archivo
2010-01-10 19:32:52,880 INFO [testl4j.Main] - Iniciando prueba de log4j

En el logger para "testl4j", indicamos que el nivel de prioridad habilitado es "info", por este motivo, no se muestra el mensaje de "debug".

2do Ejemplo)
-------------------
Para esta prueba, eliminamos del archivo log4.xml, todas las lineas de "logger".
Al hacer esto, no se tiene una configuración específica para el paquete testl4j, por lo que utiliza la configuración por defecto( "root")
Al ejecutar el programa, obtenemos la siguiente salida:
1) Consola
[INFO] [10/01/2010 19:40:51] [testl4j.Main]:24 - Iniciando prueba de log4j
[DEBUG] [10/01/2010 19:40:51] [testl4j.Main]:25 - Iniciando prueba de log4j
2) Archivo


En consola se imprime tanto el mensaje de debug y el de info, ya que el nivel de prioridad por defecto se configuro con "debug".
En el archivo de configuración no se imprime ningún mensaje, ya que solo se configuro un append por defecto, el de consola.

Por mayor información, parámetros, appenders, etc, la pagina de log4j es: http://logging.apache.org/log4j
Leer más...

Buscar un elemento en un array - java Arrays

Para nuestra búsqueda en un array vamos a usar java.util.Arrays.binarySearch(array[], key)
Los elementos del array en el cual queremos buscar, tienen que estar ordenados en modo ascendente.
Si el elemento a buscar existe en el array, retorna un entero positivo, que corresponde con la posición del elemento en el array.
Si el elemento a buscar NO existe en el array, retorna un entero negativo.


Ej.

String arrayTest[] = {"aa", "bb", "cc", "dd", "ee"};
//buscamos un elemento que existe en el array
int idx = Arrays.binarySearch(arrayTest, "dd");
System.out.println( "Elemento encontrado en: "+idx);

//buscamos un elemento que NO existe en el array
idx = Arrays.binarySearch(arrayTest, "zz");
System.out.println( "No se encuentra elemento, resultado: "+idx);

Resultado:
run:
Elemento encontrado en: 3
No se encuentra elemento, resultado: -6

Si el array no esta ordenado, el resultado es indefinido.
En caso que el array pueda estar desordenado, puede usarse otro método de "java.util.Arrays"

Arrays.sort( arrayTest);
int idx = Arrays.binarySearch(arrayTest, "dd");
... Leer más...

inicializar variable static final en java

Las variables estáticas son inicializadas cuando se carga la clase, antes de que pueda ser creado un objeto o se pueda ejecutar algún método estático de esa clase.

Al indicar una variable como "final", estamos diciendo que una vez inicializada, no podemos modificar su valor.

Para inicializar una variable "static final", podemos hacerlo en la propia declaración,

ej: public static final int MAX = 10 ;

También puede inicializarse en un bloque estático:

public static final int MAX ;
static {
MAX = 10 ;
}

Este bloque "static", se ejecuta cuando la clase es cargado, y antes de poder usar una variable o método estático de la clase.
Es posible ejecutar un método de un objeto en este bloque, con la lógica necesaria para inicializar la variable. Leer más...