java - Gestión global de transacciones-Jboss: cerrar una conexión para usted
spring hibernate (3)
Tenemos una aplicación de primavera implementada en un servidor jboss 7.
La aplicación utiliza múltiples fuentes de datos obtenidas de jboss a través de jndi.
La gestión de transacciones también es proporcionada por el contenedor Java EE (utilizamos Spring JtaTransactionManager)
La arquitectura de la aplicación es heredada con DAO que extiende las plantillas de hibernación (utilizando Spring HibernateDaoSupport).
Las transacciones se gestionan en la capa de servicio utilizando anotaciones @Transactional
.
Mis primeras preguntas son:
Al encontrar la anotación, ¿cómo sabe el administrador de transacciones qué fuentes de datos estarán involucradas en la transacción?
¿Cuándo recupera efectivamente una conexión JDBC y en qué fuentes de datos? ¿Cuándo abre efectivamente una transacción? (solo DAO obtuvo una referencia a sessionFactory vinculado a un origen de datos específico).
El controlador que estamos utilizando no es compatible con las transacciones distribuidas (XA) , en la mayoría de los casos no necesitamos confirmación de varias fases ya que solo se escribe una fuente de datos. De todos modos, cuando accedemos (solo lectura) a otras fuentes de datos dentro de la misma transacción, recibimos mensajes en los registros:
INFO [org.jboss.jca.core.api.connectionmanager.ccm.CachedConnectionManager] (http--0.0.0.0-8080-4) IJ000100: Closing a connection for you. Please close them yourself: org.jboss.jca.adapters.jdbc.jdk6.WrappedConnectionJDK6@691644c: java.lang.Throwable: STACKTRACE
at org.jboss.jca.core.connectionmanager.ccm.CachedConnectionManagerImpl.registerConnection(CachedConnectionManagerImpl.java:265)
at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:495)
at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:129)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81) [spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446) [hibernate-core-3.3.1.GA.jar:3.3.1.GA]
[...]
¿Hay alguna manera de gestionar adecuadamente la liberación de la conexión en ese caso sin utilizar fuentes de datos XA?
De lo contrario, ¿pueden esos mensajes ser ignorados de manera segura o denotan un problema real? (el nivel de registro es INFO)
[editar]
Algunos datos adicionales sobre la configuración:
ejemplo de declaración de fuente de datos
<!-- JNDI datasource -->
<bean id="customersDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/${shared.datasource}" />
</bean>
Associated sessionFactory
<bean id="sharedSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="customersDataSource" />
<property name="configLocation" value="classpath:hibernate.shared.cfg.xml" />
<property name="hibernateProperties">
<props>
<!-- jboss specific transaction management -->
<prop key="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>
<prop key="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>
<prop key="hibernate.connection.release_mode">after_transaction</prop>
<prop key="hibernate.transaction.auto_close_session">true</prop>
[...]
</props>
</property>
</bean>
Estamos pensando en jugar con hibernate.connection.release_mode
pero incluso si solo se escribe una fuente de datos en una sola transacción, no siempre es la misma.
Al encontrar la anotación, ¿cómo sabe el administrador de transacciones qué fuentes de datos estarán involucradas en la transacción?
Mientras tengas:
<tx:annotation-driven/>
Spring debe usar un TransactionInterceptor que intercepte su llamada al método de servicio y envuelva la solicitud en una transacción JTA.
Spring no tiene un administrador de transacciones XA real, el JtaTransactionManager es solo una fachada que requiere un proveedor JTA de back-end (como el administrador de transacciones JBoss AS).
Aún necesita configurar Jboss TM como puede ver en el siguiente artículo :
<bean id="jbossTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple">
</bean>
¿Cuándo recupera efectivamente una conexión JDBC y en qué fuentes de datos? ¿Cuándo abre efectivamente una transacción? (solo DAO obtuvo una referencia a sessionFactory vinculado a un origen de datos específico).
La transacción es activada por el JtaTransactionManager que delega la solicitud de inicio de transacción real a JBoss TM.
Todas las fuentes de datos deben ser quejas XA, no se puede mezclar JTA con recursos de datos locales. Algún administrador de transacciones puede usar la optimización LastResourceCommit que le permite alistar hasta un DataSource que no sea XA.
La fuente de datos se enlista en la transacción actual en el momento en que se desea una conexión a la base de datos:
DataSource.getConnection()
A partir de este momento, esta conexión participará en la transacción actual, por lo tanto, se comprometerá o retrotraerá en función del resultado de la transacción.
No creo que deba usar "LocalDataSourceConnectionProvider",
Si sigues este ejemplo :
Necesitas:
<jta-data-source>java:/WareHouseDS</jta-data-source>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
Hibernate necesita saber dónde obtener Jboss JNDI para el DataSource registrado.
Buena suerte con tu implementación.
Bueno, yo estaba haciendo una montaña en una colina de topo.
De hecho, algunos accesos a la fuente de datos están fuera de un alcance transaccional, ya que el modo de liberación de la conexión de hibernación está configurado en la conexión after_transaction
nunca se libera.
Acabo de agregar algunas anotaciones @Transactional faltantes y solucionó el problema.
Tenga en cuenta que parece que una propagación configurada para support
parece desencadenar la liberación de la conexión incluso cuando la persona que llama no está dentro de un alcance transaccional
Creo que la mejor manera de entender cómo funciona Jta Transaction Manager y cómo maneja múltiples fuentes de datos es hacer referencia a [Java Transaction API (JTA) specification][1]
. Después de descargarlo, consulte 3.3 Transaction interface
y 3.4 XA Ressource interface
secciones de 3.4 XA Ressource interface
.