Etiqueta

28 diciembre 2018

Nueva herramienta de migración de Omnis DF1 a SQLite o PostgreSQL

Otra de las novedades que incluye Omnis Studio 10, supone una garantía de estabilidad y longevidad para nuestras aplicaciones, especialmente en lo que al uso de la base de datos nativa (los llamados df1) se refiere. La gran ventaja que supondrá el uso de ésta herramienta es, que tras su conversión a una base de datos SQLite o PostgreSQL, los antiguos comandos denominados "Omnis DML" permanecerán en la biblioteca convertida, pero, (y este es el importante detalle) se ejecutarán contra la base de datos seleccionada (SQLite o PostgreSQL), sin problemas y automáticamente, en lugar del antiguo fichero de datos Omnis. Por ejemplo, comandos como "Prepare for edit" o "Update files" se ejecutaran contra la nueva base de datos (SQLite o PostgreSQL). 



Sin duda ésta opción, es muy bien recibida por todos aquellos que hemos deseado por mucho tiempo, disponer de un almacenamiento de datos más robusto, proporcionándonos a la vez, una cómoda puerta de salida, en la migración de nuestras antiguas aplicaciones hacia el soporte de código SQL. Un mejorado "OmnisSQL DAM" será el encargado de producir el "milagro" de acceder a un fichero SQLite como si se tratase de un antiguo fichero .df1

Se han realizado pruebas con el nuevo "OmnisSQL DAM" contra archivos de datos SQLite y Omnis, tanto directamente como utilizando "Data Bridge". Las pruebas se han realizado insertando ~ 2.5MB y leyendo ~ 20MB de un archivo de datos. Los tiempos de finalización de la prueba se muestran en segundos.


27 diciembre 2018

Objetos "JavaScript Worker"

Omnis Studio 10, ahora tiene embebido (integrado) el "framework" "node.js", el cual incluye gran cantidad de módulos de código abierto desarrollados por terceros y que (por tanto) podremos usar libremente desde nuestro código Omnis. Un nuevo "Worker Object" denominado "JavaScript Worker Object" nos permitirá ejecutar métodos de "node.js", mediante simplemente invocarlo desde nuestro código Omnis, para posteriormente recibir los resultados en el método indicado como retorno del mismo. A modo de ejemplo, Omnis incluye la librería "xml2js" la cual permite convertir un XML a JSON.

Construcción de métodos JavaScript


Con éste fin Omnis dispone de un nuevo archivo JS, denominado "ow3javascript.js", el cual podremos localizar bajo el directorio "clientserver/server/remotedebug" y que es el punto de partida para todas las llamadas a los métodos de "node.js". Éstas llegaran desde Omnis como solicitudes HTTP y retornaran sus resultados también como contenido HTTP. Cada "Worker" ejecutará sus métodos secuencialmente.

Un nuevo directorio o carpeta denominada "node_modules", contendrá los módulos que serán requeridos desde el "ow3javascript.js". Es aquí, donde deberemos ubicar lo módulos "node.js" que deseemos utilizar, mediante el comando "npm -i" ejecutado desde ésta misma carpeta; éstos serán los módulos que ineraccionaran con nuestras aplicaciones Omnis.

Existen al menos dos archivos clave que siempre deberán estar ubicados y presentes en ésta carpeta:

  • omnis_calls.js - Módulo que encargado de devolver los resultados a Omnis.
  • omnis_modules.js - Módulo encargado de suministrar la lista de los que podrán ser invocados desde Omnis.

En ésta misma carpeta, podremos localizar dos módulos suministrados a modo de ejemplo denominados: "omnis_test.js" y "omnis_xml2js.js". Vistos desde Omnis sus nombres son "test" y "xml2js", a cada uno de ellos le corresponderá una entrada en el "omnis_modules.js" proporcionándose así la lista de métodos que podrán ser invocados desde Omnis.

Creación de un "Worker"


Asigne el subtipo del objeto externo "OW3 Worker Objects\JAVASCRIPTWorker", a una variable de tipo "Object" u "Object Reference", , también puede hacerse mediante crear una clase objeto a la que asignar el "subtipo" ya indicado, para luego asignarlo a una variable Omnis.

¡¡Importante!! Antes de invocar su método "$init", será necesario configurar su propiedad "$callbackinst", para indicar dónde recibir los resultados. Por ejemplo: "Calculate Object.$callbackinst as $cinst"

Propiedades


El "Worker JavaScript" soporta las propiedades "Worker" estándar: $state, $threadcount, $errorcode y $errortext.

Métodos de invocación


$init([cPath, bDebugNodeJs=kFalse])


Permite preparar el objeto, de forma que esté listo para ejecutar llamadas a métodos JavaScript. Devuelve "true" si tiene éxito. Debe ejecutarse antes que cualquier otro método.

  • cPath
    Permite cambiar la ruta de búsqueda de módulos predeterminada "NODE_PATH". La ruta predeterminada es "≤Carpeta de datos Omnis≥/node_modules". Tenga en cuenta, que sí cambia esta ruta, el resto de módulos que son obligatorios también deberán ser alojados en la nueva ruta.

  • bDebugNodeJs
    Booleano que indica si se desea poder depurar "node.js", por ejemplo, mediante Chrome. Es posible que no pueda iniciarse el "Worker" si se configura para más de un "Worker JavaScript" en activo, ya que "node.js" requiere de un puerto para depuración disponible. Para su depuración en Chrome, introduzca "chrome://inspect", y luego abra las herramientas de depuración dedicadas para "node.js". 

$start()


Ejecuta el "Worker JavaScript" en segundo plano. Devuelve "true" sí ha sido iniciado correctamente. El método $start(), se encargará de iniciar "node.js" he invocar los métodos JavaScript. Seguramente realizaremos llamadas a diferentes métodos del mismo proceso, por lo que no será necesario ejecutar $start() con frecuencia, lo que significa que la sobrecarga debida a la ejecución de procesos "node.js" es mínima.

$cancel


Cancela la ejecución del proceso "node.js". Cualquier método ya en progreso no será completado.


$callmethod(cModule, cMethod, vListOrRow [,bWait=kFalse, &cErrorText])



Permite la invocación de un método, al cual se pasa un solo parámetro desde el objeto JavaScript ("vListOrRow"). Opcionalmente se esperará a que el método complete su ejecución ("bWait"). El método devolverá "true" si la invocación es exitosa. "cModule" y "cMethod" identifican al módulo y al método dentro del módulo, que será invocado. "vListOrRow" será convertido a formato JSON antes de su paso al método como parámetro. El uso de "bWait" indicará que deseamos suspender la ejecución, hasta que el método haya terminado. "cErrorText" recibirá un texto descriptivo del error, en caso de fallo de "$callmethod".



Métodos de retorno




$cancelled


Se puede reescribir este método (Override) si se desea controlar la notificación correspondiente a una cancelación del "Worker" realizada correctamente.

$workererror(wError)


La reescritura de éste método (Override), permite recibir notificaciones de error del "Worker" no relacionados con la invocación a alguno de sus métodos, como, por ejemplo, un error producido al iniciarse "node.js". El sub-proceso del "Worker" se cerrará tras la generación de dicha notificación. "wError" contiene dos columnas, un entero llamado "errorCode" y un texto llamado "errorInfo".

$methoderror(wError)


La re-escritura de éste método (Override), permite recibir notificaciones de error tras el intento de invocar un método mediante "$callmethod". "wError" tiene dos columnas, un entero llamado "errorCode" y un texto llamada "errorInfo".

$methodreturn(wReturn)


Éste es el método al cual llegarán los resultados tras la ejecución de un "$callmethod". "wReturn" es una variable de tipo "row". Si el método de JavaScript devuelve un objeto, será el equivalente Omnis creado al convertir el JSON en una "row". Si el método de JavaScript devuelve otros datos, como por ejemplo. una imagen, esta consistirá en una "row" con una sola columna denominada "content", con los datos devueltos por el método.

26 diciembre 2018

El nuevo Depurador Remoto

La depuración remota permite depurar el código Omnis de una librería compartida en la red. Omnis usa para ello una versión “developer” independiente, el llamado “remote debug client”, el cual se conectará a través de la red a otro Omnis Studio, denominado “remote debug server”.


Algunos aspectos a tener en cuenta:

  • El “remote debug server” es quien ejecuta el código a depurar, y puede residir en cualquier tipo de instalación: “development”, “runtime”, “server” o “headless server”.
  • El código Omnis es ejecutado en modo “multi-threaded server”, creándose para ello pilas de procesos independientes de la principal.
  • El “remote debug server” y el “client” no precisan estar ejecutándose en el mismo sistema operativo.
  • La versión “client” debe ser la misma o posterior a la versión “server”.
  • Las clases protegidas y las bibliotecas bloqueadas también pueden ser depuradas.

Aunque hablamos de “depurador remoto”, en realidad, tanto el cliente como el servidor podrían residir en la misma máquina, de hecho cliente y servidor podrían contener los mismos procesos Omnis. En este último caso, el “remote debug client” es ejecutado con algunas restricciones, indicadas mas adelante en este artículo.

Conectividad


El “client” y el “server” se conectan entre sí a través de un WebSocket. Una conexión WebSocket es una conexión directa entre cliente y servidor, por lo que puede requerir de la apertura del puerto correspondiente en el “firewall”. Puesto que las conexiones WebSocket se inician como conexiones HTTP, un WebSocket puede soportar una conexión TLS segura, así como el requerimiento de un certificado de autenticación para el cliente. El “remote debug”, usa siempre una conexión TLS, por lo que el WebSocket es iniciado como HTTPS.

La conexión entre un cliente y un servidor es denominada “remote debug session” o simplemente “session”. Omnis podrá ejecutar una sola “session” a la vez.

El "Remote Debug Server"


Desde la versión “developer”, podremos configurar el “remote debug server” tras hacer clic sobre su nodo en el “Browser”, y seleccionar la opción “Remote Debug Server”.

Para una versión “runtime” de Omnis (no “headless”), y si la librería “remotedebug.lbs” está en la carpeta “startup”, se dispondrá de un menú denominado “Remote Debug”. El cual contiene una sola opción, que permite abrir la ventana de configuración. Si se trata de un servidor “headless” podremos llevar a cabo la configuración desde la ventana de administració (osadmin).

La ventana de configuración muestra dos pestañas, una para controlar el servidor y otra para configurarlo.

La pestaña “Control Server” tiene un solo botón, utilizado para arrancar o detener el servidor. De no encontrarse arrancado, no aceptará conexiones desde un cliente.

La pestaña “Configure Server” permite llevar a cabo su configuración, muestra los campos que corresponden a las entradas en el archivo de configuración y que describiremos a continuación.

El fichero de configuración


La configuración se guarda en el fichero denominado  “remote_debug_server_config.json”, ubicado en “clientserver/server/remotedebug” de la carpeta de instalación Omnis. Podemos optar por editar este archivo JSON directamente con cualquier editor o usar la opción descrita anteriormente.

Debemos tener en cuenta que Omnis hace uso de un servidor “node.js” ejecutado junto con Omnis, desde el se construye el servidor WebSocket. Como consecuencia, parte de la información de configuración es compartida también con “node.js”.

Configuración ejemplo:

{
   "debugPort": 8080, 
  "serverPfx": "server.pfx", 
  "pfxPassPhrase": "xxxxxx", 
   "ca": [ "server_cert.pem" ], 
  "requestCert": false, 
  "rejectUnauthorized":  false, 
  "userName": "myUser",
 "hashedPassword":   
 "AAGGoAAAABBSEkknQUIeHQHu1sIyWxlSAAAAIHw9kvCVF4tE//S   MpbSGVD/RKJLekoR7TlTvZVy3MbkJ", 
   "startRemoteDebugServerAtStartup": true,
   "pauseAtStartupUntilDebuggerClientStartsExecution": false,
   "logConnectionSetup": false
}

debugPort

El puerto TCP/IP en el que el servidor WebSocket escucha las conexiones entrantes desde el cliente.

serverPfx

Este es un archivo que contiene el certificado del servidor y la clave privada. Debe estar en el mismo directorio que el “remote_debug_server_config.json”. La instalación por defecto consta de un certificado auto-firmado y una clave generada mediante el comando openssl (disponible en cualquier sistema con openssl instalado). Tendrá que proporcionar su propia clave privada y su certificado. Puede generar una nueva clave privada y un certificado auto-firmado utilizando los siguientes comandos:

openssl req -x509 -newkey rsa:4096 -keyout server_key.pem -out server_cert.pem -nodes -days 1024 -subj "/CN=localhost/O=Demo" -passin pass:xxxxxx
openssl pkcs12 -export -out server.pfx -inkey server_key.pem -in server_cert.pem

Este archivo deberá ser indicado bajo la opción “PFX” y es invocado por el método https.createServer() de “node.js”. Podrá encontrar más información sobre esto, en la documentación de “node.js”:

https://nodejs.org/docs/latest-v8.x/api/https.html#https_class_https_serve 
https://nodejs.org/docs/latest-v8.x/api/tls.html#tls_tls_createsecurecontext_options

pfxPassPhrase

Esta es la frase-contraseña utilizada para proteger el archivo PFX en el servidor. En nuestro ejemplo es "xxxxxx".

ca

Ver https://nodejs.org/docs/latest-v8.x/api/tls.html#tls_tls_createsecurecontext_options para más detalles. Normalmente, usted sólo tendrá un CA, puesto que tiene un sólo certificado auto-firmado, en cuyo caso tendremos una sola entrada. En nuestro ejemplo el certificado fue firmado usando “server_cert.pem”. Generalmente su valor es una lista separada por comas de certificados de confianza, nombres de archivos los cuales deben residir en el mismo directorio que el “remote_debug_server_config.json”.

requestCert

Valor booleano. Si es verdadero, el servidor “node.js” solicitará un certificado para autenticar al cliente. Los certificados de cliente se explican más adelante, en la entrada conectividad del cliente.

rejectUnauthorized

Valor booleano. Si es verdadero, el servidor rechazará cualquier conexión no incluida en la lista de CA’s suministrada. Esta opción solo tiene efecto si “requestCert” es cierto.

userName

Si no está vacío, la conexión WebSocket también usará autenticación básica HTTP con el usuario, en cuyo caso este campo deberá contener el nombre del usuario utilizado para la autenticación básica HTTP.

hashedPassword

Si “userName” no está vacío, será el "hash" PBKDF2 de la contraseña requerida para la autenticación básica HTTP.

startRemoteDebugServerAtStartup

Esta opción booleana indica si el “remote debug server” debe iniciarse  automáticamente al iniciarse Omnis.

pauseAtStartupUntilDebuggerClientStartsExecution

Si el “remote debug server” está configurado para iniciarse automáticamente cuando se inicia Omnis, podremos configurar esta opción booleana a “true” para causar que Omnis pause su ejecución durante el momento de ejecutar la “startup_task” y otras "tasa" iniciales de nuestra librería Omnis.

Cuando se utiliza esta opción, Omnis muestra un mensaje de trabajo (Waiting for remote debug client to start execution…), entrando en un bucle de espera, hasta que se reciba un comando desde el cliente para ejecución. Durante este bucle, el cliente podrá ver y depurar el código remotamente, mediante (por ejemplo) establecer puntos de interrupción.

El bucle termina cuando el cliente envía un comando de inicio de ejecución, cuando la sesión con el “remote debug server” es cerrada o cuando un usuario hace clic sobre el botón “cancel” situado junto al mensaje de trabajo mostrado en el servidor. Cuando el bucle termina, Omnis ejecutará la “startup_task” de la librería.

El “Remote Debug Client”


El “remote debug client” es accesible a través de un nuevo nodo situado sobre el árbol del navegador de Studio denominado, "Remote Debug Client". Utiliza un modelo de sesión similar al de VCS. Tras hacer clic sobre el nodo, se mostrarán los enlaces “Session Manager”, y “Open Session”.

El “Session Manager” permite configurar las sesiones de depuración remotas. Cada sesión contendrá los parámetros que permitirá al cliente iniciar un WebSocket de conexión con un “remote debug server”. A continuación describimos cada uno de sus parámetros:

Name

Nombre que identifica el sesión.

Server

Dirección IP o nombre DNS del “remote debug server”.

Debug Port

Puerto configurado en el “remote debug server”. En su conexión al servidor, el cliente construirá la URL siguiente:
wss://Server:DebugPort

Client Certificate

Si el servidor requiere un certificado de cliente, deberá especificarse aquí. Podrá generar un certificado de cliente usando los siguientes comandos openssl:
openssl req -newkey rsa:4096 -keyout client_key.pem -out client_csr.pem -nodes -days 1024 -subj "/CN=192.168.1.11" -passin pass:xxxxxx
openssl x509 -req -in client_csr.pem -CA server_cert.pem -CAkey server_key.pem -out client_cert.pem -set_serial 01 -days 1024
Tenga en cuenta que en este ejemplo usamos la clave y el certificado de servidor utilizados con el ejemplo para el “PFX”. Paro, el certificado del cliente necesitará ser instalado en la máquina del cliente.

Para Windows, genere un archivo “client.pfx”:
openssl pkcs12 -export -out client.pfx -inkey client_key.pem -in client_cert.pem
Añada el “client.pfx” al almacén de certificados de Windows, mediante hacer doble clic  en el archivo, agregándolo a “Personal certificates” del usuario en curso.

Para macOS, genere un archivo “pkcs12”:
openssl pkcs12 -export -out client.p12 -inkey client_key.pem -in client_cert.pem
Haga doble clic sobre el archivo para agregarlo al llavero.
Puede encontrar más detalles sobre esto en la documentación sobre CURL en:
https://curl.haxx.se/libcurl/c/CURLOPT_SSLCERT.html
Tenga en cuenta que el parámetro “Client Certificate” pasa su valor al comando CURL bajo la opción CURLOPT_SSLCERT.

En caso de Windows, el parámetro es la ruta hacia el lugar donde está almacenado…
CurrentUser\MY\afe2179599460d20da08c12e8c328d84bd300735
…donde afe2179599460d20da08c12e8c328d84bd300735 es la huella digital, visible mediante hacer doble clic en “certificate” del MMC (MMC certificate snap-in view, pestaña “details”, campo “thumbprint”).

En caso de macOS, se puede especificar la ruta del archivo “p12” o el nombre que tiene en el llavero del cliente.

User Name

Si el servidor utiliza autenticación básica HTTP, es el nombre de usuario requerido.

Password

Si el servidor usa autenticación básica HTTP, será la contraseña requerida.  Alternativamente, podrá dejarse vacía, causando que se le solicite al cliente la cuando sea necesaria.

Server Connection Logging

Mediante ésta opción podremos monitorizar la conexión con el “remote debug server”, para poder observar cualquier problema de conexión. También deberemos habilitar ésta opción en el archivo de configuración, bajo la entrada “logConnectionSetup”.

Si está habilitado, se creará un archivo de registro  denominado: “.htm” en el directorio “logs/remotedebug , con el registro de lo que ha ocurrido al conectarse al “remote debug server”. Tenga en cuenta que el registro no se escribe hasta que la conexión es cerrada.

Preparación del código para su depuración remota


Deberemos habilitar en nuestras librerías e instancias de tipo tarea “task” la capacidad “remote debugging” mediante configurar su propiedad $remotedebug.

Library


Por defecto, una librería no puede ser depurada remotamente, lo que significa que cuando el cliente intente conectarse para depuración, normalmente no aparecerá en el interfaz de cliente. Si queremos que aparezca necesitaremos establecer su propiedad “$clib.$remotedebug”, como “True”, lo cual no podrá realizarse sobre librerías ya marcadas como privadas, lo que significa que deberemos fijar esta propiedad como “true” antes de hacerla privada.

Task


La configuración de “$clib.$remotedebug” permite que la librería y sus clases aparezcan sobre la ventana cliente de depuración remota. Permitiéndonos manipular su código y establecer “break points”.

Sin embargo, sólo las clases “task” y “remote task” marcadas para depuración remota, reaccionarán ante los “breack points” que fijemos. Esto permitirá un mayor control sobre lo que podrá o no podrá ser depurado remotamente y del lado del servidor, permitirá evitar que un “breack point” detenga la ejecución para otros posibles clientes en uso.

Para marcar una “task” o “remote task” para depuración remota, configure su propiedad
“$remotedebug” a kTrue.

Tabién podremos activar ésta propiedad, cómo un parámetro en el URL de conexión, hacia un “remote form” (omnisRemoteDebug = 1), por ejemplo:
http://127.0.0.1:5981/jschtml/jsDragDrop.htm?omnisRemoteDebug=1

Interfaz del depurador remoto 

Abriendo un sesión

Para usar el “remote debugger client” tras configurar una sesión, haga clic sobre el nodo “Remote Debug Client” y después sobre el enlace “Open Session”, luego haga clic sobre el enlace correspondiente a la sesión que deseemos utilizar.

Esto hará que el cliente inicie una conexión WebSocket con el servidor. Mientras se establece, se mostrará su progreso sobre el panel del navegador, aunque suele ser muy rápido. Además, aparecerá un nuevo enlace durante éste proceso denominado “Cancel Open Session”.

Browsing Libraries

Una vez abierta la sesión, se mostrarán las bibliotecas marcadas para depuración remota.

Los nodos secundarios del “Remote Debug Client” tienen un comportamiento similar al de los habituales para la edición de librerías. Cuando seleccionamos alguno de éstos nodos secundarios, el panel del navegador se actualizará para mostrar su contenido permitiendo la edición de todo el contenido de la librería.

Si se selecciona una sola clase en el panel del navegador, se mostrará un enlace denominado "Open debug window". Haga clic sobre él para abrir la ventana de depuración remota para esa clase.

Finalmente, si el servidor está en pausa y por tanto a la espera de ejecutar el inicio, entre los enlaces podrá ver uno con el nombre “Run Startup”, mediante el cual podrá indicar al servidor que debe continuar y ejecutar su proceso inicial.

La ventana del “Remote Debug”

Esta ventana muestran un diseño muy similar al del editor de métodos. Su diferencia principal está en que siempre muestra el panel de depuración y no existe un panel de edición, y en su esquina inferior derecha aparece un nuevo panel de variables.

La barra de herramientas (Instance)

Permite mostrar los métodos u objetos específicos de una instancia actualmente en uso. El menú “Instance” nos permitirá cerrarla, así como también retirarla o añadirla a la lista del depurador.

Tenga en cuenta que este menú se desactiva tan pronto como la ventana de depuración remota es asociada, es decir durante el proceso de depuración de una instancia.

Observaciones

Deberemos tener presente que el conjunto de librerías e instancias, susceptibles de ser depuradas pueden cambiar en el servidor. Omnis mantiene al cliente constantemente actualizado con respecto a la situación en que se encuentre el servidor. Por ejemplo, si una librería se cierra en el servidor, se informa al cliente y se actualiza su interfaz lo que significa su eliminación del navegador y el cierre de cualquier ventana de depuración remota relacionada. Sin embargo, si se producen cambios en un método en el servidor, el cliente no recibirá el método actualizado hasta que sea de nuevo solicitado, debe tenerse en cuenta que cada vez que el cliente realiza una operación de depuración, el cliente solicita el método y retiene una copia del mismo, hasta que la acción termina, si durante ese proceso, el método ha cambiado en el servidor, el cliente no lo recibirá hasta necesitar una nueva copia.


25 diciembre 2018

Omnis Developers Conference, Mexico City – Lunes 11 de Marzo 2019

Lunes 11 de Marzo 2019,  Omnis Developers Conference, Mexico City

Martes 12 + Miercoles 13 Marzo 2019,  Omnis Academy, Mexico City
Objetivos
  • Conocer OMNIS Studio
  • Presentar de la nueva versión 10
  • Componer aplicaciones que traspasan las fronteras
  • Componer aplicaciones Web y Moviles (Android, iOS, Windows 10)
  • Establecer contactos, conociendo más detalle sobre aplicaciones y proyectos.

Consulte la agenda e inscríbase hoy mismo...