lunes, 7 de septiembre de 2015

PROYECTOS PARA LO QUE RESTA DEL 2015

Saludos a todos las personas que leen el blog y que me escriben, mencionan, taggean en las redes sociales, etc... y, bien, el motivo de éste post -no técnico- es para comentar el plan que tengo en referencia a los temas en los que me centraré y desarrollaré, así como la estrategia de difusión que he decidido emplear en el blog por lo que resta del año.

Puntos importantes.

1) Mucha  mucha gente me escribe solicitando ayuda en el lenguaje java, y dichas dudas muchas veces implican cuestiones como: configuraciones (de las aplicaciones como tal, IDE, descriptors, etc.), obtención de librerías, etc., y, trato de ayudar, pero, al ver la recurrencia en éstos problemas en mis followers, he decidido cambiar de metodología de enseñanza, pues pese a que trato de que los artículos que posteo sean lo más explicitos y didácticos, noto que hay restricciones en llegar a la gente entre un artículo escrito Vs un video detallado, donde, paso a paso se vea lo que uno debe hacer; por tanto, he decidido que la modalidad con la que trabajaré serán video tutoriales, es los que estoy seguro puedo ser mucho más explicito y será mucho más fácil prender así.

2) Hay dos temas puntuales en los que me centraré en el blog por lo que resta del año y estoy seguro que abarcaré potencialmente el primer trimestre del año que viene:
  • Firma Electrónica. Este tema me parece tremendamente interesante y lo había pospuesto por cuestiones laborales, pero, precisamente por mi trabajo tuve que usar firma electrónica en una aplicación y, bien, pretendo indicar cómo se debe usar, o al menos dar una guía por donde debería llevarse éste tema pa los que lo requieran.
  • JEE7. Considerando que un 99% de las preguntas que me llegan se centran en el tema java (empresarial), he decidido empezar una serie de video tutoriales centrados en el tema JEE7 y me he propuesto hacerlo, empezando desde temas básicos como: instalación del IDE, descarga de herramientas, configuraciones, etc., hasta ejemplos de la vida real, patrones etc. 
    • Los  temas que planeo incluir son: las tecnologías standar parte del stack JEE7 (JPA, EJB, Web Services, Web Sockets, etc.)
    • Para el front end potencialmente decida deshacerme de JSF e ir por algo un poco más actual como Angular.
    • El servidor de aplicaciones sin dudar será WildFly. 
NOTA 1: Espero sus comentarios y sugerencias (que como siempre son leídos y bien aceptados).
NOTA 2: Si el 99% de preguntas son sobre java, ¿a qué se refiere el 1% restante?. No voy a entrar en detalles pero casi siempre son preguntas personales jejeje.

Gracias.

martes, 3 de marzo de 2015

Usando una relación @ManyToMany (JPA) desde JSF

Antecedentes 

El relevante rol de JPA (Java Persistence API) en cualquier aplicacion java es innegable, desde aplicaciones de escritorio hasta el ambito empresarial JEE; es por ésto que el presente post pretende abordar la relación ManyToMany (una de las anotaciones de mapeo que JPA tiene para relacionar el mundo orientado a objetos con el mundo de tablas relacionales de base de datos).

En forma general JPA es un API destinado a la persistencia de datos es decir,  sirve de puente para poder interactuar entre las tablas de una base de datos con un mundo orientado a objetos y mediante un proveedor de persistencia (Hibernate, EclipseLink, TopLink, etc) poder conseguir manipular la informacion que formará parte de las tablas.

Una de las piezas clave para trabajar con JPA son las entidades, que basicamente son la representación en código java de una tabla de la base de datos (claro usando anotaciones especiales para ello). JPA usa un EntityManager que en definitiva es quien se encarga de adminstrar las Entidades y a su cargo tambien está el hacer posible acciones como: crear, borrar, actualizar, etc.; pero lo repito, todo ésto es posible gracias a un proveedor de persistencia pues JPA como tal no puede trabajar si no cuenta con un proveedor de persistencia, de ahí que un error común es pensar que JPA es igual o podría trabajar autónomamente tal cual  una herramientas ORM como Hibernate, y hay que dejar en claro que JPA es la especificación para peristencia en Java, mientras que Hibernate, Toplink, EclipseLink son proveedores de persistencia, es decir implementan lo que la especificación de persistencia define.

Hablando de JPA surgen algunas dudas comunes:

¿Por que Java no usa un proveedor de peristencia propio de JPA?. 
Porque eso precisamente refuerza la idea de libertad en uso de software libre, es decir, que el propio desarrollador decida cuál es la mejor implementación (o proveedor de persistencia) que se ajuste a sus necesidades.

¿Cual es el mejor proveedor de persistencia?
Hibernate por la experiencia y recorrido que tiene probablemente podría ser la mejor elección al momento de definir el proveedor de persistencia, pues de heho sirvió como blueprint para la definición de JPA, y no lo niego, Hibernate es una muy buena alternativa, sin embargo, por la experiencia propia de trabajar con EclipseLink debo decir que he tenido muy buenos resultados, por tanto queda a criterio de cada desarrollador el uso del proveedor de persistencia.

¿La peristencia en Java se consigue unicamente con JPA?
No, existen diversas tecnologías como la tradicional JDBC, harramientas ORM como Hibernate, el proyecto Apache Cayenne, Data Nucleous, etc.

Manos a la obra:
Como lo mencióne antes, el presente post se enfoca en la relación ManyToMany pues la misma supone un poco más de esfuerzo que las relaciones tradicionales @OneToOne, @OneToMany... sin embargo si el tema de persistencia es interesante para la comunidad (y si me lo hacen saber) podría escribir mas posts sobre cada una de ellas tanto unidireccional como bidireccionalmente.

El objetivo de éste post es lograr almacenar información de una relacion ManyToMany entre dos tablas desde una aplicacion web empresarial JEE.

En términos generales la relación se puede esquematizar como lo demuestra la siguiente imagen, donde es notorio el relacionamiento entre dos tablas (A y B) y una tabla intermedia de relacionamiento (A_B):

Nuestro caso de uso de ejemplo sera una anulación de documento en el que se pueda seleccionar multiples errores para dicha anulación, es decir, muchas anulaciones de documento pueden contener varios errores (escenario típico de una relacion Many To Many).

Nuestras tablas son las siguientes: ANULACION, ERROR y la tabla de rompimiento ANULACION_ERROR. Considérese que tanto ANULACION como ERROR deben tener bien definida su clave priaria (que posterioremente se transladara a la tabla de rompimiento).




La tabla ANULACION_ERROR (como se muestra en la siguiente imagen), se compone de dos claves foráneas, transladadas desde las tablas ANULACION y ERROR.


NOTA: Si decidimos que JPA realicé el mapeo de una relacion ManyToMany desde código java para que  generen las tablas de la base de datos  de manera automática, JPA seguirá estándares de generación (como muestra la siguiente imagen): El nombre de la tabla de rompimiento se formará por la unión de las dos tablas de los extremos por ejemplo, entre una tabla A y una tabla B, la tablade rompimiento se llamará A_B; y JPA generará automáticamente una key por las dos claves foráneas heredadas (mírese la imagen SYS_C0069738) pero como se mostrará en el desarrollo del post no es necesario ésto ultimo.


Ahora desde el código Java, necesitamos dos clases que representen a las tablas; éstas clases se llaman entidades y deben cumplir dos requisitos básicos: 1) llevar las anotación @Entity u @Id y 2) Implementar la Interfaz Serializable (por ser objetos que serán enviados a travez de una red).

La entidad para la tabla ANULACION se muestra a continuación:


La entidad para la tabla ERROR se muestra a continuación:

Considérese:
1) El uso de la anotacion @Table para indicar la tabla correspondiente a cada entidad.
2) La anotacion @ManyToMany  indica que hay una relacion ManyToMany entre la Entidades: Anulacion y Error1.
3) el argumento: mappedBy indica cuál es el lado dueño de la relacion, para éste caso mappedBy = "err" indica que el propietario de la relacion es Anulacion, es decir primero debo asignar el listado de errores a Anulacion y posteriormente persisto Anulación con sus errores correspondientes, en la tabla ANULACION_ERROR se reflejará los datos de Anulacion y Error.



4) No hace falta una Entidad para la tabla intermedia ANULACION_ERROR.
5) Si la tabla intermedia estuviera constuida fuera de los standares de generación automática de tablas que usa por defecto JPA, deberá usarse la anotación @JoinTable donde indicaremos el nombre de la tabla así como las columnas foráneas. Por ejemplo:

Ahora, desde la capa de vista invocamos la relación de la siguiente manera:

En donde, en un backing bean llamado "anulacionController" tendremos una referencia a: - erroresAnulacion que es un List de Error1, que mediante algun método de la lógica de negocio (en nuestro caso usamos la tecnología EJB) lo poblamos con los objetos que están guardados previamente en la base de datos :


- selectedErroresAnulacion que es un List de Errores que almacenará los Errores seleccionados por el usuario y que se persistirán en la tabla ANULACION_ERROR

Nótese también que se hace uso de un  convertidor, el cual se localiza dentro del controlador en la vista para de Error1 con el siguiente código:

Finalmente desde la vista se podrá visualizar los diversos campos de error, los cuales se seleccionarán para realizar el guardado en la base de datos:


Recomendación:  Como se vio en el código al manejar las relaciones para minimizar la complejidad y mejorar el rendimiento, se recomienda realizarlo con objetos propios de la aplicación, por ej: Anulacion, Error, etc.  en lugar de realizarlo con Objetos de tipo SelectItem o DataModel.

lunes, 30 de junio de 2014

De una lista de aplicaciones deployadas en Glassfish, cómo setear una aplicación para que aparezca como default.

Al trabajar con servidores web es común que un servidor tenga deployadas en él varias aplicaciones, y la manera de acceder a cualquiere de las aplicaciones sería usando:

localhost:8080/app1
localhost:8080/app2
localhost:8080/app3

Y así la lista podría continua hasta el infinito (/app4, /app5...). Pero, ¿qué tal si en lugar de indicar el nombre de la aplicación, simplemente colocamos en el browser localhost:8080? seremos redireccionados a la pagina index por default de glassfish, lo cual de profesional no tiene absolutamente nada. 



NOTA: se ha usado la notación común localhost:8080 por facilidad de explicación pero obviamente, localhost y el puerto variarán en cada caso y mejor todavía para el caso de producción podría mostrarse como una url limpia del estilo www.misaplicaciones.com

Entonces ¿cómo lograr que una aplicación deployada en glassfish se redireccione directamente con la dirección ligada al servidor?. Es estúpidamente fácil y tremendamente útil al momento de subir a producción nuestra aplicaciones. 

1) En la consola de administración de Glassfish, vamos a Configuración / server-config / Servidores Virtuales / server


 2) En la sección "server" en "Módulo web por Defecto" se debe elegir la aplicación que por default se cargará al acceder a la dirección del servidor.


  Y al acceder via browser la aplicación seleccionada se mostrará por defecto. Facilísimo y útil.


miércoles, 28 de agosto de 2013

¿Cómo evitar obtener una página en blanco cuando un reporte de Jasperreports está vacío?

Cuando trabajamos con Jasper Reports, en términos generales el objetivo básico es llenar un reporte con contenido coherente; pero, en la contraparte, ¿qué ocure cuando el reporte está vacío y no tiene información para mostrar?. En un ejemplo real, la siguiente imagen muestraun reporte pdf que se genería en condiciones normales, es decir, con información que mostrar:


Pero ¿qué ocurre si dicho reporte no tiene información para mostrar?. Como uede verse en la imagen, no se ha controlado el reporte vacío y cuando el ususario genere un reporte simplemente tendrá un archivo pdf (o la extensión que fue) pero vacío, lo cual no es para nada  una buena práctica.


Para solucionar éste inconveniente, desde la herramienta iReport, en las propiedades del proyecto, en la opción "When no Data" seleccionamos "All Sections, No detail" con el obejtivo de que el resporte no se muestre simplemente en blanco, sino que tenga las secciones que conforman el reporte pero sin información.

 

Entonces la salida del reporte, será mucho más coherente que una simple hoja en blanco.



miércoles, 21 de agosto de 2013

Validar un rango de fechas usando el componente Calendar de Primefaces (sin complicarnos)

Para quienes vivimos el día a día desarrollando aplicaciones con java, es normal que siempre surjan requerimentos que para su solución los desarrolladores nos rompamos la cabeza buscando alternativas, muchas veces sobredimensionando la complejidad real de la solución, complicándola mucho mas allá de lo que realmente es necesario; y claro, en muchas ocasiones al mirar ya con cabeza fría dichas soluciones, asombra la facilidad y lo obvia que resulta dicha solución. Y menciono ésto, pues puntualmente en la actualidad, al generar un reporte en donde tuve un caso de validación de dos fechas, donde una fecha final no puede ser anterior a una fecha inicial, me di demasiadas vueltas en un mismo tema, para terminar dándome cuenta que la solución fue muchísimo más facil de lo que habría pensado.

Como se ve en la imagen, el reporte está en directa dependencia de un rango de fechas, por tanto una fecha final no puede ser anterior a la inicial.

Como gran fan de la librería Primefaces, uso para éste caso el componente Calendar, el mismo que se desplegará visualmente de la siguienta manera:


NOTA: Usando javascript genero una función para limitar el ingreso por teclado con onkeypress, obligando al usuario a que necesariamente obtenga una fecha seleccionándola del componente Calendar y que así no ingrese información basura.

El Código ligado a los componentes  Calendar es el siguiente:



En donde, en el primer componente calendar mediante ajax: actualizo el segundo componente calendar, limitando el rango de selección en la fecha final mindate="#{nacidoVivoRenaviController.FInicial}" sin que pueda ser anterior a la fecha inicial previamente seleccionada, como puede verse en la imagen siguiente se desabilitan los dias que no cumplan con el criterio:


 y en el segundo componente calendar, envío la fecha inicial como atributo y la comparo con la fecha final que invoca un validador, el cual generará un error en caso de que la fecha final no cumpla con el criterio, claro, como lo dije previamente con javascript impido que el usuario ingrese informacion manualmente, pero para fines didácticos tambien he añadido el validador:


Y en caso de violarse el criterio de rango de fechas se mostraría el siguiente mensaje emergente:


NOTA: Este post se basó en un excelente artículo hallado en daily bugs

miércoles, 31 de julio de 2013

Mostrar en un Reporte hecho en Jasper Reports imagenes almacenadas en una Base de Datos

En la actualidad, por mi trabajo surgió una necesidad puntual: Guardar los datos de una persona (incluida su fotografía) en una base de datos (para éste caso Oracle) y posteriormente generar un reporte con JasperReports que muestre toda esa información. En términos generales, mostrar la información de campos estilo VARCHAR en el reporte no implica mucha dificultas, pero al hablar de la imagen (almacenada en un BLOB) las cosas se ponen un poquito más interesantes, NO complicado del todo, pero que sí requiere cierto truquito que sabiendolo manejar podría ahorrarnos tiempo. La imagen siguiente, -como ya lo mencioné- muestra la estructira de la tabla y el tipo de dato en el que estoy almacenando la imagen en la base de datos (Blob).


Para hacer el upload de la imagen desde la capa de vista hacia la base de datos, empleo el componente p:fileUplod de Primefaces. El código desde la página xhtml (JSF) es el siguiente:



El backing bean de respaldo:

En donde "current" es una entidad Persona, la cual será persistida en la base de datos, nótese que la imagen se almacena en un byte[]



Ahora, en lo que respecta al reporte, uso la herramienta iReports, y debo comentar que estoy usando un JRBeanCollectionDataSource, es decir, envío una coleccion de objetos java para "alimentar" al reporte, pero no profundizaré mucho en lo que respecta al JRBeanCollectionDataSource pues será motivo de mi próximo post. Habiendo creado el reporte con un "empty DataSource" como muesta la siguiente imagen:



Debemos crear un field equivalente al atributo destinado a la fotografía de la entidad:



Tómose en cuenta que en las propiedades de dicho field, "Field Class" se declarará como java.lang.Object.



Ahora, desde la Paleta de componentes, arrastramos el elemento "Image" hacia el reporte:



Y en las propiedades de la imagen:



En "Image Expression" colocamos el siguiente código:

net.sf.jasperreports.engine.util.JRImageLoader.loadImage ((byte []) $F{fotoPer})



Y al generar el reporte, ya podemos mostrar una imagen cagada desde una base de datos: :)

martes, 27 de noviembre de 2012

Solucionando el problema de estilos css que no se actualizan en Grails 2.1.1

Empecé a hacer un sistema con la última vesión de grails (2.1.1) y me topé con un problema referente a las hojas de estilo css: Si por algún motivo cuando se trabaja con las versiones 2.x de Grails dichos estilos no se actualizan correctamente al ejecutar la aplicación, describo tres alternativas que podrían sanear dicho problema:

1) En el archivo grails-app/conf/Config.groovy añadir las siguientes líneas de código:



2) En el archivo grails-app/views/layout/main.gsp en la etiqueta head añadir:



3)En el archivo grails-app/conf/BuildConfig.groovy comenatr la línea siguiente:



Espero haya sido de ayuda. Un fuerte abrazo a mis lectores.