B4J=true Group=Default Group ModulesStructureVersion=1 Type=StaticCode Version=10.3 @EndOfDesignText@ ' ######################################## ' ##### HISTORIAL DE CAMBIOS ##### ' ######################################## Sub Process_Globals '- VERSION X.XX.XX (cabios a implementar) '- Agregar que se puedan usar cualquier cantidad de archivos config.properties '- Agregar que se pueda recargar solo un archivo de configuracion o todos a la vez. '- Agregar que el "Test" del manager revise (con el query de Jorge) cuantas conexiones hay actualmente activas, ' o si no en el test, un nuevo handler, talvez "Conexiones". '- Agregar una forma de probar con carga el servidor '- Agregar la opcion de "Queries lentos" '- VERSION 5.09.13.3 '- Implementación de "Hot-Swap" para recarga de configuraciones de DB sin reiniciar el servidor. '- Migración a ReentrantLock para sincronización debido a incompatibilidad con 'Sync'. '- **Problemas Resueltos:** '- 1. **Falta de "Hot-Swap" en `reload`:** El comando `reload` en `Manager.bas` no permitía la recarga dinámica de las configuraciones de la base de datos (config.properties) sin necesidad de reiniciar el servidor. La implementación anterior simplemente re-inicializaba las instancias existentes de `RDCConnector` in-situ, sin liberar los recursos de los pools de conexión anteriores, lo cual era ineficiente y propenso a errores. '- 2. **Ausencia de un mecanismo de cierre de pools:** No existía un método `Close` en `RDCConnector.bas` que permitiera cerrar ordenadamente los `ConnectionPool` (C3P0) y liberar las conexiones a la base de datos, lo que era crítico para un "hot-swap" limpio . '- 3. **Incompatibilidad con `Sync`:** La palabra clave `Sync` de B4X no era reconocida por el entorno de desarrollo del usuario, impidiendo su uso para la sincronización de hilos necesaria en el "hot-swap". '- 4. **Ausencia de `Finally` en B4X:** La palabra clave `Finally` (común en otros lenguajes como Java para asegurar la liberación de recursos) no está disponible directamente en B4X, lo cual planteó un desafío para garantizar la liberación del `ReentrantLock` de forma segura. '- **Cambios Implementados:** '- **En `Main.bas`:** '- * **Declaración de `MainConnectorsLock`:** Se añadió `Public MainConnectorsLock As JavaObject` en `Sub Process_Globals` para declarar una instancia de `java.util.concurrent.locks.ReentrantLock`, que servirá como objeto de bloqueo global para proteger el mapa `Main.Connectors`. '- * **Inicialización de `MainConnectorsLock`:** Se inicializó `MainConnectorsLock.InitializeNewInstance("java.util.concurrent.locks.ReentrantLock", Null)` en `Sub AppStart`, asegurando que el objeto de bloqueo esté listo al inicio del servidor. '- **En `RDCConnector.bas`:** '- * **Método `Public Sub Close`:** Se añadió esta subrutina al final del módulo. Utiliza `JavaObject` para invocar `joPool.RunMethod("close", Null)` sobre la instancia subyacente de C3P0, permitiendo un cierre ordenado y la liberación de todas las conexiones del pool . '- **En `Manager.bas`:** '- * **Reemplazo completo de la lógica `If Command = "reload" Then`:** '- * **Creación de `newConnectors`:** Se crea un mapa temporal (`Dim newConnectors As Map`) para inicializar las **nuevas instancias** de `RDCConnector` con la configuración fresca de los archivos `.properties` . '- * **Preservación de `oldConnectors`:** Se almacena una referencia al mapa `Main.Connectors` actual en un nuevo mapa (`Dim oldConnectors As Map`) para tener acceso a los conectores antiguos que necesitan ser cerrados . '- * **Sincronización con `ReentrantLock`:** Para proteger la manipulación del mapa `Main.Connectors` (que es compartido por múltiples hilos), se utilizan `Main.MainConnectorsLock.RunMethod("lock", Null)` y `Main.MainConnectorsLock.RunMethod("unlock", Null)`. Esto asegura que el reemplazo del mapa sea atómico, es decir, que solo un hilo pueda acceder a `Main.Connectors` durante la lectura y la escritura . '- * **Manejo de Bloqueo Seguro sin `Finally`:** Dado que `Finally` no está disponible en B4X, se implementó un patrón con una bandera booleana (`lockAcquired`) dentro de un bloque `Try...Catch` para garantizar que `unlock()` siempre se ejecute si `lock()` fue exitoso, previniendo interbloqueos . '- * **Cierre explícito de `oldConnectors`:** Después de que los `newConnectors` reemplazan a los `oldConnectors`, se itera sobre el mapa `oldConnectors` y se llama a `oldRDC.Close` para cada conector, liberando sus recursos de base de datos de manera limpia . '- * **Validación de inicialización y control de errores:** Se agregó lógica para verificar el éxito de la inicialización de los nuevos conectores y abortar el "hot-swap" si ocurre un error crítico, manteniendo los conectores antiguos activos para evitar una interrupción del servicio . '- * **Registro detallado:** Se mejoró la salida del log HTML del `Manager` para mostrar el proceso de recarga, las estadísticas de los pools recién inicializados y el cierre de los antiguos, incluyendo JSON detallado de las métricas de C3P0 . '- • Beneficio: Estos cambios dotan al servidor jRDC2-Multi de una capacidad crítica para actualizar sus configuraciones de conexión a bases de datos en caliente, sin necesidad de reiniciar el servicio. Esto mejora la disponibilidad, simplifica el mantenimiento y previene fugas de recursos al asegurar el cierre ordenado de los pools de conexión antiguos. '- VERSION 5.09.13.2 '- Módulo: DBHandlerJSON.bas '- Descripción de Cambios: Manejo de Peticiones POST con Content-Type: application/json '- • Problema Identificado: La implementación anterior de DBHandlerJSON procesaba las peticiones POST esperando que el payload JSON se encontrara en el parámetro j de la URL (req.GetParameter("j")). Esto impedía la correcta lectura de peticiones POST que utilizaban Content-Type: application/json, donde el JSON se envía directamente en el cuerpo de la petición (InputStream). Como resultado, los clientes recibían un error indicando la ausencia del parámetro j . '- • Solución Implementada: '- 1. Se modificó la lógica en el método Handle para detectar explícitamente las peticiones POST con Content-Type igual a application/json. '- 2. En estos casos, el payload JSON ahora se lee directamente del InputStream de la petición (req.InputStream). '- 3. Se utilizó Bit.InputStreamToBytes(Is0) para leer el cuerpo completo de la petición a un Array de bytes, seguido de BytesToString para convertirlo en la cadena JSON. '- 4. Se añadió el cierre explícito del InputStream (Is0.Close) para asegurar la liberación de recursos . '- 5. Se corrigió el nombre de la variable Is a Is0 para evitar un conflicto con la palabra reservada Is de B4X . '- 6. Se actualizó el mensaje de error para aclarar que el JSON puede faltar tanto en el parámetro j como en el cuerpo de la petición. '- • Beneficio: Esta corrección asegura que el DBHandlerJSON sea compatible con el "Método Recomendado" de POST con application/json, mejorando la robustez y la adherencia a los estándares de las APIs web, Sin comprometer la retrocompatibilidad con el "Método Legacy" (GET con parámetro j). '- VERSION 5.09.13 ' feat: Mejora la inicialización del pool de conexiones y el soporte multi-DB. ' ' - Este commit aborda y resuelve varios problemas críticos relacionados con la inicialización ' del pool de conexiones (C3P0) para múltiples bases de datos y la depuración de logs ' en el servidor jRDC2-Multi. ' ' **Problemas Resueltos:** ' ' 1. **Inicialización de `TotalConnections: 0` en todos los pools:** Anteriormente, el Log mostraba 0 conexiones inicializadas para todas las bases de datos (DB1, DB2, DB3, DB4) durante `AppStart`, a pesar de que los `handlers` de `DBHandlerB4X` y `DBHandlerJSON` podían conectarse más tarde bajo demanda. Esto indicaba un fallo silencioso en la creación de conexiones iniciales por parte de C3P0. ' 2. **Configuración inconsistente de C3P0:** Parámetros críticos de C3P0 como `acquireRetryAttempts` y `breakAfterAcquireFailure` no se aplicaban correctamente al inicio, manteniendo los valores por defecto que ocultaban errores de conexión. ' 3. **`jdbcUrl` truncado/vacío:** Se observó que la `jdbcUrl` aparecía truncada o vacía en algunos logs de C3P0, indicando un problema en la carga de la configuración. ' ' **Cambios Implementados:** ' ' **En `Main.bas`:** ' ' * **Declaración de conectores:** Se aseguró la declaración de variables `Dim conX As RDCConnector` separadas para cada conector (con1, con2, con3, con4) para evitar conflictos de variables y asegurar la inicialización correcta. ' **En `RDCConnector.bas`:** ' ' * **Corrección de *shadowing* de `config`:** Se modificó `LoadConfigMap(DB)` para asignar directamente a la variable de clase `config` (eliminando `Dim` local), resolviendo el problema de la `jdbcUrl` truncada y asegurando que cada `RDCConnector` use su configuración específica de manera persistente. ' * **Reordenamiento y robustecimiento de `Initialize`:** ' * **Carga de `config`:** Se asegura que `config` se cargue completamente en la variable de clase antes de cualquier operación del pool. ' * **Configuración de C3P0:** Todas las propiedades del pool (incluyendo `setInitialPoolSize`, `setMinPoolSize`, `setMaxPoolSize`, `setMaxIdleTime`, etc. ahora se aplican mediante `jo.RunMethod` *inmediatamente después* de `pool.Initialize` y *antes* de que el pool intente adquirir conexiones. ' * **Forzar reportes de errores:** Se añadieron las líneas `jo.RunMethod("setAcquireRetryAttempts", Array As Object(1))` y `jo.RunMethod("setBreakAfterAcquireFailure", Array As Object(True))`. Estas son cruciales para forzar a C3P0 a lanzar una `SQLException` explícita si falla al crear las conexiones iniciales, en lugar de fallar silenciosamente. ' * **Activación forzada del pool:** Se implementó `Dim tempCon As SQL = pool.GetConnection` seguido de `tempCon.Close` dentro de un bloque `Try...Catch`. Esto obliga al pool a establecer las conexiones iniciales (`InitialPoolSize`) con la configuración ya aplicada, permitiendo la captura de errores reales si la conexión falla. '- VERSION 5.09.08 '- Se agregó que se puedan configurar en el config.properties los siguientes parametros: ' ' - setInitialPoolSize = 3 ' - setMinPoolSize = 2 ' - setMaxPoolSize = 5 ' '- Se agregaron en duro a RDConnector los siguientes parametros: ' ' - setMaxIdleTime <-- Tiempo máximo de inactividad de la conexión. ' - setMaxConnectionAge <-- Tiempo de vida máximo de una conexión. ' - setCheckoutTimeout <-- Tiempo máximo de espera por una conexión. ' '- Se agregó en el config.properties, al final del "JdbcUrl" este parametro, que le indica al servidor de Oracle ' el nombre del cliente que se está conectando "?v$session.program=jRDC_Multi" '- VERSION 5.09.08 '- Se cambio el codigo para que en lugar de esperar un mapa con los parametros del query y nombres de los parametros (par1, par2, etc) para definir el ordenamiento, ahora se espera una lista [1,"2",3], y el orden de los parametros se toma directamente del orden en el que se mandan, de la misma forma que en B4A. '- VERSION 5.09.04 '- Se cambio el nombre del handler de B4X a DBHandlerB4X. '- Se quitaron los handlers que ya no servian. '- VERSION 5.09.01 '- Se corrigieron errores en "Manager". '- Se cambiaron nombres de handlers. '- Se corrigio un error en la ruta de "www/login.html". '- VERSION 5.08.31 '- Se corrigio que no avisaba cuando el query no requeria parametros y si se enviaban (en el JSONHandler) '- VERSION 5.08.30 '- Se cambiaron los 4 handlers de B4A a uno solo que toma el DB de la ruta automáticamente. '- Se agregaron validaciones del numero de parametros y si el query no los requiere o se dan de mas o de menos, manda un error especificando eso, ya no se reciben errores directos de la base de datos, esto fue tanto para B4A como para JSON. '- Se modificó el Readme.md para incluir todos estos cambios. '- VERSION 5.08.25 '- Se modificaron los archivos de reinicio de los servicios (servidor y Bow) y se cambio el menu del "manager" para que a seccion de "reload" incluya la liga a reinciar Bow. '- VERSION 5.08.02 '- Se hizo un cambio para tratar de que las conexiones se "identifiquen" con Oracle y Jorge pueda saber que conexiones/recursos estamos ocupando '- VERSION 4.11.14 '- Se agregó el parametro "setMaxPoolSize=5" para que solo genere 5 conexiones a la base de datos, antes generaba 15. '- Se quitaron lineas previamente comentadas. '- VERSION 4.11.09 '- Commit inicial on Nov 9, 2024 End Sub