Quartz & Seam, “You cannot rollback during a managed transaction!”

Bien, he estado un par de días liado con este problema, y al fin he dado con el error. Puedo aseguraros que ni JBoss ni Quartz dan las suficientes pautas para solventar este problema, ni tan siquiera lo comentan… En fin, ya que me ha costado tela y he tenido que consultar una y mil veces a Google para seguirle la pista, os dar alguna pista para que podáis arreglarlo.

En mi caso, utilizo Seam 2.2.1EAP5, que a su vez incluye la librería de Quartz 1.8.6. Tengo creada una tarea programada que realiza una actualización del sistema de manera autónoma cada noche (mediante cron expressions) y, a demás, ejecuto cada cierto tiempo, y bajo demanda, algunos jobs programados, para poder utilizar el bloque por base de datos que ofrece Quartz. Estos jobs son SimpleJobs de Quartz, que lanzo con fecha actual y por lo tanto se programan de manera automática para ser ejecutados inmediatamente. A demás, también hago esto para poder crear jobs únicos (distinguidos por nombre y grupo), con lo que puedo preguntarle a Quartz fácilmente qué sabe de ellos, si están vivos, en proceso, etc… Para mas inri, mis conexiones son de tipo XA (Oracle y SQLServer), y e aquí el problema. Parece ser que Quartz no se lleva demasiado bien con este tipo de conexiones. A demás, que Seam las gestiona de manera automática (con autocommit!!!)

Bien, ya os he puesto en contexto, ahora os comento lo que sucedía, por si es vuestro mismo problema.

Al ejecutar cada uno de los simplejobs el sistema lanzaba estas excepciones, alguna vez una u otra:

java.sql.SQLException: You cannot rollback during a managed transaction!] at org.quartz.impl.jdbcjobstore
java.sql.SQLException: You cannot commit during a managed transaction!] at org.quartz.impl.jdbcjobstore

Según parece, Quartz no acepta managed connections, y en cima, se lleva mal con las que son de tipo XA. Yo como tengo que hacer traspaso de datos de SQLServer a Oracle, a través de Seam, se me dan todos los casos posible.

Tras mucho buscar, y probar, al fin di con la solución. Se debe configurar una conexión non managed connection, a demás de cambiar el driver para que no utilice el típico JobStoreTX, sino que haga uso del JobStoreCMT.

Por lo tanto, entre otras propiedades, deberemos definir las siguientes, teniendo en cuenta que el datasource que definamos debe ser non managed (no definirla en Seam) y no XA (el driver tiene que ser el estandard, no XA).

Os dejo el contenido de mi seam.quartz.properties:

#=======================================================
# Configure Main Scheduler Properties
#=======================================================
org.quartz.scheduler.instanceName=myScheduler
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false

#=======================================================
# Configure ThreadPool
#=======================================================
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=5
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true

#=======================================================
# Configure JobStore
#=======================================================
org.quartz.jobStore.misfireThreshold=60000 
# org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreCMT
# org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate 
org.quartz.jobStore.nonManagedTXDataSource=myQuartzDS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.dataSource=myQuartzDS
org.quartz.jobStore.clusterCheckinInterval=10000

#=======================================================
# Configure Cluster
#=======================================================
org.quartz.jobStore.isClustered=true

#============================================================================
# Configure Datasources  
#============================================================================
org.quartz.dataSource.intervencioQuartzDS.jndiURL=java:/myQuartzDS

Prestad especial atención a las líneas comentadas, porque son las que he cambiado expresamente para solucionar esta situación:

  • 21 y 22: cambiado el JobStoreTX por JobStoreCMT
  • 23 y 24: cambiado el driver de Oracle por el JDBC Standard, esto puede no ser necesario…
  • 25 y 27: deberemos indicar dos datasources, aunque sean el mismo, pero deben ser no managed y no xa

Tras esto, arrancamos y probamos.

Confío en que mi solución también sea la vuestra. Espero vuestros comentarios.

Suerte!!!

 

Jordi

Share Button

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.