domingo, 27 de noviembre de 2016

Cargue de archivos planos en bases de datos desde un Portal Web

Es muy usual encontrar usuarios encargados de procesos funcionales, los cuales requieren periódicamente realizar cargues de información a las bases de datos de una organización. Para ello existen muchas alternativas, desde enviarle directamente el archivo al administrador de la base de datos para que él realice el cargue, hasta el desarrollo de un portal simple que le permita al usuario realizar dicho cargue por su cuenta.

En esta entrada quiero resaltar las partes más importantes de un desarrollo en el que trabajé recientemente y que ataca esta necesidad. Básicamente se ha construido una página web que permite alojar el archivo seleccionado por el usuario y lo ubica en una carpeta temporal dentro del servidor Web. Posteriormente, una tarea programada se encarga de enviar dicho archivo al servidor de base de datos usando FTP. Una vez en el servidor de base de datos, otra tarea programada se encarga de leer y registrar los nuevos archivos cargados por el usuario. Finalmente se lee cada uno de los archivos y se realizan los cargues en las tablas finales.

Paso 1. Envió de archivos desde un Servidor Web (Windows) a uno de Base de Datos (Linux) usando FTP.

Se debe crear una carpeta temporal dentro del servidor web que contendrá dos archivos. En el primero estará la declaración de la tarea FTP (Esta linea debe ir en un archivo de extensión .BAT y puede ser llamado directamente desde la aplicación web o por medio de una tarea programada):

ftp -n -s:c:\interfases\ftp_masiva.txt

Y en el segundo está la definición de la misma (siguiendo este ejemplo, este archivo deberá llamarse ftp_masiva.txt):

open
SERVER_DESTINO
user USUARIO_FTP PASSWORD_USUARIO_FTP
prompt off
lcd "URL_ORIGEN"
cd URL_DESTINO
mput *.*
bye

Importante:

- La carpeta destino debe estar correctamente configurada para aceptar el protocolo FTP. Se recomienda apoyarse para esto en un buen DBA.
- Si la URL origen es de un servidor Windows, esta debe estar entre comillas.
- Con el comando mput se pasan TODOS los archivos que estén en la carpeta origen y se mueven a la carpeta destino.

Paso 2. Registrar los archivos dentro de la base de datos.

Este ejemplo se ha realizado para un motor de base de datos Oracle, el cual según mi investigación, no contiene funciones o librerías que permitan saber los nombres de los archivos en un directorio dado. Para ello entonces, usaremos una clase Java propia que incluiremos en el motor y que será usada para esta tarea:


La clase DirList recibe por parámetro un directorio (debidamente registrado en la tabla SYS.ALL_DIRECTORIES) y, luego de aplicar algunas reglas de negocio, inserta los nombres de los archivos que serán procesados en una tabla creada para ello.

Una vez realizado el anterior punto, se debe acceder a esta funcionalidad por medio de un procedimiento de base de datos:


El procedimiento get_dir_list recibe nuevamente el directorio al cual queremos consultar y se lo pasa por llamado a la clase Java anterior.

Paso 3. Procesamiento de la información.

Contando ya con los nombres de los archivos a procesar en una tabla, se puede proceder a, por ejemplo, realizar el cargue de la información en una tabla. Una vez cargado un archivo, se pueden hacer muchas cosas con él, como por ejemplo borrarlo de la tabla temporal o moverlo a otra carpeta que lleve le histórico de cargues (para ello se pueden usar los métodos UTL_FILE.REMOVEUTL_FILE.COPY). También se puede notificar al usuario de que el archivo ha sido procesado o ha terminado en error, usando algún paquete que envíe notificaciones por correo electrónico.

Puede que esta forma de realizar el cargue tenga muchas desventajas: El uso de tareas programadas y la configuración de permisos que puede ser problemática si no se cuenta con el apoyo de los administradores, pero es una forma rápida y relativamente sencilla de quitarnos de encima una tarea que debe ser de los usuarios y no de TI.

domingo, 30 de octubre de 2016

Scrum: Hacia la Agilidad

Scrum es un marco de trabajo para el desarrollo y mantenimiento de productos complejos. Se autodefine como ligero (el documento La Guía de Scrum solo consta de 17 páginas), fácil de entender (las reglas de Scrum son sencillas de interpretar), pero extremadamente difícil de llegar a dominar.

El objetivo de esta entrada es ayudar a todos los interesados en Scrum a solventar ese último punto. Si bien es cierto que dominar un marco de trabajo requiere en gran medida de experiencia y práctica, también se requiere no pasar por alto detalles importantes de Scrum que a menudo no suelen ser muy tenidos en cuenta por aquellos que lo practican. A continuación, algunos ejemplos:

  • Los equipos de desarrollo Scrum no contienen sub-equipos dedicados a dominios concretos como pruebas o análisis de negocios. Cualquier miembro de Scrum debe estar en la capacidad de ejecutar tareas de diversa índole tecnológica.
  • Aunque es preferible que las personas encargadas de los roles de Scrum Master y Product Owner no participen como miembros del equipo de desarrollo, estos pueden hacerlo y entran a computar en la medición del tamaño del equipo de desarrollo. Se recomienda que sea de entre 3 y 9 miembros.
  • El Sprint Backlog no es únicamente un subconjunto de elementos del Product Backlog seleccionados por el equipo de desarrollo, sino que también es un plan de trabajo que detalla como el equipo de desarrollo convertirá dichos elementos en un incremento de Producto.
  • En cada Daily Scrum se valida el progreso del equipo de desarrollo hacia el cumplimiento del objetivo del Sprint.
  • En cada Sprint Review el Product Backlog valida el progreso del equipo Scrum hacia el cumplimiento del objetivo del producto (de manera global).
  • Un Product Backlog nunca está completo. Mientras el producto este vivo, existirá su correspondiente Product Backlog.
  • Scrum no tiene en cuenta el tiempo empleado en trabajar los elementos de Sprint Backlog. El trabajo restante y la fecha de entrega son las únicas variables de interés.

El anterior conjunto de afirmaciones son extraídas directamente de La Guía de Scrum, escrita por Ken Schwaber y Jeff Sutherland. La probabilidad de que preguntas relacionadas a estos puntos aparezcan en el examen de certificación como Scrum Master es bastante elevada.

¿Tienes algunos otros aspectos que consideres importantes y a veces pasados por alto? Compártelos por favor en los comentarios de esta entrada.

domingo, 15 de mayo de 2016

Centrar título en plantilla de Blogger

Cuando se crea un blog en un sitio como Blogger, es común que se desee personalizar el mismo con detalles a gusto del autor. Uno de esos posibles cambios es la de poner una imagen de fondo en el header (a modo de banner) y también la de contar con un título específico para todo el sitio.

El definir la imagen de fondo, así como el título, es relativamente sencillo. Lo que no lo es tanto (dependiendo de la plantilla seleccionada), es la de centrar el título. Por ejemplo, para la plantilla Fantástico, S.A. , el título por defecto se ubica en la parte superior izquierda del banner.

Para centrarlo, se pueden seguir los siguientes pasos (existen muchas formas de hacerlo, lo acá mostrado es solo una de muchas posibilidades):

1. Inspeccionar el elemento que se desea centrar, en este caso del título, con la ayuda de un navegador moderno, como Chrome o Edge.

2. Determinar cual o cuales son las clases CCS que afectan al elemento. En este caso en particular, el título de la plantilla se ve afectado por las clases titlewrapper y title.


3. Ir al editor HTML de la plantilla. La ruta para llegar a él es Plantilla y después se da clic en el botón Editar HTML.

4. Incluir en la sección CSS de la plantilla los selectores y propiedades necesarios para que nuestra sitio cambie según lo que deseemos. Para este ejemplo en particular, solo es necesario agregar las siguientes líneas:

.titlewrapper{
  margin-top: 10em;
}
.titlewrapper .title{
  text-align: center;
}

5. Para finalizar, se da clic en el botón guardar plantilla y se validan los cambios en el blog.

Es posible editar tanto el HTML y el CSS de nuestro blog directamente en el editor (es decir, empezar desde el punto 3) pero es más sencillo primero visualizar la disposición final de los elementos por medio de un navegador, para posteriormente editar estrictamente lo necesario en la plantilla y así evitar dañarla.


domingo, 31 de enero de 2016

Ajustar tamaño de Iframe automáticamente según su contenido

Aunque hoy en día con las recomendaciones de la W3C lo común es no utilizar Iframes, estos aún continúan vigentes. Es normal que dentro de un Iframe se invoque a un recurso externo de nuestro sitio (usualmente vídeos de YouTube o paginas similares). 

En un desarrollo en el que estuve trabajando el año pasado me vi en la necesidad de crear un "Wizard", el cual guiaba al usuario a través de ciertas paginas para que diligenciara información. Si bien hubiera podido utilizar algún plugin de JQuery para esta tarea, la decisión final que se tomó para este desarrollo fue la de crear una pagina en HTML5 que contuviera un Iframe y, dentro de este, se irían mostrando de manera dinámica las paginas que contienen los formularios (Esto por motivos de la tecnología en la cual estaba construido dicho portal y para evitar problemas de compatibilidad).

El problema de fondo al cual me enfrenté fue la de ir ajustando en tiempo de ejecución la altura del Iframe (se definió un ancho fijo por motivos de diseño). En Internet existen muchas fuentes dispersas que pueden ayudar en la construcción de un desarrollo como este, pero no encontré una fuente que brindara una forma sencilla y completa que me diera la solución exacta a lo que buscaba. El motivo de esta entrada es, entonces, resumir el desarrollo que realice y compartirlo con cualquier persona que pueda encontrarlo útil.

Lo primero que se debe construir es el Iframe dentro de la página principal. Los estilos iniciales se pueden definir en un CSS adjunto, pero como veremos mas adelante, la propiedad de la altura cambiará de forma dinámica.



La lógica de este desarrollo a grandes rasgos es la siguiente: Por medio de JavaScript se irán cambiando las paginas internas del Iframe según las decisiones que tome el usuario. Justo en ese momento, el Iframe ejecutará el método autoResize(this) dentro del cual se calculará la altura en PX del scroll generado por la nueva pagina. Acto seguido, el valor de esa medida se le asignará a la altura del Iframe:


Las lineas que hacen la asignación para Google Chrome, Mozilla y los demás navegadores (a excepción del siempre problemático Internet Explorer) son la 14 y la 15. Para Explorer, la linea que realiza el mismo trabajo es la linea 9.

Para finalizar y para aquellos que no sepan como asignar el contenido de un Iframe desde JavaScript, les dejo la siguiente imagen:


Comprendo que esta es una solución muy sencilla que se puede quedar corta para otro tipo de requerimientos y que, ademas, utilizando librerías modernas de JavaScript es posible realizar el mismo trabajo con muchas menos lineas. Sin embargo, considero que es un buen punto de partida para aquellos que deseen soluciones mas robustas.

lunes, 2 de noviembre de 2015

Java - Librería para lectura de XML (SAXParser)

Es muy común encontrar en aplicaciones Java y de otros lenguajes, que la ejecución y estructura de las mismas se encuentran definidas en archivos XML. Gracias al framework definido por el Ingeniero Pablo Augusto Sznajdleder en su libro Java a fondo, ahora es posible consumir estos valiosos recursos de una manera fácil y rápida.

A continuación, comparto con ustedes la librería resultante de la implementación del código estipulado en la obra de Sznajdleder y su funcionamiento:

1. Importar el .jar en las librerías externas del proyecto donde se desee consumir (Enlace de descarga).
2. Ubicar el recurso XML que se desea consumir dentro de la carpeta del proyecto (es común que los archivos .properties y de configuración de portabilidad entre bases de datos, ya estén incluidos dentro de la carpeta del proyecto)
3. Realizar el consumo del servicio, dependiendo de lo que se desea.

Con el siguiente ejemplo quedará todo más claro. Dado el siguiente XML de prueba, vamos a obtener los valores de algunos atributos de la etiqueta conection-pool y la totalidad de los campos de la tabla EMP.




  • Obtener los valores de los atributos de alguna etiqueta en particular:

La salida de la ejecución del anterior programa será:


  • Obtener los hijos de una etiqueta particular de un tag:

Y nuevamente, la salida del programa anterior será:


Como recomendación general para el uso de esta librería se recomienda tener cuidado con la "ruta" de navegación (variable path de ambos programas), puesto que es la base que utiliza la clase SAXParser de Java para hacer el consumo del archivo XML y cargar la totalidad de los nodos en memoria. Esta es una primera versión de una librería que puede dar mucho más y estaré pendiente de comentarios y oportunidades de mejora que podamos aplicarle.




viernes, 16 de octubre de 2015

Excel VBA - Copiar Filas en Excel con una Macro

Hace poco tuve un requerimiento en el cual debía generar un reporte con Excel a partir de una plantilla base. El core del asunto es que no podía saber de antemano cual era la cantidad de registros que iba  a tener el reporte y las filas del mismo debían contar con un formato especial.

Consideré que se veía horrible si dejaba simplemente toda la hoja de Excel con el formato preestablecido (este consistía en celdas con bordes, algunas con fondos de diversos colores, formatos de fecha y de contabilidad), así que decidí ubicar en la plantilla una única fila con dichos formato y, en tiempo de ejecución, replicar esa fila "base" tantas veces como fuera necesario.

Para ello, desde el sistema que hace las veces de modelo y control de este desarrollo, incluí una linea adicional que agregaba en una celda especifica de la hoja de Excel la cantidad de registros que debía incluir el reporte.

La macro resultante que deseo compartir es la siguiente:


Como es de suponer, en la variable cant se recoge el valor que indica la cantidad de filas en las cuales esta macro debe replicar el formato. La variable val indica la fila en la cual se comienza a replicar el formato (la fila base es la 3 y en esa fila también va información, por eso se resta 1).

Luego del bucle que replica el formato de la fila, se borra de la celda B1 el valor que indicaba la cantidad de registros del reporte.

Esta forma de replicar formatos de fila puede ser muy simple cuando no se tenga precisamente un formato fijo (en este caso, se aprovechó que el reporte siempre empezaba en la columna B y acababa en la columna V) pero se pueda extrapolar a otros escenarios.

Si alguien que lea esta lineas puede encontrar la forma de realizar la misma acción sin necesidad del bucle, le agradecería que nos compartiera su solución.

domingo, 11 de octubre de 2015

Java - Concatenar cadenas con +: Un pecado mortal

Recientemente he estado revisando los apuntes y algunos libros de programación para retomar mi trabajo en Java. Una de las primeras anotaciones importantes que encontré en dicha información es la que resalta el uso de las clases StringBuffer y StringBuilder.

Supongamos que se tiene la siguiente clase, cuyo único propósito es concatenar un conjunto de 100000 caracteres en un único objeto String:



Como se puede apreciar, la concatenación se realiza con el operador +. Luego de ejecutar dicho programa, se puede verificar que el tiempo de ejecución del mismo el de alrededor de 9000 ms (existía en algunos casos cierta variabilidad de unos 200 a 300 ms que no comprendo aún porque ocurre). Tal y como en mis libros ponía, decidí verificar el rendimiento del mismo programa pero usando las clases mencionadas en el título de esta entrada. Las versiones fueron las siguientes:


Los resultados obtenidos fueron una descomunal diferencia de tiempo entre el concatenar por medio del operador + y el uso de las clases StringBuilder y StringBuffer. Ya que en algunas veces existía diferencia entre las ejecuciones, decidí ejecutar cada programa en 5 ocasiones y después resumir los resultados en una tabla, la cual muestro a continuación:


Como es evidente, el uso del operador + aumenta dramáticamente la ejecución de una clase sencilla como la que se ha tomado de ejemplo. Las clases StringBuffer y StringBuilder son la forma más adecuada de realizar una concatenación, sobre todo en proyectos donde el trabajo con caracteres sea fundamental. De momento, el pecado de concatenar con + solo debería ser ‘permisible’ en una que otra línea de código… como para imprimir un resultado en un out.println… ¿o no?

Para una próxima entrada, diferenciaremos entre StringBuffer y StringBuilder.