lunes, 15 de julio de 2013

Genexus y "No operations allowed after connection closed.Connection was implicitly closed by the driver."


Me he vuelto loco con este error, todavía no tengo muy claro a que se debe pero parece ser que Genexus mantiene la conexion abierta mientras mysql la cerró, al intentar acceder nuevamente la webapp cae.

Sintomas:  En un webpanel cualquiera el cual se mostraba perfectamente, luego de transcurrida cierta cantidad de tiempo , al hacer refresh aparece el error:

Estado HTTP 500 -


type Informe de Excepción
mensaje
descripción El servidor encontró un error interno () que hizo que no pudiera rellenar este requerimiento.
excepción
javax.servlet.ServletException: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.Connection was implicitly closed by the driver.
 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
 at java.lang.reflect.Constructor.newInstance(Unknown Source)
 at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
 at com.mysql.jdbc.Util.getInstance(Util.java:381)
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1012)
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:986)
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:981)
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
 at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1201)
 at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1188)
 at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4273)
 at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4239)
 at com.genexus.db.driver.GXConnection.prepareStatement(Unknown Source)
 at com.genexus.db.driver.PreparedStatementCache.createStatement(Unknown Source)
 at com.genexus.db.driver.PreparedStatementCache.getStatement(Unknown Source)
 at com.genexus.db.driver.GXConnection.getStatement(Unknown Source)
 at com.genexus.db.driver.GXConnection.getStatement(Unknown Source)
 at com.genexus.db.SentenceProvider.getPreparedStatement(Unknown Source)
 at com.genexus.db.ForEachCursor.preExecute(Unknown Source)
 at com.genexus.db.DataStoreProvider.execute(Unknown Source)
 at com.genexus.db.DataStoreProvider.execute(Unknown Source)
 at com.genexus.db.DataStoreProvider.execute(Unknown Source)
 at com.genexus.db.DataStoreProvider.execute(Unknown Source)
 at com.genexus.db.DataStoreProvider.execute(Unknown Source)

Lo primero que hice fue ver los valores de conexión del mysql, las variables interactive_timeout y wait_timeout
Para ello en el administrador de consultas de mysql ejecutar: Show Variables like '%timeout'

Ambas estaban con el valor 300 , es decir que transcurridos 300 segundos mysql cerraría la conexión.

Visto eso se me ocurrió agregar en el connection string un ?autoreconnect=true para que se vuelva a conectar, pero eso empeoro las cosas ya que quedaba intentando reconectar hasta caer por heap space error, matandome el servidor.

Luego de semanas de idas y venidas la solución aparentemente fue la siguiente:

Setear las propiedades del datastore Recycle type y Recycle time asi:
El valor 3 de recycle time corresponde a un valor menor al seteado en wait_timout de mysql, hay que tener en cuenta que uno va expresado en minutos y el otro en segundos.