Spanish [Solucionado] Conexión a SQL SERVER con jRDC2

aspi

Member
Licensed User
Longtime User
Hola a todos.

Siguiendo el tutotal de José Aguilar (https://www.b4x.com/android/forum/threads/tutorial-acceder-a-base-de-datos-con-jrdc2.130278/), he conseguido hacer funcionar el ejemplo con mis consultas desde B4A a un servidor sql server a través de B4J. Hasta aquí todo bien.

El problema viene cuando creo el 'paquete autónomo':
  • si ejecuto el .exe (doble click), se abre y se cierra.
  • si ejecuto el exe como administrador, se ejecuta y escucha el puerto, aunque cuando hago la consulta, se produce un error.
  • si ejecuto el .bat, se ejecuta en modo depuración, se comporta igual (escucha y error al recibir la consulta)

Cuando lanzo la consulta desde la app, en el servidor aparece:

log:
Feb 26, 2023 1:24:18 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 20000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1hgeby9au13b6pej1k2q8df|7e0e6aa2, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> net.sourceforge.jtds.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1hgeby9au13b6pej1k2q8df|7e0e6aa2, idleConnectionTestPeriod -> 600, initialPoolSize -> 3, jdbcUrl -> jdbc:jtds:sqlserver://./ExitERP;instance=SQLSERVER;namedPipe=true;appname=zeta_conecta_db;charset=Cp1252;characterEncoding=Cp1252;, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 1800, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 150, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {password=******, user=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> true, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
(TimeoutException) com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool@629b2d02 -- timeout at awaitAvailable()
Command: , took: 20050ms, client=192.168.1.10

Y cuando se produce el time out:
time out:
Feb 26, 2023 1:25:03 PM com.mchange.v2.resourcepool.BasicResourcePool
WARNING: com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@3dfe9fde -- Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (30). Last acquisition attempt exception:
java.sql.SQLException: Could not find a Java charset equivalent to DB charset Cp1252.
        at b4j/net.sourceforge.jtds.jdbc.JtdsConnection.loadCharset(Unknown Source)
        at b4j/net.sourceforge.jtds.jdbc.JtdsConnection.<init>(Unknown Source)
        at b4j/net.sourceforge.jtds.jdbc.Driver.connect(Unknown Source)
        at b4j/com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(Unknown Source)
        at b4j/com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(Unknown Source)
        at b4j/com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(Unknown Source)
        at b4j/com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(Unknown Source)
        at b4j/com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(Unknown Source)
        at b4j/com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(Unknown Source)
        at b4j/com.mchange.v2.resourcepool.BasicResourcePool.access$700(Unknown Source)
        at b4j/com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(Unknown Source)
        at b4j/com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(Unknown Source)

Por lo que leo, entiendo que el problema está en la codificación de la respuesta de sql server, que en este caso es Cp1252.
error:
java.sql.SQLException: Could not find a Java charset equivalent to DB charset Cp1252.

En diferentes ejemplos, he visto dos maneras de indicarla:
  • charset=Cp1252
  • characterEncoding=Cp1252
quedando así la cadena de conexión (más vale que sobre...):
B4X:
JdbcUrl=jdbc:jtds:sqlserver://./nombre_de_mi_base_datos;instance=SQLSERVER;namedPipe=true;appname=nombre_mi_app;charset=Cp1252;characterEncoding=Cp1252;

Aun así, el error es el mismo.

Buscando la solución, veo que el fichero Charsets.properies contiene las equivalencias necesarias, así que añado:
B4X:
#CustomBuildAction: After Packager, %WINDIR%\System32\robocopy.exe, ..\ temp\build\bin\ Charsets.properties

El fichero se copia en la carpeta build\bin, pero sigue igual.

Cuando estás empezando, es muy frustrante estos errores sin sentido, ya que el programa funciona correctamente desde el IDE pero no desde el paquete autónomo.

Gracias de antemano.


Un saludo desde Murcia.
 
Last edited:

JCO

Active Member
Licensed User
Longtime User
Sin estar muy seguro intenta cambiando el charset a UTF-8:
B4X:
JdbcUrl=jdbc:jtds:sqlserver://./nombre_de_mi_base_datos;instance=SQLSERVER;namedPipe=true;appname=nombre_mi_app;charset=UTF-8;
 

aspi

Member
Licensed User
Longtime User
Hola JCO.

He probado y sigue igual, pero ahora con utf-8:
B4X:
java.sql.SQLException: Could not find a Java charset equivalent to DB charset UTF-8.

La sensación que tengo es que no encuentra Charsets.properties y no sabe como tratar la respuesta del servidor.
 

aspi

Member
Licensed User
Longtime User
Otra pista...

Si ejecuto desde B4J y navego a http://localhost:17178/test:
B4X:
El servidor remoto está ejecutándose (02/26/2023 19:56:54)
Conexión establecida.

Si mato el proceso, genero el paquete autónomo, ejecuto y voy al navegador:
B4X:
WARNING: Could not load driverClass net.sourceforge.jtds.jdbc.Driver
java.lang.ClassNotFoundException: net.sourceforge.jtds.jdbc.Driver
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
        at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Unknown Source)
        at b4j/com.mchange.v2.c3p0.DriverManagerDataSource.ensureDriverLoaded(Unknown Source)
        at b4j/com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(Unknown Source)
        at b4j/com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(Unknown Source)
        at b4j/com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(Unknown Source)
        at b4j/com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(Unknown Source)
        at b4j/com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(Unknown Source)
        at b4j/com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(Unknown Source)
        at b4j/com.mchange.v2.resourcepool.BasicResourcePool.access$700(Unknown Source)
        at b4j/com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(Unknown Source)
        at b4j/com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(Unknown Source)
 

josejad

Expert
Licensed User
Longtime User
cuando creo el 'paquete autónomo':
Hola:

Supongo que con el 'paquete autónomo' te refieres al .jar ya compilado de B4J, no?
Dónde lo estás ejecutando, en tu propio ordenador?

Cómo estás creando el exe?
Qué ocurre si lo ejecutas con algo como

"C:\Program Files\Java\jdk-11.0.1\bin\java.exe" -jar jRDC.jar
 

aspi

Member
Licensed User
Longtime User
Hola José.

Sí, en B4J, desde el menú Proyecto -> Crear un paquete autónomo.

Y si lo ejecuto de esa manera, funciona.

Eso sería una posible solución. Lo ideal sería hacer funcionar el ejecutable que se genera en \Objects\temp\build
 

josejad

Expert
Licensed User
Longtime User
Hola:

Si no me equivoco, B4JPackager11 sirve para aplicaciones con interfaz de usuario (UI), que no es el caso de un servidor jRDC2.
Por tanto, la forma de ejecutarlo sería la que te he indicado, o podrías probar Launch4j aunque ya tendrías que buscar soporte para esa app.

saludos,
 

aspi

Member
Licensed User
Longtime User
Me vale de esa manera. Muchas gracias José.

Por favor, renombra el título como solucionado. No veo forma de hacerlo.
 

josejad

Expert
Licensed User
Longtime User
Por favor, renombra el título como solucionado. No veo forma de hacerlo.
Lo siento, me temo que no puedo renombrarlo, solo lo puede hacer el propio usuario o un administrador.
Para poder editar el título, hay que ser usuario con licencia, lo cual se puede conseguir comprando una licencia de B4i o haciendo cualquier donación a B4A, B4J o B4R.


saludos,
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Tu problema es que estas usando JTDS.
Esa libreria esta desactualizada y no deberia usarse por ningun motivo.

La libreria oficial de microsoft ya esta lista para usarse con las ultimas versiones de java y deberia corregir el problema que tienes con el "paquete autonomo"
 

aspi

Member
Licensed User
Longtime User
Hola Enrique.

He probado con el driver que comentas de Microsoft...y después de muchos erroers y algunos ajustes, al final lo he conseguido.

cadena de conexión:
DriverClass=com.microsoft.sqlserver.jdbc.SQLServerDriver
JdbcUrl=jdbc:sqlserver://ip_servidor:1433;databaseName=nombre_base_datos;integratedSecurity=false;encrypt=true;trustServerCertificate=true

Main:
#AdditionalJar: mssql-jdbc-12.2.0.jre11

El último problema que encontré fue un error por no poder establecer una conexión segura con el servidor, así que habilité la encriptación y forcé que confiara en el certificado que presente el servidor:

cadena de conexión:
encrypt=true;trustServerCertificate=true

Arriba sólo he indicado los parámetros indispensables. Se pueden ver todos en https://learn.microsoft.com/es-es/s...e-connection-properties?view=sql-server-ver16

He podido comprobar que parando el servidor y volviéndolo a ejecutar, el programa reconecta sin problemas.

Ahora que ya puedo conectar, aparco un rato B4J y me divierto un rato con B4A.

Un saludo y muchas gracias a todos.
 
Top