En muchas soluciones de la vida real es necesario manipular y leer el contenido de archivos y es muy común que en un principio se trate de utilizar solo las clases del paquete java.io, esto esta bien si se quiere optimizar la lectura o manipulación de archivos o se requiere una solución a un problema especifico. Sin embargo existen los Apache Commons, que es un conjunto de librerías para una gran variedad de problemas y una de esas librerías es commons-io.jar que viene con la clase FileUtils y que facilita el manejo de archivos. Aquí enlistamos algunas de las funciones de esa clase que la hacen bastante útil.
Permite escribir a un archivo
Leer desde un archivo
Crear directorios, incluyendo directorios padres (de forma recursiva)
Copiar archivos y directorios
Borrar archivos y directorios
Covertir hacia o desde una URL
Listar archivos y directorios con filtros y extensión
Comparar el contenido de archivos
Obtener el última fecha de actualizacion
Calcular checksum, entre otras.
Aqui un pequeño ejemplo para convertir un archivo de texto a String o traer una lista de archivos desde un directorio y filtrando extensiones.
public class Prueba {
public static void main(String[] args) {
//Leer el contenido de un archivo de texto y depositarlo en un String
File archivo = new File("ejemplo.txt");
//Traer una lista de archivos filtrando la extensión
File root = new File("/proy");
try {
// Leer el contenido de un archivo y copiarlo a un String
String content = FileUtils.readFileToString(archivo);
System.out.println("File content: " + content);
//Obtener una lista de archivos de forma recursiva contenida en un directorio
String[] extensiones = {"xml", "java", "dat"};
boolean recursivo = true;
¿Quién no ha incurrido en estos errores? Si ya llevas algún tiempo desarrollando, seguro has sufrido por alguno de ellos.
La lista de errores más frecuentes encontrados en la ejecución de los proyectos de TI:
Errores relacionados con la gente
Miembros del equipo desmotivados
Falta de capacitación de la gente involucrada en el desarrollo
Personas problemáticas en el equipo
Agregar más programadores a un proyecto ya retrasado
Oficinas ruidosas y aglomeradas
Fricciones entre quienes desarrollan y el cliente
Expectativas poco realistas
Falta de un líder efectivo para el proyecto
Falta de participación del usuario
Falta de acuerdo antes que el desarrollo de inicio
Las “Ilusiones”
Errores relacionados con los procesos
Planeación demasiado optimista
Falta de administración de riesgos
Falla en los contratos
No hay suficiente planeación
Abandono del plan bajo presión
Pérdida de tiempo al inicio del proyecto
Saltarse las tareas iniciales
Diseño no adecuado
Falta de supervisión por parte de los responsables
Falta de estimaciones adecuadas
Errores relacionados con el producto
Requerimientos excesivos
Cambio de requerimientos
Developers muy meticulosos
Errores relacionados con la tecnología
Síndrome de la panacea
Sobre-estimación de las ventajas del uso de una nueva herramienta
Cambio de herramientas a mitad del proyecto
Falta de un control de código fuente automático
Seguramente ya hay muchos mas.
Y ahora algunas de las razones por las que se incurre en estos errores:
Errores relacionados con la gente
Miembros del equipo desmotivados. Es casi imposible encontrar gente que se enamore de todos los proyectos.
Falta de capacitación de la gente involucrada en el desarrollo. «La gente que va comenzando es la que cobra menos, ¿Y por qué no meter solo becarios?» ¡Típico!
Personas problemáticas. Dime si no has estado junto al tipo que cree saber más que el líder de proyecto, pero no lleva más de unas semanas en un proyecto real (los de la escuela no cuentan). O bien, gente que simplemente no está bien con la vida ¡Y se dedicó a programar!
Agregar más programadores a un proyecto ya retrasado. Y como además no es necesario capacitarlos, explicarles las reglas de negocio, explicarles lo que quisieron hacer los otros programadores (que seguro ya no se acuerdan o ya ni están).
Oficinas ruidosas y aglomeradas. «Son programadores, no personas y solo necesitan una PC delante de ellos y unas mesas de madera»
Fricciones entre los developers y el cliente. ¡Esa manía de que la gente de TI de creer que siempre sabe lo que el cliente realmente necesita!
Expectativas poco realistas. Nunca falta el que quiere que le fabriquen un Word y pagar solo lo que cuesta el CD pirata.
Falta de un líder efectivo para el proyecto. Bueno, la gente de TI no nació para administrar proyectos, ¡Por eso programa! Pero casi nadie respeta a un líder de proyecto que no ha programado, por eso debe ser una especie de super administrador-programador-buena-gente.
Falta de participación del usuario. El usuario solo quiere sentarse y que su programa funcione y que no le quite tiempo para entrar al facebook.
Falta de acuerdo antes que el desarrollo de inicio. Y es que, ¿Cómo podemos estar de acuerdo con todas las tonterías que el cliente pide?
Las “Ilusiones”. El usuario piensa que le darán un automóvil, el líder de proyecto cree que solo le dará tiempo para hacer una bicicleta, los programadores tienen problemas para construir las ruedas de unos simples patines, y al final el usuario va a terminar caminando, como siempre lo ha hecho (el usuario es el incauto que trabaja para el que contrató a tu empresa, le vas a quitar tiempo y al final harás mas difícil su trabajo)
Errores relacionados con los procesos
Planeamiento demasiado optimista. ¡Claro! Hacemos un módulo por día y el último integramos todo.
Falta de administración de riesgos. ¿Alguien conoce a los que se dedican a administrar esas cosas?
Falla en los contratos. Lo bueno de usar plantillas de World es que todas incluyen las letras chiquitas donde no nos hacemos responsables de errores o vicios ocultos después de seis o más meses. Que es más o menos el tiempo en el que la base de datos se irá al carajo.
No hay suficiente planeamiento. Muchas veces solo se tiene el texto que viene en la propuesta comercial.
Abandono del planeamiento bajo presión. Sobre todo cuando le dices al usuario que hacer un facebook o un twitter es normalmente más caro que hacer una simple página web.
Pérdida de tiempo al inicio del proyecto. Y cuando pasa el pánico y comienza la negación.
Saltarse las tareas iniciales. Nunca analizas y nunca diseñas, ¡Esa es tarea de ñoños!
Diseño inadecuado. ¡Porque así me enseñaron en la escuela y los profesores son gente muy capacitada que lleva años en la industria del desarrollo de sistemas!
Falta de supervisión. Porque el gestor y el líder llevan como veinte proyectos al mismo tiempo y todavía no terminan otros que ya se entregaron. Y por supuesto los programadores se pueden enseñar solitos sobre lo que el cliente quiere.
Falta de estimaciones. ¡Para que! Si solo es la autoestima de los programadores lo que se va al carajo cuando fallan los proyectos.
Errores relacionados con el producto
Requerimientos excesivos. Si no está clara la propuesta el cliente te va a meter todas las funcionalidades que pueda y si puede hacer todo su trabajo, mejor.
Cambio de requerimientos. Porque claro, el mercado cambia constantemente y hay que ser competitivos y ajustarse a esos cambios. Pero la verdad es que, es hasta que el usuario comienza a usar el sistema, que se da cuenta de que nadie tenía idea de lo que se tenía que hacer realmente.
Developers muy meticulosos. Todos los programmers somos obsesivos compulsivos, es lo que nos metió en esto desde un principio.
Errores relacionados con la tecnología
Síndrome de la panacea. ¡Claro! Hay que usar Struts, Spring y Hibernate… siempre y ya con eso quedan bien todos los sistemas.
Sobre-estimación de las ventajas del uso de una nueva herramienta. Como cuando usas una de esas herramientas de business intelligence o un CMS, que según el vendedor, harán prácticamente todo lo que el cliente te pida.
Cambio de herramientas a mitad del proyecto. Si no funciona Struts usa JSF, porque es mejor, si no funciona tampoco pues usa Spring MVC, porque es más simple, si no funciona mete Flex, porque se ve bien, si no funciona… y así.
Falta de un control de código fuente automático. Te apuesto que eso si no te lo enseñaron en la escuela. Y que difícil es entender y usar subversión y que todos tus compañeros lo usen, la primera vez.
Mostraremos como hacer una pequeño ejemplo Web en JavaServer Faces 2.0 que permita crear, leer, actualizar y borrar registros en una base datos de MySQL. Todo esto con la ayuda de las herramientas de NetBeans.
En este ejemplo haremos uso de las siguientes tecnologías:
JavaServer Faces (JSF) 2.0
Java Persistence API (JPA) 2.0
Enterprise JavaBeans (EJB) 3.1
Será necesario tener instalado el siguiente software:
NetBeans IDE 7.0, o superior.
Java Development Kit (JDK) 6, o superior.
GlassFish Application Server v3, o superior.
MySQL 5.x o superior
Para este ejemplo seguiremos los siguientes pasos:
Crear la base de datos.
Examinar la estructura de base de datos.
Crear el proyecto Web.
Generar las clases de entidad desde la base de datos.
Generar los JSF desde las clases de entidad.
Explorando la aplicación.
Crear la base de datos
Si ya has creado una base de datos en MySQL antes, quizá sabes también que hay más de una forma o herramienta para administrarla. Aquí te mostraremos como hacerlo desde la pestaña de servicios de NetBeans. Si accedes a ella y después das click en Databases, podrás ver que existe predefinido un item solo para registrar un servidor de base de datos de MySQL, para iniciar el servicio en NetBeans, debes dar click derecho y después en propiedades para completar los datos de conexión.
Es probable que si tienes instalado MySQL localmente, NetBeans detecte y se encargue de registrar automáticamente la BD.
Debes llenar los datos de acceso que definiste al instalar MySQL, como la IP del equipo donde esté instalado que típicamente es localhost o 127.0.0.1
Cuando hayas terminado de llenar los datos para conectarte, simplemente da click derecho al mouse y después en conectar.
Ya que te hayas conectado es posible crear una nueva base de datos en las opciones del submenu con click derecho:
Yo he creado una BD llamada: ejemploJSF20.
Al crear la base de datos, también se crea una conexión a la misma y es posible ejecutar comandos de SQL sobre la nueva base.
Para este ejemplo te proporcionamos dos scripts de SQL que te permitirán crear las tablas necesarias y llenarlas de datos de ejemplo para ejecutar el ejercicio adecuadamente.
Examinar la estructura de base de datos Una vez que has ejecutado los scripts puedes explorar la base de datos para ver las tablas y el contenido que has creado. No olvides refrescar el estado de la conexión.
Bien, ya se han creado y poblado las tablas que necesitaremos.
La siguiente es una descripción de las tablas:
Tabla
Descripción
Características
CLIENTE
Cliente de la agencia de consultoria
No-generada, llave primaria compuesta (cuyos campos no constituyen una llave foranea)
CONSULTOR
Un empleado de la agencia de consultoría que los clientes pueden contratar sobre una base contractual
Incluye un campo resumen de tipo LONG VARCHAR
ESTATUS_CONSULTOR
El estado de un consultor con la agencia de consultoría (por ejemplo, activos e inactivos son estados posibles)
No-generada, llave primaria de tipo CHAR
RECLUTADOR
Un empleado de la agencia consultora responsable de la conexión de los clientes y consultores
PROYECTO
Un proyecto de los clientes con consultores de la agencia.
No-generada, llave compuesta que incluye dos campos constituyendo una llave foranea para la tabla CLIENTE
FACTURABLE
Un conjunto de horas trabajadas por un consultor en un proyecto, para los que la consultoría de proyectos facture al cliente en cuestión
Incluye un campo artefacto de tipo CLOB
DIRECCION
Dirección de Facturación
CONSULTOR_PROYECTO
Tabla de Union que indica que consultores están asignados a que proyectos.
Referencia-cruzada PROYECTO y CONSULTOR, los primeros tienen una clave primaria compuesta
La base de datos incluye una variedad de relaciones. Al crear clases de entidad de una base de datos, el IDE genera automáticamente las propiedades del tipo de Java adecuada basada en el tipo de SQL de las columnas. La siguiente tabla describe las relaciones de entidades para consultar la base de datos. (Relaciones inversas no se muestran)
Entidad
Entidad Relacionada
Información
Descripción
CLIENTE
RECLUTADOR
nullable con edición manual; nullable uno-a-muchos si no.
CLIENTE tiene muchos RECLUTADORES y RECULTADOR tiene cero o un CLIENTE (si no es editado manualmente)
CLIENTE
DIRECCION
non-nullable uno-a-uno
CLIENTE tiene una DIRECCION y DIRECCION tiene cero o un CLIENTE
CLIENTE
PROYECTO
non-nullable uno-a-muchos; en una entidad Proyecto, el valor del campo cliente es parte de la llave primaria del Proyecto
CLIENTE tiene muchos PROYECTOs y un PROYECTO tiene un CLIENTE
CONSULTOR
PROYECTO
muchos-a-muchos
CONSULTOR tiene muchos PROYECTOs y PROYECTO tiene muchos CONSULTORES
CONSULTOR
FACTURABLE
non-nullable uno-a-muchos
CONSULTOR tiene muchas FACTURABLEs y FACTURABLE tiene un CONSULTOR
ESTATUS_CONSULTOR
CONSULTOR
non-nullable uno-a-muchos
ESTATUS_CONSULTOR tiene muchos CONSULTOREs y CONSULTOR tiene un ESTATUS_CONSULTOR
CONSULTOR
RECLUTADOR
nullable uno-a-muchos
CONSULTOR tiene cero o un RECLUTADOR y RECLUTADOR tiene muchos CONSULTOREs
FACTURABLE
PROYECTO
non-nullable uno-a-muchos
FACTURABLE tiene un PROYECTO y PROYECTO tiene muchos FACTURABLEs
Crear el proyecto Web
Ahora es momento de crear el proyecto Web utilizando el framework de JSF
En el menú superior debes elegir: File->New Project (Ctrl-Shift-N).
Selecciona Web Application de la categoría Java Web. Da click en Next.
Escribe el nombre del proyecto y la hubicación, para este ejemplo usamos el nombre ejemploJSF2. Despues da click en el botón Next
Selecciona el servidor GlassFish v3 y especifica la versión de Java EE con la Java EE 6 Web. Da un click en Next.
En el panel de Frameworks, selecciona la opción de JavaServer Faces. Da click en Finish.
Cuando das click en Finish, el IDE genera el proyecto de tipo Web y abre index.xhtml en el editor.
Generar las clases de entidad desde la base de datos
1.- Después de conectar la IDE a la base de datos, usaremos el asistente o wizard que obtiene entidades de la base de datos para generar de forma rápida las clases basadas en las tablas de la base de datos. El IDE puede generar clases de entidad de cada tabla que selecciones, y puede generar además, cualquier clase de entidades para relacionar las tablas.
2.- En la ventana de Proyectos, dando un click derecho al nodo de ejemploJSF2, y seleccionando New->Entity Classes from Database. (Si esta opción no está en la lista, elija Otra. Despues, en el Wizard de File, seleccione la categoría de Persistence, después Entity Classes from Database).
3.- Selecciona New Data Source from the Data Source, arrastra la lista para abrir la ventana de dialogo Create Data Source.
4.- Selecciona el nombre JNDI jdbc/ejemploJSF2 y selecciona jdbc:mysql://localhost:3306/ejemploJSF2 como la base de conexión.
5.- Las tablas de la base de datos deberán aparecer en la lista de Tablas disponibles.
6.- Da click en el boton Add All para seleccionar todas las tablas. Da click en Next.
7.- Escribe jpa.ent como nombre de paquete. Asegura que el checkbox para generar consultas con nombre se ha seleccionado «Generate Named Query Annotations».
8.- Puedes dejar los valores por default que vienen, da click en Finish y el IDE comenzará a crear las entidades en el paquete que especificamos.
Al utilizar el asistente para crear clases de entidad de una base de datos, el IDE examina las relaciones entre las tablas de base de datos. En la ventana de Proyectos, si se expande el nodo del paquete jpa.ent, se puede ver que el IDE genera una clase de entidad para cada tabla, excepto para la tabla de PROYECTO_CONSULTOR. El IDE no ha creado una clase de entidad para PROYECTO_CONSULTOR porque la tabla es una union de tablas.
El IDE también ha generado dos clases adicionales para las tablas con llaves primarias compuestas: CLIENTE y PROYECTO. Las clases de llave primaria de estas tablas (ClientePK.java y ProyectoPK.java) tiene PK concatenado.
Si nos fijamos en el código generado para las clases de entidad se puede ver que el asistente añade anotaciones @GeneratedValue a los campos auto generados de ID y las anotaciones @Basic (optional = «false») a algunos de los campos en las clases de entidad. En base a las anotaciones @Basic (optional = «false»), las páginas que el asistente JSF Pages from Entity Classes genera, incluyen un código con controles para prevenir las violaciónes para columnas con valor no nulo.
Generando los JSF desde las clases de entidad
Ahora que hemos creado las clases de entidad, haremos la interfaz web para mostrar y modificar los datos. Usaremos el asistente JSF Pages from Entity Classes para generar páginas JavaServer Faces. El código generado por el asistente o wizzard se basa en las anotaciones de persistencia contenidas en las clases de entidad.
Para cada clase de entidad, el asistente genera lo siguiente:
Un bean de sesión sin estado para la creación, lectura, modificación y eliminación de entidades.
Un bean JSF manejador, session-scoped,
Un directorio que contiene cuatro archivos Facelets para realizar de CRUD (Create.xhtml, Edit.xhtml, List.xhtml, y View.xhtml)
Clases que serán usadas por los beans JSF manejadores (JsfUtil, PaginationHelper)
Un paquete de propiedades para los mensajes localizados, y una entrada correspondiente en el archivo de configuración del proyecto (faces-config.xml se crea si no existe)
Archivos Web auxiliares, incluyendo una hoja de estilos predeterminada para renderear componentes y un archivo plantilla para Facelets.
Para generar las páginas JSF
1.- En la ventana Proyectos, haz click en el nodo del proyecto y elije New> JSF Pages from Entity Classes para abrir el asistente. (Si esta opción no aparece en la lista, elije Otro. Luego, en el asistente de archivos, selecciona la categoría JavaServer Faces, a continuación, JSF Pages from Entity Classes)
La lista de clases de entidad disponibles muestra las siete clases de entidad que figuran en el proyecto. El cuadro no muestra las clases ClientPK.java y ProjectPK.java.
2.- Haz click en Agregar todo para mover todas las clases a la Selección de cuadro de clases de entidad.
Haz click en Siguiente.
3.- En el paso 3 del asistente, Generamos páginas JSF y clases, escribe jpa.con para el paquete controlador de JPA y jsf.con para las clases de respaldo de los JSFs.
4.- Escribe jsf para el folder donde estarán los JSFs
5.- Escribe ‘/Bundle’ en el campo «Localization Bundle Name». Esto generará un paquete llamado recursos en donde estará el archivo Bundle.properties (Si se deja en blanco, el paquete de propiedades, se creará en el paquete default del proyecto.)
Para que el IDE se adapte mejor a tus convenciones de proyecto, puedes personalizar los archivos generados por el asistente. Haz click en el enlace Customize Template para modificar el archivo de plantillas utilizadas por el asistente.
5.- En general, puedes acceder y realizar cambios en todas las plantillas gestionada por el IDE usando el Administrador de plantillas (Tools > Templates).
Si expandes el nodo Web Pages, veras que el IDE genera una carpeta para cada una de las clases de entidad. Cada carpeta contiene los archivos de Create.xhtml, Edit.xhtml, List.xhtml y View.xhtml. El IDE también modificó el archivo index.xhtml insertando los enlaces a cada una de las páginas List.xhtml.
Cada bean JSF manejador es específico para los cuatro archivos Facelets correspondientes e incluye el código que invoca métodos en el bean de sesión adecuado.
Expande el nodo o folder de recursos para localizar la hoja de estilos jsfcrud.css que fue generado por el asistente. Si abres la página de la aplicación de bienvenida (index.xhtml) o el archivo Facelets de plantilla (template.xhtml) en el editor, verás que contiene una referencia a la hoja de estilos.
El archivo Facelets de plantilla es usado por cada uno de los cuatro archivos de Facelets para cada clase de entidad.
<h:outputStylesheet name="css/jsfcrud.css"/>
Si expandes los paquetes fuente del nodo se pueden ver los beans controladores de JPA, los bean manejadores de JSF, clases de utilidad, y archivos de propiedades que el asistente genera.
El asistente también genera un archivo de configuración de Faces (faces-config.xml) para registrar la ubicación del paquete de propiedades. Si expandes el nodo de archivos de configuración y abres faces-config.xml en el editor de XML, se puede ver que se incluye la siguiente entrada.
Además, si exploras el paquete de recursos, encontrarás en el archivo de Bundle.properties, mensajes para el idioma del cliente por defecto. Los mensajes se derivan de las propiedades de la entidad de clase.
Para agregar un paquete de propiedades nuevas haz click en el archivo Bundle.properties y selecciona Customize. La ventana de diálogo Customizer te permite añadir nuevas configuraciones regionales para la aplicación.
Explorando la Aplicación
Ahora que el proyecto contiene las clases de entidad, los EJBs de sesión para controlar las clases de entidad, y JSF de front-end para mostrar y modificar la base de datos, intenta ejecutar el proyecto para ver los resultados.
En seguida se presentan algunos ejercicios opcionales que te ayudarán a familiarizarte con la aplicación, así como las características y funcionalidad que el IDE.
Examinar el proyecto terminado
Rellenar la base de datos con una secuencia de comandos de SQL
Explorar el Editor de Facelets
Exploración de la integridad de base de datos, con validación de campo
Edición de clases de la entidad
Examinar el proyecto terminado
1.- Para ejecutar el proyecto, haz click derecho en el nodo del proyecto en la ventana de proyectos y selecciona Run o Ejecutar.
Como puedes ver, nuevos enlaces se han añadido a la página de bienvenida (index.xhtml) con ayuda del asistente. Los enlaces creados se ofrecen como puntos de entrada a las páginas de Facelets que proporcionan la funcionalidad CRUD sobre la base de datos de la aplicación.
2.- Haz click en el vínculo Show All Consultor Items. Tomando en cuenta el código anterior, puedes ver que la página de destino es /consultor/List (En JSF 2.0, la extensión de archivo se infiere debido a la navegación implícita)
Si no olvidaste ejecutar el segundo script de SQL que se encarga de rellenar algunas tablas podrás ver algunos datos, para el caso de Consultores se muestra al menos un registro.
Como podrás ver, las ociones: crear, ver, editar y elimimar son generadas también por el asistente.
Explorar en el Editor de páginas Facelets
1.- Abra el archivo /consultor/List.xhtml en el editor. Línea 8 indica que la página se basa en el archivo Facelets template.xhtml para crearse.
2.- Busca el archivo template.xhtml.
3.- En plantilla se usa la etiqueta
<ui:insert>
para insertar contenido como el título y el cuerpo.
4.- Regresa al archivo List.xhtml (presiona Ctrl-Tab). La etiqueta ui:define ui:define se utiliza para definir el contenido que se aplicarán al título de la plantilla y el cuerpo. Este patrón se utiliza para todos los cuatro archivos de Facelets (Create.xhtml, Edit.xhtml, List.xhtml, y View.xhtml) generados para cada clase de entidad.
5.- Coloca el cursor sobre cualquiera de las expresiones EL que usan los mensajes localizados contenida en el archivo Bundle.properties. Presiona Ctrl-Espacio para ver el mensaje localizado.
6.- Desplazate hasta el final del archivo y busca el código para el enlace Crear nuevo consultor (Línea 92). Este es el siguiente:
7.- Presiona Ctrl-Espacio en la acción del atributo commandLink para invocar el pop-up de la documentación.
El atributo action indica el método que controla la solicitud cuando se hace click en el enlace en el navegador. La siguiente documentación se proporciona:
MethodExpression representa la acción de la aplicación que se invoca cuando este componente es activado por el usuario. La expresión debe evaluar un método público que no toma parámetros y devuelve un objeto (el método toString () se llama para obtener el resultado lógico), que se pasa a NavigationHandler para esta aplicación.
En otras palabras, el valor de acción generalmente se refiere a un método en un bean JSF manejador que se evalúa a una cadena. La cadena es utilizada por NavigationHandler de JSF de remitir la solicitud a la vista apropiada. Podrás verificar esto en los siguientes pasos.
8.- Pon el cursor en consultorController y presione Ctrl-Space. La funcionalidad de completado del editor, indica que consultorController es un bean JSF controlador.
9.- Mueve el cursor a prepareCreate y pulsa Ctrl-Espacio. La función de completado de código enumera los métodos que figuran en el bean ConsultorController.
Explorando la integridad de base de datos con validación de campos
1.- Desde la página con la Lista de Consultores en el navegador, haz click en ‘Create New Consultor». Deberá aparecer el formulario de creación de Consultores.
2.- Ingresa los siguientes datos en el formulario. Por el momento, dejar los campos RecruiterId y StatusId en blanco.
Campo
Valor
ConsultorId
2
Email
jorge.listo@consultores.com
Password
jorge.listo
TarifaPor
75
TarifaPorHoraFacturable
110
FechaContratacion
07/22/2008
Resumen
Soy el mejor ¡Contratame!
ReclutadorId
—
EstatusId
—
3.- Haz click en Guardar. Al hacerlo, un error de validación se marca para el campo EstatusId.
¿Por qué ocurrió esto? Reexamina el diagrama entidad-relación de la base de datos. Como se indica en la tabla de relaciones, CONSULTOR y ESTATUS_CONSULTOR comparten una relación no-nula, uno-a-muchos. Por lo tanto, cada entrada en la tabla CONSULTOR debe contener una referencia a una entrada en la tabla ESTATUS_CONSULTOR. Esto se denota por la clave externa consultor_fk_estatus_consultor que une las dos tablas.
4.- Para superar el error de validación, selecciona entity.ConsultorStatus [EstatusId = A] de la lista de EstatusId desplegable.
Nota: Puedes dejar el campo en blanco RecruiterId. Como se indica en el diagrama de relación, la relación entre CONSULTOR y la tabla de RECLUTADOR puede ser nula, uno-a-muchos, lo que significa que las entradas de CONSULTOR no necesitan estar asociadas con una entrada en RECLUTADOR.
5.- Haz click en Guardar. Aparecerá un mensaje indicando que la entrada consultor se ha guardado correctamente. Si haces click en Show All Consultor Items, verás la entrada que se ha guardado en la tabla.
En general, las páginas Facelets generadas, proveen de errores para facilitar la entrada que el usuario introduce:
* Campos vacíos para campos no-nulas. * Modificaciones a los datos que no puede ser alterados (por ejemplo, las claves primarias). * Introducción de datos que no son del tipo correcto. * Modificaciones a los datos cuando la vista de un usuario ya no está sincronizada con la base de datos.
Editando las Clases de Entidad
En la seccion anterior vimos cómo la lista desplegable de EstatusId no era muy amigable. Quizá ya te has dado cuenta de que el texto que se muestra para cada elemento es una representación en cadena de cada entidad EstatusConsultor encontrada.
Veremos cómo usar completamente el editor de código, documentación y apoyo a la navegación como conclusión. También modificaremos el mensaje que se envía al usuario para que sea más amigable.
1.- Abre el archivo /consultor/Create.xhtml. Este es el formulario Create New Consultor que acabas de ver en el navegador. Desplazate hacia abajo para ver el código del la lista desplegable EstatusId (en negrita a continuación).
2.- Examina el valor aplicado a la etiqueta . El atributo «value» determina el texto que se muestra para cada elemento de la lista desplegable.
3.- Presione Ctrl-Espacio en itemsAvailableSelectOne. La función de completar código del editor indica que getItemsAvailableSelectOne() de EstatusConsultorController devuelve un arreglo de objetos selectItem.
4.- Coloca el cursor sobre el valor de retorno selectItem[] en la firma del método, y pulsa Ctrl-Space para invocar la documentación pop-up.
Si lo deseas haz click en el navegador web (el icono del navegador web) para abrir la documentación Javadoc en un navegador web externo.
Como puedes ver, la clase SelectItem pertenece al freamwork de JSF. El componente de UISelectOne, como se menciona en la documentación, está representado por la etiqueta de que se examinó en el paso 1.
5.- Presiona Ctrl, a continuación, pasa el ratón sobre el metodo findAll(). Un pop-up aparece mostrando la firma del método.
Puedes ver que aquí ejbFacade.findAll() devuelve una lista de objetos ConsultantStatus.
6.- Desplazate sobre a JsfUtil.getSelectItems. Mueve el ratón sobre getSelectItems y presiona la tecla Ctrl, a continuación, haz click en el enlace que aparece.
Nota: Recuerda que JsfUtil es una de las clases de que se genera cuando se completó del asistente para JSF Pages from Entity Classes.
El método que itera a través de la lista de entidades (es decir, la lista de objetos EstatusConsulor), creando un SelectItem para cada uno. Como se indica en negrita a continuación, cada SelectItem se crea usando el objeto de entidad y una etiqueta para el objeto.
public static SelectItem[] getSelectItems(List<?> entities, boolean selectOne) {
int size = selectOne ? entities.size() + 1 : entities.size();
SelectItem[] items = new SelectItem[size];
int i = 0;
if (selectOne) {
items[0] = new SelectItem("", "---");
i++;
}
for (Object x : entities) {
items[i++] = new SelectItem(x, x.toString());
}
return items;
}
La etiqueta se crea usando el método toString(), y es la representación del objeto. (Véase la definición Javadoc para el constructor SelectItem (valor java.lang.Object, java.lang.String etiqueta))
Ahora que has comprobado que es el resultado de toString() es lo que se representa en el navegador al ver los elementos en una lista desplegable, modificaremos el método toString () de EstatusConsultor.
7.- Abre la clase EstatusConsultor en el editor. Modifica el método toString() para devolver el estatusId y descripcion. Estos son corresponden a las dos columnas de la tabla ESTATUS_CONSULTOR.
8.- Ejecuta el proyecto de nuevo. Cuando el navegador muestra la página de bienvenida, haz click en el vínculo Mostrar todos los artículos de consultores, a continuación, haz click en Crear nuevo consultor.
Inspecciona la lista desplegable EstatusId. Verás que ahora muestra el ID de estado y la descripción para el expediente de la que figura en el cuadro ESTATUS_CONSUTOR de la base de datos.
Que tal!, en esta ocasión les traigo este ejemplo de JavaServer Faces 2.0, un «Hola Mundo». Se trata de un ejemplo sencillo para familiarizarse con el framework.
Para hacer el ejemplo necesitas tener instalados previamente:
Para este ejemplo he creado un video que espero te sea de utilidad.
Si tienes problemas para ver el video da click en la opción de Fullscreen que aparece en las opciones de reproducción del YouTube.
Por lo sencillo del ejemplo no he dejado una liga con el código, espero tener ejemplos mas elaborados y dejen claro las capacidades de esta tecnología.
Una de las grandes ventajas de usar NetBeans es que las tecnologias de Sun para Java estan disponibles y bien integradas a la IDE, de tal forma que no es necesario preocuparse por instalar librerias o servidores Web para correr ejemplos o proyectos completos. La gente de Sun se ha preocupado por integrar las tecnologías de mayor uso en el mercado, no importa si no son creadas o promocionadas por ellos mismos. Sin embargo son los Frameworks de Sun los mejor integrados.
JSF 2.0 presentará novedades en cuatro áreas principales: facilidad de desarrollo, desempeño, adopción y nuevas características. Seguidamente un resumen de éstas.
Facilidad de desarrollo: esta área permitirá la creación de componentes por medio de agregación, reducirá la configuración por medio de descriptores, remplazándola por un uso extensivo de anotaciones las cuales se usarán al desarrollar componentes, navigation rules etc. Por último se eliminará el desarrollo de Tag Handlers gracias a la integración con facelets.
Nuevas características: entre las nuevas características se puede ver una expansión del ciclo de vida del request para brindar soporte a peticiones Ajax, además se ofrecerá soporte de primera clase para el manejo de los recursos utilizados por los componentes JSF.
Desempeño: se propone renderizar deltas de los componentes JSF según se necesite en lugar de un renderizado completo de los componentes, se mejorará el manejo de eventos mediante PhaseListener y los componentes serán sin estado por defecto.
Adopción: para tener una mejor adopción JSF pretende mejorar la interoperabilidad entre librerías de diferentes vendedores, se agregará soporte para JSR 311, Skinning o Themeing entre otros.
Seguramente sabes que significa Captcha . Bueno yo tampoco sabía, según Wikipedia es el acrónimo de Completely Automated Public Turing test to tell Computers and Humans Apart ó Prueba de Turing pública y automática para diferenciar máquinas y humanos.
En algunas ocasiones te habrás topado con algún formulario donde aparece una imagen extraña donde debes teclear un código que en teoría solo un humano puede reconocer. De esta forma se evita que robots entren y agreguen publicidad indeseada de forma automática en comentarios de blogs o en algunos foros.
Haremos un ejemplo sencillo para mostrar esta funcionalidad, desde luego Struts2 no tiene un método directo para hacerlo y de hecho la solución que damos puede ser usada sin ningún framework, pero aun asi veremos como se configura el Action para recibir la respuesta del usuario.
Para este ejemplo debes descargarte la libreria SimpleCaptcha-1.1.1.jar y agregarla junto con las demas librerias de tu proyecto. La puedes encontrar y descargar aqui:
Este proyecto creado por James Childers es sencillo y fácil de utilizar, permite crear la imagen con el código de verificación utilizando un servlet que debe darse de alta en el archivo web.xml de nuestro proyecto.
Puedes ver que solo agregamos un servlet, sin embargo, la librería SimpleCapcha tiene algunas opciones mas para soportar tamaños especificos de imagenes y juegos de caracteres.
Aqui te muestro la clase Action que usaremos: AccionValidarCodigo.
public class AccionValidarCodigo extends ActionSupport {
@Override
public String execute() throws Exception {
HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(org.apache.struts2.StrutsStatics.HTTP_REQUEST);
HttpSession session = request.getSession();
Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME);
request.setCharacterEncoding(«UTF-8»);
String answer = request.getParameter(«answer»);
if (captcha.isCorrect(answer)) {
return SUCCESS;
} else {
addActionError(«Código inválido, trate nuevamente.»);
return ERROR;
}
}
}
Como puedes ver, el servlet que dimos de alta guarda en la sesión la variable que será cotejada con el dato de entrada del formulario.
Puedes ver que es muy sencilla, lo importante que debes notar es que el servlet de SimpleCaptcha es la que se encarga de generar la imagen con el código de verificación, siempre y cuando la llames igual que como la definiste en el archivo web.xml, es
Usaremos dos JSPs parar este ejemplo, el que se encarga de mostrar el sencillo formulario y el que muestra el mensaje de validación exitosa.
En este ejemplo veremos nuevamente el uso interceptores, como ya hemos mencionado en otros post, Struts2 posee una amplia gama de funciones que permiten hacer mas ágil el desarrollo y que están puestas a disposición de los desarrolladores a través de los interceptores que vienen por default.
En esta ocasión veremos un interceptor que nos permite realizar una de las funciones con la que comúnmente nos topamos en el desarrollo de aplicaciones empresariales, se trata de la carga de archivos.
El interceptor FileUpload está dado de alta en la pila de interceptores del paquete default que maneja Struts2.
Si ya tenemos configurado nuestro proyecto solo es necesario agregar estas librerías:
commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
Si no recuerdas que otras librerías son requeridas o como configurar tu proyecto para usar Struts2 puedes regresar al primer ejemplo que vimos en este mismo blog sobre como hacerlo:
public class AccionCargaArchivo extends ActionSupport { private File archivo; private String archivoContentType; private String archivoFileName; private String datos = "";
public String execute() { try{ BufferedReader entrada = new BufferedReader( new FileReader( archivo ) ); if ( archivoContentType.equals("text/plain")){ String aux; while((aux = entrada.readLine()) != null){ datos += aux + "n"; } } }catch(Exception e){ e.printStackTrace(); } return SUCCESS; }
public File getArchivo() { return archivo; }
public void setArchivo(File archivo) { this.archivo = archivo; }
public String getArchivoContentType() { return archivoContentType; }
public void setArchivoContentType(String archivoContentType) { this.archivoContentType = archivoContentType; }
public String getArchivoFileName() { return archivoFileName; }
public void setArchivoFileName(String archivoFileName) { this.archivoFileName = archivoFileName; }
public String getDatos() { return datos; }
public void setDatos(String datos) { this.datos = datos; } }
Del la clase Action anterior observa cuidadosamente las siguientes variables:
File nombreDeArchivo;
String nombreDeArchivoContentType;
String nombreDeArchivoFileName;
Como puedes ver la variable de tipo File tiene un nombre arbitrario, sin embargo las otras dos deben cumplir con un formato establecido para que el interceptor pueda encontrarlas y establecer los datos correspondientes al tipo de contenido y al nombre del archivo.
archivo – Es el nombre del archivo.
archivoContentType – Contiene el tipo de contenido del archivo.
archivoFileName – Contiene el nombre del archivo tal como fue almacenado en el servidor.
Esto es todo lo que debe hacerse para que el Framework a través del inteceptor tome el archivo y lo relacione con las variables que declaramos en el Action.
También haremos la jsp de respuesta, que solo mostrará algunos datos del archivo que se esta subiendo al servidor.
El código es el siguiente:
<%@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"> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h1>El archivo fué recibido con exito!</h1> El tipo del contenido es : <s:property value="archivoContentType"/><br> Nombre del archivo es : <s:property value="archivoFileName"/><br> Nombre del archivo temporal : <s:property value="archivo.name"/><br> Contenido del archivo :<br> <s:textarea name="dat" value="%{datos}" cols="50" /> </body> </html>
y por último haremos cambios necesarios en el archivo de configuración de Struts2 para hacer referencia a las clases y jsps que acabamos de crear.
Si corres el ejemplo y mandas llamar al formulario de carga de archivo debe aparecerte algo como lo siguiente:
formularioDeCargaDeArchivo.jsp
Como puedes ver nos aparece el campo para especificar el archivo que queremos subir.
Para este ejemplo solo cargaremos archivos de texto plano y visualizaremos el contenido.
Damos click en el boton de Subir y tendremos una respuesta como esta:
En esta jsp mostramos el tipo de datos del archivo, el nombre del archivo y el nombre que tendrá temporalmente en el servidor mientras es procesado durante el tiempo que se ejecute nuestra acción.
Despues mostramos simplemente el contenido. Listo ya tenemos el ejemplo.
Es importante que sepas que el archivo temporal se removera del servidor una vez que el ciclo de llamada a la acción termine.
Espero que te sirva este ejemplo, si tienes alguna duda o comentario hazmelo saber. Hasta el proximo post.
La siguiente es una comparación tomada y traducida de la página de Rose India, un pequeño articulo que anima a los desarrolladores de Struts1 a comenzar a usar Struts2
Les pongo la liga de la página.
También puedes encontrar muchos otros ejemplos de programación en Java.
Struts1 vs Struts2
Clases Action
Struts1
Se Requiere extender de la una clase Action abstracta. El problema común en Struts1 es que se programan clases abstractas en lugar de interfaces.
Struts2
Un Action puede implementar una interfaz Action, además de otras interfaces que le permitan integrar mas servicios. Struts2 provee de una clase base ActionSupport que implementa las interfaces comúnmente usadas. Además esta interfaz no es requerida. Cualquier POJO con un método de ejecución puede ser usado como Action en Struts2
Modelo de hilos
Struts1
Las Actions implementan el patrón singleton y deben ser thread-safe por lo que puede haber solo una instancia de una clase para manejar todas las peticiones para ese Action. La estrategia singleton pone restricciones sobre lo que podemos hacer con los Actions de Struts1 y se requiere un cuidado extra para desarrollar. Los recursos usados para los Actions deben ser thread-safe o sincronized.
Struts2
Los objetos Action son instanciados por cada petición, por lo que no hay problemas de tipo con la seguridad de hilos. En la práctica, los contenedores de servlets generan muchas instancias, así que un objeto mas no representa problemas de rendimiento y de impacto en el garbage collection
Dependencia de los Servlets
Struts1
Las Actions tiene dependencias de la API de Servlets dado que HttpServletRequest y HttpServletResponse son pasados al método excecute cuando la Action es invocada.
Struts2
Las Actions no están acopladas al contenedor. A menudo el contexto de los servlets esta representado por simples Maps, permitiendo a las Actions ser probadas de forma aislada. Las Actions de Struts2 puede mantener el uso del request y el response si se requiere. De cualquier forma, otros elementos de la arquitectura reducen o eliminan la necesidad de acceder a HttpServetRequest o a HttpServletResponse directamente.
Manejo de pruebas
Struts1
El principal obstáculo para las Actions de Struts1 es que la ejecución de métodos requiere de la API de Servlets. Una extensión de terceras partes, como Struts TestCase, que ofrece un conjunto de simuladores para objetos de Struts1.
Struts2
Las Actions pueden ser probadas instanciado la Action, estableciendo propiedades e invocando métodos. El soporte a la Inyección de Dependecias permite hacer las pruebas de forma simple.
Recolección de datos de entrada
Struts1
Es necesario el uso de un objeto ActionForm para capturar las entradas. Como las Actions, todos los ActionForm deben extender de una clase. Como algunos JavaBeans no implementan de ActionForm los desarrolladores a menudo crean clases redundantes para capturar a las entradas. Los DynaBeans pueden ser usados de forma alternativa para crear clases ActionForm convencionales, pero, los desarrolladores deben JavaBeans existentes.
Struts2
Usa las propiedades de las Actions para manejar las entradas, elimina la necesidad de un segundo objeto de entrada. las propiedades de entrada pueden ser objetos de una amplia variedad que incluso pueden tener sus propias variables. Las propiedades de las Action pueden usadas por la pagina Web por medio de los TagLibs. Struts2 soporta incluso el patrón de ActionForm, asi como objetos y acciones POJO. Tipos de objetos, incluyendo negocios o objetos de dominio, pueden ser usados como objetos en entrada y salida. La característica ModelDriven simplifica las referencias por taglib a objetos POJO.
Lenguaje de Expresiones
Struts1
Esta integrado con JSTL, así que usa el JSTL EL. El EL tiene una traza grafica de objetos básica y una relativamente pobre colección e indexación de soporte a propiedades.
Struts2
Puede usarse JSTL, pero el marco de trabajo soporta ademas un lenguaje de expresiones mas poderoso y flexible llamado «Object Graph Notation Language» (OGNL)
Vinculación de objetos de la vista
Struts1
Usa el mecanismo estándar de JSPS para el vincular objetos en el contexto de las páginas.
Struts2
Usa una tecnología llamada «ValueStack» donde los taglibs pueden acceder a valores sin estar acoplados a la vista donde el tipo de objeto se renderea. La estrategia del «ValueStack» permite reutilizar vistas gracias al rango de variables que pueden tener el mismo nombre pero tipo diferente tipos de propiedades.
Conversion de tipo
Struts1
Las propiedades de los ActionForm son usualmente Strings. Struts1 usa comúnmente Commons-Beanutils para la conversión de tipos. Las conversiones son configurables por clase y no por instancia.
Struts2
Usa OGNL para la conversión de tipos. El marco de trabajo incluye convertidores para objetos básicos y tipos primitivos.
Validación
Struts1
Soporta validación manual por medio de métodos en el ActionForm, o a través de una extensión de los Commons Validator. Las clases pueden tener diferentes contextos de validación para la misma clase, pero no pueden encadenar validaciones en sub objetos.
Struts2
Soporta validación manual por medio de métodos y por el marco de trabajo XWork Validation. El XWork soporta encadenamiento de validaciones en las subpropiedades usando las validaciones definidas para las propiedades de la clase y el contexto de validación.
Control de la ejecución del Action
Struts1
Soporta Request Porcessors (Ciclos de vida) separados por cada módulo, pero todas las Actions en el módulo deben compartir el mismo ciclo de vida.
Struts2
Soporta ciclos de vida diferentes, uno por Action por medio de la pila de interceptores. Pilas configurables pueden ser creadas y usadas con diferentes Actions si es necesario.
Esta es una tabla excelente para observar solo algunas de las mejoras en Struts2, sin embargo yo pondría especial énfasis en las ventajas que ofrecen los interceptores en Struts2, ya que permiten aislar gran parte de operaciones de control que son comunes en todas las aplicaciones Web, entre ellas una muy importante, el manejo de la sesión y la restricción de acceso a usuarios con permisos. Aislando estas operaciones es mas fácil reutilizar el código en otras aplicaciones.
Además los interceptores que vienen por default en el marco de trabajo resuelven y aislan una gran cantidad trabajo, como carga de archivos, validaciones, intenacionalizacion y mas. Solo tendremos que usar lo que los desarrolladores de Struts2 ponen a nuestra disposición.
Espero que este post les sea de utilidad, no olviden dejar sus comentarios si tienen alguna duda sobre los ejemplos o si tienen alguna sugerencia para el blog.
En este ejemplo, el segundo de Struts2, veremos como restringir el acceso a páginas privadas mediante el uso de la sesión y de los interceptores, también mostraremos como desplegar una lista de resultados utilizando las etiquetas de Struts2.
Antes de comenzar es necesario tener a la mano el código del ejemplo anterior pues lo usaremos como base, puedes verlo dando click acá:
Haremos algunos cambios en el código, pero es necesario que notes algunas cosas que el primer ejemplo adelantaba sobre el manejo de la sesión.
Como podrás ver la clase AccionEntrar.java esta extendiendo de ActionSupport y también se implementan los métodos de la interfaz SessionAware, esta última es la que nos permitirá hacer uso de la sesión dentro del marco de trabajo.
public class AccionEntrar extends ActionSupport implements SessionAware{
private Map session;
private String mensajeError;
private String usr;
private String pas;
…
Al implementar SessionAware se definen los métodos:
public Map getSession() {
return session;
}
public void setSession(Map session) {
this.session = session;
}
y desde luego declaramos la variable session, que es de la clase Map.
En nuestra clase AccionEntrar verificamos los datos del usuario. De ser válidos daremos acceso a la página de bienvenida, si son incorrectos redirigimos a la página de entrada nuevamente. Todo este flujo también esta definido en nuestro archivo de configuración struts.xml.
Pero que pasa si ahora queremos que en nuestra aplicación se despliegue una lista de datos privados que solo pueda verse después de una autenticación válida, mostraremos como hacer eso. Comencemos por agregar una liga para desplegar una lista de usuarios en nuestra página de bienvenida.
Después de la etiqueta de bienvenida agrega esta línea:
<s:a href="DesplegarLista.action">Desplegar lista de productos</s:a>
El código de tu jsp deberá quedar así:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!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>Pagina de Bienvenida</title>
</head>
<body>
<h1>Bienvenido, has entrado al sistema!</h1>
<s:a href="DesplegarLista.action">Desplegar lista de usuarios</s:a>
</body>
</html>
Utilizamos cookies para asegurar que damos la mejor experiencia al usuario en nuestro sitio web. Si continúa utilizando este sitio asumiremos que está de acuerdo.