Un viaje sobre lenguajes, APIs y otras cosas raras en el mundo del desarrollo de sistemas.

Control de acceso

El control de acceso debe ser homogéneo a través de todos los sistemas y debe tener coordinación entre ellos, las vigencias de las sesiones deberán permitir que el concepto de Single Sign  On deba ser implementado a lo largo de todos los programas, para eso estándares como OAuth 2.0 son benéficos y su implementación puede ser poco costosa (a nivel programático y de arquitectura).

OAuth solamente servirá como mecanismo de autenticación, una vez autenticado el usuario o la aplicación cada sistema deberá revisar los permisos de control de acceso que tiene para ella.

OAuth permite de igual manera ser un buen punto de apoyo para poder iniciar la implementación de APIs digitales que permitan ofrecer servicios específicos a sistemas internos y externos que tengan permiso para ellos.

Las sesiones y controles de acceso siempre deben ser manejadas del lado del servidor.

Todo acceso denegado siempre debe llevar a un lugar seguro, nunca a una página de error.

ControlDeAcceso

Los controles de acceso a los que se refiere este documento son a nivel aplicativo, pero de nada sirven estos si no hay una implementación de control de acceso físico a las instalaciones estratégicas del área de TI y un control específico del uso de la información, por lo cual se sugiere hacer una revisión del acceso físico a las instalaciones que incluyan:

  • Verificación de identidad del “ingresante”
  • Verificación de salida
  • Bitacorización de ambos
  • Revisión física de recursos tecnológicos de entrada y de salida
  • Conexiones limitadas a las redes de desarrollo y de equipos de producción. (Los desarrolladores no deben tener acceso a datos de producción y de ser posible deberán trabajar en una red lógica –o física- distinta).
  • Repositorios de código, llaves criptográficas y documentos de análisis deben ser resguardados de manera especial y en ningún momento residir en computadoras ajenas a cada uno de los proyectos.

ControlDeAcceso2

Prácticas criptográficas

El cifrado de datos debe llevarse siempre bajo las normas de confidencialidad, integridad y no repudiación. Estos conceptos SIEMPRE deben evaluarse en un sistema para saber el tipo de criptografía hay que aplicar en cada uno de los módulos de las aplicaciones.

De manera inicial se debe exigir que todas las comunicaciones, lleven datos confidenciales o no, sean aseguradas mediante los protocolos SSL o TLS (HTTPS), por lo que se debe implementar una generación de llaves de certificación que permitan la generación de estos protocolos y de un intercambio de información de servicios internos SOLAMENTE MEDIANTE SERVICIOS AUTENTICADOS MUTUAMENTE (Conocido comúnmente como HTTPS  de autenticación mutua) o mediante mecanismos como JWT que permiten la correcta identificación de el origen del mensaje, estos mecanismos pueden convivir perfectamente con mecanismos como OAuth.

Para efectos de no repudiación i de integridad de la información el área de TI (Seguridad) debera establecer los parámetros adecuados para realizarlo.

Todas las funciones criptográficas deben ejecutarse del lado servidor, o en un ambiente considerado seguro (el navegador no lo es).

Las excepciones generadas por los módulos criptográficos deben ser manejadas. Las fallas deben ser “seguras”

Los generadores de números aleatorios no deben ser predecibles, al igual que la generación de GUIDs, es importante verificar si el lenguaje que se maneja tiene una correcta implementación de números aleatorios seguros o hay que buscar alguna librería externa.

Criptograficas

Manejo de errores y bitácoras

Toda bitácora debe proveer datos suficientes para:

  • Análisis de errores
  • Trazabilidad de operaciones y usuarios que las realizaron
  • Generación de reversión de operaciones (rollback)
  • Seguimiento de operaciones que faciliten la no repudiación
  • Establecimiento del seguimiento de autenticación y autenticación de dos fases, cuando sea necesario.
  • Definición de ubicación lógica de los usuarios que hicieron las operaciones
  • Definición de ubicación en el tiempo de cuando se realizaron las operaciones.
  • Las bitácoras NUNCA deben estar en lugares de acceso público

Cada uno de los sistemas puede llegar a requerir todos (idealmente) o algunos de los datos antes citados, algunas áreas, instituciones o empresas pueden requerir incluso más datos ya sea por políticas internas o por legislaciones locales o federales.

Protección de Datos

La protección de datos es un tema muy amplio fuera del alcance de este documento, sin embargo es importante manejarlo en el ámbito de la programación.

  • Los datos sensibles siempre deben ser almacenados de manera cifrada
  • Los datos sensibles siempre deben comunicarse de manera cifrada
  • Los passwords NUNCA deben ser recuperables ni leidos por nadie, en caso de requerirse deben poder ser reemplazados mediante mecanismos adecuados, pero nadie debe poder tener acceso a los passwords. Para lograr esto se recomienda que sean manejados por servidores LDAP o en el peor de los casos (si son manejados directamente desde la aplicación) que estos estén bajo un mecanismo de ofuscación de “hashing” (SHA 256, por ejemplo)
  • La ubicación física de los datos sensibles debe estar protegida adecuadamente al igual que la ubicación o ubicaciones de los respaldos.
  • Una contraseña no debe ser guardada en una variable ni ser parte de una petición GET
  • Una contraseña no debe estar en una variable de sesión o de aplicación
  • Una contraseña no debe ser guardada en una variable “por algún tiempo”
  • No se deben utilizar campos de contraseña personalizados.
  • No se debe permitir el copiar y pegar de datos sensibles

ProteccionDeDatos

Seguridad en las comunicaciones

Las comunicaciones son esenciales, como ya hablamos en el punto anterior es importante mantener todas ellas de una manera segura, ya sea por protocolos SSL, TLS, SSH, SFTP o cualquier otro que permita que estas permanezcan privadas entre los servidores y el usuario. (Este ddocumento no trata de comunicaciones de audio como Voz por IP, manejo de conmutadores, líneas celulares aunque debe extenderse la misma política de cifrado hacia ellas dependiendo de la instancia correspondiente, adicional a ello se deben revisar las bitácoras de uso de dichas líneas y habilitar incluso –de ser necesario- la grabación de conversaciones bajo las condiciones requeridas por las leyes y de acuerdo a la sensibilidad de los datos de ellas).

Cada punto de comunicación es un punto posible de “hackeo” por lo que es  importante que los datos siempre estén protegidos.

comsec

El manejo de la seguridad de las comunicaciones tiene que ver con las políticas del manejo de llaves (generación, distribución y almacenamiento) que deben ser siempre vigilados y bitacorizados por el área de seguridad de TI.

De igual manera el equipo de seguridad deberá generar las políticas del desarrollo e implementación de algoritmos de cifrado, con lo cual establecerán los protocolos que se deban utilizar para cada uno de los datos que se tengan que comunicar o almacenar dentro de los sistemas y la forma en que estos se trasladarán. La comunicación de los datos va más allá del momento en que se realiza los traslados de un punto a otro mediante una red, implica la posibilidad (o imposibilidad) de almacenamiento de datos sensibles y la forma en que estos deben ser manejados en el tiempo, incluyendo los traslados de los respaldos de dichos datos.

Toda conexión debe tener bien establecido el código de página por el cual se está estableciendo.

 

Configuración en los sistemas

La configuración de los sistemas incluye varios factores:

  • Configuración de los equipos físicos
  • Configuración de los sistemas operativos
  • Configuración de las bases de datos y los servidores de aplicación
  • Configuración de las aplicaciones

Como regla general la configuración física de los equipos y de los sistemas operativos debe ser regulada y normada por parte del área de infraestructura, mientras que la última debe realizarse mediante los requerimientos de seguridad obtenidos para cada aplicación.

En cuanto a la configuración de la base de datos y de los servidores de aplicación se deben generar esquemas mediante los cuales estos puedan replicarse para su instalación, actualmente los servicios de IaaS, PaaS o SaaS proveen excelentes plataformas de generación de modelos (templates) para poder lograr este objetivo.

En cuanto a la configuración de las aplicaciones es importante que los usuarios y contraseñas de acceso a la base de datos solamente estén disponible mediante mecanismos seguros que puedan ser manipulados por el área de infraestructura para evitar su manipulación por parte de los desarrolladores o de los propios usuarios.

Remueva cualquier código de prueba en los ambientes de producción, incluyendo los “avisos de debugueo”

Verifique que los encabezados de HTTP lleven únicamente la información necesaria.

Seguridad en las bases de datos

  • Los datos sensibles siempre deben estar cifrados
  • El análisis de datos debe indicar cuales son los datos sensibles de cada aplicación (cada base de datos debe indicar esto en su diccionario de datos)
  • Todas las bases de datos deben tener un diccionario de datos
  • Se deben evitar en la medida de lo posible los Store Procedures si se busca independencia de la base de datos.
  • Siempre se debe acceder a la base de datos por queries parametrizados
  • Se deben utilizar ORMs para la programación (JPA, Hibernate, iBatis en Java, Linq en .NET)
  • Todos los datos enviados como parámetros deben estar debidamente limpios (sanitizados)
  • Ninguna conexión a la base de datos debe ser codificada en duro.
  • Evite usar funciones propias del manejador de la base de datos en vez de SQL estándar.
  • Deshabilite accesos a cuentas que no tengan una razón de acceso a la BD.
  • Los accesos deben ser siempre bajo el patrón de privilegios mínimos.

Manejo de archivos

El manejo de archivos siempre es complejo, sobre todo en lenguajes como C/C++ donde se tiene un API muy directo al usado por el Sistema Operativo, para estos casos siempre es bueno pensar en los permisos necesarios, establecer las protecciones adecuadas y evitar caer en las condiciones de carrera TOCTOU

Algunas recomendaciones genéricas son:

  • Evite el aumento de privilegios
  • Limite el número de archivos que un sistema web puede aceptar para subir.
  • En caso de sistemas operativos UNIX no deje permisos de ejecución en los directorios donde se guarden los archivos recibidos
  • Verifique las rutas y no deje que los usuarios que ejecutan servicios web tengan acceso a directorios adicionales a los que necesitan para su operación
  • Nunca envíe una ruta absoluta al cliente
  • Todos los archivos usados por la aplicación deben ser de solo lectura

Manejo de memoria

El manejo de  memoria es por lo general un grave problema, precisamente es la base de que lenguajes como Java y C# hayan aparecido en el mercado, C y los apuntadores solían generar muchos problemas en programadores que los usaban de manera descuidada provocando graves problemas de buffer overflow y de underflow.

memoria

Pero el problema va más allá, el manejo de memoria involucra el aspecto de variables de ambiente, heap, stack, tipos de datos y mucho más.

En esta sección damos una lista corta, no limitativa, de algunas acciones que hay que tomar en cuenta al manejar la memoria al construir una aplicación.

  • Revise que el buffer sea siempre mayor al dato que se va a introducir
  • Verifique que todas las cadenas son terminadas en NUL (C/C++/Objective C)
  • En C y C++ no utilice las funciones strcpy prefiera la strncpy.
  • En C y C++ no utilice las funciones strcmp prefiera strncmp
  • No confie en el recolector de basura
  • Verifique que los objetos se liberen de memoria, en Java o .NET utilice memory profilers para revisar eso
  • Siempre verifique que se inicia la memoria antes de utilizarla (malloc, new o el equivalente)
  • Deshabilite el volcado de memoria, este puede dar información innecesaria o sensible a atacantes

 

Manejo de la concurrencia

La concurrencia siempre tiene retos importantes, el no generar condiciones de carrera, deadlocks o eventos similares debe hacer que se tenga cuidado con la forma en que se programa, pero uno de los retos es la forma en que los datos deben ser compartidos.

  1. No comparta datos sensibles utilizando archivos, pipes, sockets o cualquier mecanismo que los pueda exponer a otros procesos
  2. La memoria compartida entre procesos no debe contener datos sensibles, si es necesario los contendrá el menor tiempo posible
  3. Siempre se debe fallar de manera segura
  4. Revise que la utilización de semáforos sea adecuada (al entrar a zona crítica avisar y restar el contador del semáforo al salir)
  5. Verifique no bloquear recursos a menos que sea necesario
  6. No olvide cerrar todos los archivos y sockets antes de terminar un hilo de ejecución
  7. Sea consecuente con todas las reglas y buenas prácticas de programación segura dentro de un hilo de ejecución
  8. Cuando herede o modifique una clase “thread safe” asegúrese que la nueva clase también lo sea.

Referencias

https://www.securecoding.cert.org/confluence/display/java/Java+Coding+Guidelines

https://www.securecoding.cert.org/confluence/display/seccode/Top+10+Secure+Coding+Practices

SEI CERT C++ Coding Standard, 2016 Edition. CERT SEI Carnegie Mellon University

OWASP Secure Coding Practices Quick Reference Guide, The Open Web Security Application Secutiry Project. 2010.

https://www.infosecinstitute.com/topics/secure-coding

https://security.berkeley.edu/secure-coding-practice-guidelines

Anuncios

Introducción

Esto pretende ser una guía de buenas prácticas que deben seguirse para poder tener una programación segura, entendiendo por esto una programación que evite que nuestros programas sean propensos a ataques o errores que puedan generar fuga de información o puedan convertirse en punto de partida para explotar fallas en otros programas o sistemas.

Se divide primero en las reglas generales de programación  aplicables a todos los lenguajes, próximas entradas hablaremos sobre lenguajes específicos y plataformas.

En caso de ser necesario se darán algunas muestras de código para ejemplificar.

Nos dirigido a programadores, arquitectos y líderes de proyectos interesados en realizar sistemas que puedan responder a las necesidades de seguridad actuales.

La seguridad reside en guardar los siguientes aspectos de un sistema:

  1. Confidencialidad : Se refiere a la necesidad de que los datos solamente sean accedidos por aquellos que realmente deban tener acceso a ellos
  2. Integridad: Ningún dato debe ser alterado
  3. Disponibilidad: Cuando se necesite un dato este deberá poderse obtener si es que se ha cumplido los principios anteriores
  4. Autenticación : Es el mecanismo mediante el cual nos aseguramos de la identidad de quien quiere interactuar con el sistema
  5. Autorización: Es el mecanismo por el cual se da acceso a los recursos (programas, archivos, datos, servicios, etc.) a las identidades adecuadas, por ello siempre es necesaria una autenticación correcta
  6. Auditoría (No repudiación): Es el mecanismo por el cual se debe poder rastrear los accesos, autorizaciones del sistema, un buen servicio de auditoría nos debe poder llevar a resolver las preguntas ¿Quién hizo qué? Y ¿Cómo lo hizo?

CIA

Para poder cumplir con estas metas es necesario la implementación de:

  • Políticas: Se refiere a lo que la seguridad significa para un proyecto, organización u otra entidad
  • Normas: Son aquellas observaciones técnicas que deben seguirse para poder cumplir con los requerimientos de seguridad establecidos (estándares)
  • Guías: Una guía es una serie de recomendaciones que determinan como actuar. Las guías no son obligatorias y comúnmente son definidas para apoyar las normas establecidas. Comúnmente son conocidas como recomendaciones y son una referencia cuando no existe una norma establecida.
  • Procedimientos: Un procedimiento es aquel diseño o documento que explica quien, cuando, donde y por qué sobre la implementación de una política establecida.

psgp

Dentro de este conjunto de implementaciones este documento forma parte de las guías para el establecimiento de una buena implementación de la seguridad.

La meta de la seguridad de un sistema es garantizar la confidencialidad, integridad y disponibilidad de los recursos de información para proveer el buen funcionamiento de las operaciones de negocio. Estas metas se logran gracias a la implementación de controles de seguridad. Esta guía tiene como objetivo ayudar a mitigar la ocurrencia de las vulnerabilidades de software en la medida de lo posible.

Buenas Prácticas

Validar las entradas

Algunas publicaciones conocen esta práctica como Input Validation and Data Sanitization (IDS), dejando en claro que la idea de esta práctica es ver que los datos sean válidos y que no contengan “basura” que pueda poner en riesgo los sistemas.

La idea de validar las entradas se debe dar en ambos puntos, el cliente y el servidor para evitar que se trate de brincar la validación del cliente por cualquier otro método.

La sanitación (o depuración) de los datos se da cuando se verifican los caracteres de estas entradas contra una “lista blanca” a fin de no permitir ningún carácter no válido.

inputValidation

Hacer caso de las advertencias de compilación

Las advertencias de compilación “no están de adorno”, hay que atenderlas y verificar que no existan o que las existentes sean “manejables” en el código y no posibles puntos de ruptura del mismo, por ejemplo en C o C++ es posible poner if (variable = otraVariable) sin que esto sea un error en la compilación, el compilador marcará una advertencia pero es muy probable que sea un código realmente erróneo.

fixWarnings

Otras advertencias que se deben eliminar en la medida de lo posible son aquellas que tengan que ver con conversión de tipo o de no  manejo de posibles excepciones de código, sin embargo este listado no es limitativo y un código limpio de advertencias siempre deberá ser nuestro  objetivo.

Hacer caso de los diseños de seguridad y de la arquitectura establecida

Toda corporación ha pasado años tratando de refinar sus arquitecturas de software e infraestructura a fin de garantizar el correcto uso de los componentes ya existentes y de la seguridad de los mismos. En caso de cualquier duda sobre el funcionamiento de la Arquitectura (en general o la específica ligada a seguridad) acércate con el equipo de Arquitectura Técnica.

Hacer tu código sencillo

Mientras más complejo sea el esquema del código más puntos de error existen y más probabilidades de tener vulnerabilidades en él, un buen código siempre debe de ser limpio, compacto, simple y dedicado a resolver el problema para el que es hecho. Recuerda el concepto es KISS (Keep It Simple, Stupid).

El generar menos líneas de código no es hacer un código sencillo, tampoco lo es escribir más, lo que se debe buscar es un código que sea legible y que permita un buen mantenimiento, cuya lógica sea clara y apegada a la resolución de problemas.

Ante la duda de si un código es sencillo o no las opciones son reescribir el código de una manera más clara y el apoyarse de comentarios en el código.

Por omisión: restringe.

En seguridad solo hay dos opciones: O se permite o se restringe (rechaza), si se toma la decisión de permitir sobre la de restringir siempre entonces existirá el riesgo de que alguien se aproveche de ello.

restrict

Principio del menor privilegio

Si tu programa corre en una computadora con usuario de privilegios de administrador, una base de datos con un esquema sin restricciones de espacio, sin restricciones de acceso a los sistemas de archivos o un espacio sin restricción de conexiones de puertos entonces es muy probable que no funcione correctamente en un ambiente real. El desarrollador debe  poder generar su código en las mismas condiciones de restricción en que este se ejecutará para poder llegar a validarlo.

Lo ideal es suponer que ningún privilegio (informático) será otorgado salvo aquel que se especifique  claramente en los requerimientos.

privilegeAbuse

Verifica, codifica y depura los datos que se enviarán a otros sistemas

Ya hemos hablado de la validación de datos, estos datos se validan en el punto de recolección de los mismos (p.e. navegador) y deben ser verificados en los puntos de recepción (p.e. servidor de aplicaciones), al momento de enviarse estos deben ser codificados de manera correcta para poder ser interpretados sin problema alguno (URLEncode en nuestro ejemplo) y decodificados de una manera correcta, de igual manera se debe buscar evitar todos los caracteres que puedan causar conflictos, ya sea generando caracteres de escape, aplicando una codificación o simplemente no aceptándolos (un ejemplo de depuración de caracteres puede ser el envío o recepción de campos que contengan un apóstrofe  hacia una consulta de base de datos o un signo de < o de > hacia una página HTML)

CRS

Defensa a fondo

La idea de defensa a fondo es similar a la de manejar a la defensiva cuando se conduce un automóvil: No sabemos qué es lo que van a hacer los conductores de los otros carros, por lo tanto hay que prevenir y adelantarnos a los posibles movimientos de ellos.

watchout

El tema de la programación defensiva es muy amplio y se tratará en la medida de lo posible en las especificaciones de cada lenguaje, pero la idea general de realizar una programación defensiva debe ser común y de alerta independientemente de la plataforma de programación que se use.

Utilizar técnicas de aseguramiento de calidad

QALas técnicas de calidad no empiezan con el área de QA, muy al contrario ellos son un punto de apoyo para poder asegurar que todos los controles funcionen. Todas las prácticas de QA deben de tomar en cuenta los requerimientos y buenas prácticas de seguridad a fin de poder tener un sistema lo más seguro posible, entre estas prácticas no deben faltar la integración continua, las revisiones entre pares, el manejo de requerimientos, la generación de pruebas unitarias y las discusiones en los grupos ágiles sobre la seguridad requerida en cada una de las historias de usuario.

 

Adoptar normas de codificación segura

Se debe desarrollar y/o adoptar las normas que se tengan de programación para el lenguaje usado y la plataforma en la que se desarrolla o ejecutarán los programas, cada de ellas es única y pueden variar entre cada proyecto inclusive.

Una programación basada en normas y uso de librerías (frameworks) de uso común permitirá siempre el poder hacer frente a las posibles vulnerabilidades que se puedan descubrir.

Adicional al manejo propio del código siempre existirán normas y regulaciones internacionales, corporativas o informáticas que debemos observar a fin de cumplir con los requerimientos internos, estos pueden ir desde normas documentales para soportar a las áreas de servicio técnicos, normas de manejo de bitácoras o leyes nacionales o internacionales.

normasPS

Verificar y exigir requerimientos de seguridad

Como se ha mencionado anteriormente la seguridad debe ser parte integral de los requerimientos de manera que cuando estos lleguen al programador este pueda tener claridad en aquellos puntos específicos que debe verificar.

Una planeación de requerimientos que no contempla seguridad puede convertir un proyecto en un verdadero dolor de cabeza.

Manejo de la autenticación

authenticationEl manejo de la autenticación siempre es un dolor de cabeza, sin embargo la arquitectura corporativa ofrece varias soluciones para resolverlo, es precisamente esta otra de las razones por las cuales es importante seguir las guías de arquitectura y los diseños de arquitectura técnica para cada proyecto. Hacer caso omiso de ella o tratar de deshabilitar los módulos de seguridad ya establecidos trae como consecuencia generar vulnerabilidades que ya han sido resueltas durante el tiempo que esta arquitectura y soluciones se han venido desarrollando.

En aquellas plataformas donde no existan librerías corporativas las soluciones de autenticación deben ser  validadas ante Arquitectura técnica a fin de determinar los componentes a usar.

Manejo de Sesiones

En el caso de México el manejo de sesiones es muy estricto para aquellos programas bancarios e instituciones financieras,  pero en general hay que verificar siempre el cumplimiento de normas que  permitan el uso adecuado de estas. Si estás en una institución bancaria mexicana lee la Circular Única para bancos.

Un manejo equivocado de la sesión puede generar que los esfuerzos de autenticación de un sistema sean inútiles pues puede quedar comprometida la seguridad si esta sesión es interceptada o suplantada.

  • Las sesiones nunca deben ser un parámetro GET
  • Las sesiones deben tener una vigencia (deben caducar)
  • Usuarios y contraseña no deben ser parte del identificador de sesión
  • Al utilizar tokens de sesión que contengan este tipo de datos sensibles deberán usar algún tipo de criptografía.
  • Siempre se debe utilizar un protocolo seguro (https, es decir SSL o TLS)
  • Idealmente se debería cambiar un identificador de sesión después de que el usuario se ha identificado con éxito.
  • Las cookies que se usen siempre deben ser seguras

En la siguiente entrada hablaremos de:

  • Control de acceso
  • Prácticas criptográficas
  • Manejo de errores y bitácoras
  • Protección de Datos
  • Seguridad en las comunicaciones
  • Configuración en los sistemas
  • Seguridad en las bases de datos
  • Manejo de archivos
  • Manejo de memoria
  • Manejo de la concurrencia

Gluon Rulez

After my last BLOG entry (long time ago) lot of things have happened, JavaFX performance has improved a lot and the quantity of things that it provides and you can find for this framework has grown in quantity and quality. There are more components and definitely one of the missing parts on the equation has appear and it’s called GLUON.

¿What’s GLUON?

Well… Gluon is a company that took “the responsability” to lead a copule of very important projects: Scene Builder and  JavaFXPorts, improving the wy to use both of them, that’s what we are going to talk about.

Scene Builder

Scene Builder is a  JavaFX WYSIWYG for GUIs.

Yeah, i know that “we” prefer to use our old Eclipse or Netbeans and edit our FXML files handly, but it is always a good idea to have an auxiliar tool to help us to create the first prototype and let us make an approach on what we need in order to polish things after (using this tool or aour beloved notepad editor).

The tool is a good one and we are going to put a couple of screenshots about examples that we alrady talked before in this blog.

This way we can move some properties on our GUI quickly.

Improvements we have seen: a better way to manage image resources and CSS files (it does not have a CSS editor and it could be a valuable improvement on the future).

JavaFX Ports

This is what we wait for long long  time, a tool to let us use all the JavaX beauty to develop mobile devices applications.

Once again our life has been made easier. Gluon has generated some plugins that let us focus on coding and forget on the instalations needed, so to make a mobile development we only need to install the required SDKs (Android, iOS -XCode- and Gluon). To have the complete set of instructions on how to do it i will drop the link to see it:

http://docs.gluonhq.com/charm/1.0.0/#_ide_plugins

I have to point out that once you have your gluon project and the gradle files generated by the tool you must update the build.gradle file to point to the last javafx ports version as dependency:

dependencies {
classpath ‘org.javafxports:jfxmobile-plugin:1.0.6’
classpath ‘com.android.tools.build:gradle:0.5.+’
classpath ‘com.google.code.ksoap2-android:ksoap2-android:3.4.0’
}

 

If you left the default version (the one that the plugin generates the day of this post) you may have some trouble with the displaying position for the item list box for ChoiceBox and DatePicker … and you are not going to like it.

I must recomend an aditional reading of the documentation provided on the site in order to generate notification or some mobiles platform specific features for your programs.

So the good news are on, cause beside these and the modularization that will be in java 9 (jigsaw) we can be sure that the WORE concept is not just back but in the best position ever. Hopefully and Gluon can contribute to create a PPAPI plugin for browsers in order  to run again our applets, that could be “the icing on the cake”.

Greetings and i promise that my blog is back for good.

Después de la última entrada en este BLOG (ya hace bastante) muchas cosas han pasado, JavaFX mejoró bastante en su desempeño y en la cantidad de cosas que provee y poco a poco cada vez hay más soporte para los componentes necesarios para este lenguaje, definitivamente uno de los componentes que estaba perdido era GLUON.

¿Que es GLUON?

Bueno… gluon es una empresa que se ha dado a la labor de “hacerse responsable” de un par de proyectos muy específicos:  Scene Builder y JavaFXPorts, mejorando la forma de utilizar ambos, que es de lo que hablaremos a continuación.

Scene Builder

Scene Builder es un constructor de interfaces JavaFX WYSIWYG.

Si, ya se que preferimos (muchos) manejar nuestro viejo Eclipse o NetBeans y estar editando los XML (FXML) a mano, pero siempre es bueno una herramienta auxiliar que nos permita hacer la primera aproximación de una manera rápida y segura para que nosotros podamos refinarla posteriormente (ya sea con ayuda de esta herramienta o “a patín del diablo” -a mano- )

La herramienta es buena y les dejamos aqui algunos ejemplos con lo que ya alguna vez escribimos dentro de este blog.

Así pues podemos mover las características de nuestra aplicación de una forma más rápida.

Una de las mejoras que hemos observado es un mejor manejo de las iágenes y recursos CSS dentro del editor. (No tiene editor de CSS y probablemente eso pudiese ser un extra muy valioso a futuro).

JavaFX Ports

Esto es lo que durante muchos e interminables meses estuvimos buscando, una herramienta (justo de la que hablé en mi último post) que nos permitiera llevar toda la belleza de JavaFX hacia los dispositivos móviles.

Una vez más nos han facilitado la vida. Han generado plugins que nos permiten olvidarnos un podo sobre las instalaciones necesarias y nos ayudan a enfocarnos en la codificación, así que ahora para hacer un desarrollo en móviles sólo hay que instalar los SDK adecuados (Android, iOS -Xccode- y Gluon). Para las instrucciones de como instalar los plugins les dejo la liga correspondiente:

http://docs.gluonhq.com/charm/1.0.0/#_ide_plugins

Es bueno hacer notar que una vez que el proyecto e gradle se encuentre generado para nuestra aplicación es recomendable actualizar el archivo build.gradle para que las dependencias vayan a la última versión de javafx ports:

dependencies {
classpath ‘org.javafxports:jfxmobile-plugin:1.0.6’
classpath ‘com.android.tools.build:gradle:0.5.+’
classpath ‘com.google.code.ksoap2-android:ksoap2-android:3.4.0’
}

 

Por ejemplo, si usted deja la versión (que hasta hoy viene en el plugin por omisión) es probable que haya problemas con la posición en que se desplieguen las listas del Datepickeer o del ChoiceBox… lo cual no nos gustará.

Yo recomendaría, adicionalmente darle una buena leida al sitio por si creen que generar notificaciones o hacer algo específico de alguna plataforma movil debe ser parte de su aplicación.

Así pues siguen las buenas noticias, pues entre esto y la modularización que tendremos en Java 9 podemos estar seguros de que el concepto WORE está no sólo de vuelta si no en un mejor posicionamiento que muchas otras herramientas, ojalá y Gluon decidiera contribuir para que se genere un plugin PPAPI para JavaFX, sería “la cereza en el pastel”.

Saludos y les aseguro que volveré pronto con más posts.

JavaFX en mi android

El día de hoy vamos a hacer que una aplicación ya hecha en Java FX la podamos pasar a nuestro dispositivo Android.

Los pasos son a grandes rasgos:

Bajar el sdk de android y el adt para tener emuladores. http://developer.android.com/sdk/installing/index.html?pkg=tools

Bajar el runtime de JFX https://bitbucket.org/javafxports/android/downloads

Gradle viene con el dalvik sdk

Generar para gradle las siguientes variables:

NAME El nombre escogido para el proyecto.

ANDROID_SDK el path donde se ha bajado el SDK Android, Si se ha bajado todo el ADT hay que apuntar al directorio interno del adt.

DIR el directorio donde el apk será guardado. Un directorio llamado NAME será generado en este directorio de salida

PACKAGE El nombre del paquete requerido por Android. No tiene relación con el de la aplicación JavaFX pero se puede usar el mismo.

JFX_SDK Donde el JavaFX-Android Runtime ha sido compilado o descargado

JFX_APP Lugar donde está el .jar de la aplicación JavaFX

debe utilizar el API de Android al nivel 19 o posterior, si alguno de los archivos han sido compilados con Java 7 o mayor. De otra forma los archivos deben ser compilados para Java 6.

JFX_MAIN el nombre de la clase que inicia la aplicación Java (completa con el nombre de los paquetes)

DEBUG Si se quiere hacer l depuración del producto portado.

Crear el proyecto de Gradle:

gradle -PDEBUG -PDIR=/home/user/work -PNAME=HelloAndroidWorld -PPACKAGE=com.helloworld \

-PJFX_SDK=/home/user/android/android-sdk -PJFX_APP=/home/user/NetBeansProjects/HelloAndroidWorld/dist \

-PJFX_MAIN=com.helloworld.HelloAndroidWorld createProject

correr en el directorio de la aplicación: ant debug

Instale la aplicación en su dispositivo

La aplicación no correrá en dispositivos virtuales debido a que estos no tienen las extensiones de opengl requeridas por JFX. Se debe utilizar un dispositivo real.

El bundle Android ADT tiene una herramienta llamada adb que le permitirá comunicarse con el dispositivo real (o incluso con los emuladores). Instale el paquete via:

adb install -r path/to/package-debug.apk

Si quiere debugearlo hágalo usando:

adb logcat

En las entradas posteriores les iremos diciendo que es lo que hemos encontrado sobre este procedimiento, por lo pronto queda saber que el runtime que manejamos aqui es referente a JavaFX2 (Java 7), sin embargo en el mismo repositorio de bitbucket podemos encontrar el JFX rt para JFX 8… seguiremos informando

After a very heavy workload here we are to finish (or start) what we begun.

If you remember we made a user interface that had a VBox named as  “vbScores” in that VBox  we’ll put our baseball results. but what we will show?

well let’s make our FXML first:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<AnchorPane id="AnchorPane" prefHeight="45.0" prefWidth="169.0" styleClass="mainFxmlClass, rootPane" xmlns:fx="http://javafx.com/fxml" fx:controller="com.beisbolicos.scoreboard.GameResultController">
  <children>
    <GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
      <children>
        <Label fx:id="eVisitante" text="Label" textFill="#e0ff66" GridPane.columnIndex="0" GridPane.rowIndex="0">
          <font>
            <Font name="Verdana Bold" size="12.0" fx:id="x1" />
          </font>
        </Label>
        <Label fx:id="eLocal" font="$x1" text="Label" textFill="#52ff00" GridPane.columnIndex="0" GridPane.rowIndex="2" />
        <Label fx:id="cVisitante" text="Label" textFill="WHITE" GridPane.columnIndex="1" GridPane.rowIndex="0" />
        <Label fx:id="cLocal" text="Label" textFill="WHITE" GridPane.columnIndex="1" GridPane.rowIndex="2" />
        <Label id="lInning" fx:id="lInning" text="Label" textFill="#ff3d00" GridPane.columnIndex="2" GridPane.rowIndex="0">
          <font>
            <Font name="System Bold" size="12.0" fx:id="x2" />
          </font>
        </Label>
        <Label fx:id="lStatus" font="$x2" graphicTextGap="0.0" text="Label" textFill="#33ffe7" GridPane.columnIndex="0" GridPane.rowIndex="3">
          <GridPane.margin>
            <Insets fx:id="x3" />
          </GridPane.margin>
        </Label>
        <ImageView fitHeight="30.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="2" GridPane.halignment="LEFT" GridPane.hgrow="NEVER" GridPane.margin="$x3" GridPane.rowIndex="1" GridPane.rowSpan="2" GridPane.valignment="TOP" GridPane.vgrow="NEVER" />
      </children>
      <columnConstraints>
        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
      </columnConstraints>
      <rowConstraints>
        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
      </rowConstraints>
    </GridPane>
  </children>
  <stylesheets>
    <URL value="@scoreboard.css" />
  </stylesheets>
</AnchorPane>


As you can see we will put the game’s local team name and runs, visitor’s name and run and one state and one graphic for the on bases runners.

Now it’s time to connect to the WebService that will provide the data, we will make this from out initial FXML controller, that is the ScoreboardController class and we will read something like:

package com.beisbolicos.scoreboard;
import com.delunasaenz.scoreboardWS.Game;
import com.delunasaenz.scoreboardWS.ScoreboardWS;
import com.delunasaenz.scoreboardWS.ScoreboardWSService;
import java.io.IOException;import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javax.annotation.Resource;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class ScoreBoardController implements Initializable {
    public ScoreboardWSService service;
    @FXML
    private ChoiceBox leagueSelection;
    @FXML
    private VBox vbScores;
    @FXML
    private void handleButtonAction(ActionEvent event) {
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        URL wsdlLocation = null;
        try {
            wsdlLocation = new URL("http://localhost:8080/"
                    + "ScoreboardApp/ScoreboardWSService?wsdl");
        } catch (MalformedURLException ex) {
            Logger.getLogger(ScoreBoardController.class.getName()).log(Level.SEVERE, null, ex);
        }
        service = new ScoreboardWSService(wsdlLocation,
                new QName("http://scoreboard.delunasaenz.com/", "ScoreboardWSService"));
        leagueSelection.getSelectionModel().select(0);
        leagueSelection.getSelectionModel().selectedIndexProperty()
                .addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> ov,
                    Number t, Number t1) {
                actualizaLista(t1);
            }
        });
        actualizaLista(new Integer(0));
    }
    private void actualizaLista(Number t1) {
        ScoreboardWS port = service.getScoreboardWSPort();
        String liga;
        switch (t1.intValue()) { 
           case 0:
                liga = "MEX";
                break;
            case 1:
                liga = "LMP";
                break;
            case 2:
                liga = "MLB";
                break;
            case 3:
                liga = "SC";
                break;
            default:
                liga = "MEX";
                break;
        }
        List<Game> result = port.league(liga);
        vbScores.getChildren().clear();
        for (Game item : result) {
            FXMLLoader fxml = new FXMLLoader(getClass()
                        .getResource("/com/beisbolicos/scoreboard/GameResult.fxml"));
            try {
                fxml.load();
                GameResultController grc = fxml.getController();
                vbScores.getChildren().add((Node) fxml.getRoot());
                grc.setGame(item);
            } catch (IOException ex) {
                Logger.getLogger(ScoreBoardController.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
        }
    }
}

And now the explanation.

if you have used Web Services from servlets or JSP you will find that  @WebServiceRef(wsdlLocation = “http://localhost:8080/ScoreboardApp/ScoreboardWSService?wsdl&#8221;) is missing, that is because the Service reference for our webservice client (service variable), that is because that annotation only works inside a Webserver container and a JavaFX is not running on the server side, but the client side, then we need to start our WS client using the constructor of the client using the wsdlLocation, new QName(“http://scoreboard.delunasaenz.com/&#8221;, “ScoreboardWSService”) as the parameters to start it.

On the initialize method we add a listener to the leagueSelection ChoiceBox making the VBox to be filled with the current games on the league selected, the leagues are obtained thanks to web service we defined.

I hope this can get you a good brief explanation on how to start and use a WebService from a FXML/JavaFX application.

Stop the press… xD

I’ve been working hard with a project that uses a lot of text data in a TableView, usually the tableviews uses about 8 columns for each row and can be more than 100000 rows on a “bad user search”…

the problem with this is that TableView use to “paint” (outside the screen) all the cells involved (above) the line that has to be presented when you use the scroolTo(int) function, so with tables like the one i described the response can became veeeery slooow…

after making a research i wrote a “work around” for those tables with the same height on all the rows:

package my.good.stuff.package.utils;

import com.sun.javafx.scene.control.skin.TableViewSkin;
import com.sun.javafx.scene.control.skin.VirtualContainerBase;
import com.sun.javafx.scene.control.skin.VirtualFlow;
import javafx.scene.Node;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.TableView;

/**
* @author charly
*/
public class MyVeryGoodTableView extends TableView
{
protected double rowHeight;
@Override
public void scrollTo(int registro){
TableViewSkin skin = (TableViewSkin)getSkin();
VirtualFlow vf = null;
for(Node node : skin.getChildren()){
if(node instanceof VirtualFlow){
vf = (VirtualFlow)node;
}
}
ScrollBar bar=null;
for(Node node : vf.getChildrenUnmodifiable()){
if(node instanceof ScrollBar){
bar=(ScrollBar)node;
if(Orientation.VERTICAL== bar.getOrientation()){
bar.valueProperty().set((double)(
((double)registro/(double)(getItems().size()-1))
*bar.getMax()));
}
}
}
}

public double getRowHeight() {
return rowHeight;
}

public void setRowHeight(double rowHeight) {
this.rowHeight = rowHeight;
}

}

Hope this works for you… after this we will continue with the JavaFX tutorial…  xD