Announcement Announcement Module
Collapse
No announcement yet.
JtaTransactionManager / Hibernate / JMS ( MQServer ) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JtaTransactionManager / Hibernate / JMS ( MQServer )

    Hey People of Spring,

    Need fresh ideas on how to make "JtaTransactionManager" to behave:

    GIVEN:
    ------

    1. Hibernate 3.1
    2. MQServer 6.0
    3. Sun Application Server 8.2

    PROBLEM DESCRIPTION:
    -----------------------

    Got it working with

    Hibernate (transacting DAOs) but not MQ Series
    or
    MQServer ( transacting JMS ) but not Hibernate

    There is a synchronous JMS call (send/receive) which needs a separate transaction on send ( so it is committed and it can receive ), hence the global transaction, that transacts everything (including DAOs) needs to be suspended, therefore corresponding propagation level ( NOT_SUPPORTED or REQUIRES_NEW ) is applied.

    However "JtaTransactionManager" does not like to suspend/resume and fails to do so:

    Code:
    Caused by: java.lang.IllegalStateException
        at com.sun.jts.jta.TransactionManagerImpl.resume(TransactionManagerImpl.java:420)
        at com.sun.enterprise.distributedtx.J2EETransactionManagerImpl.resume(J2EETransactionManagerImpl.java:1011)
        at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.resume(J2EETransactionManagerOpt.java:493)
    If two unrelated pointcuts used - meaning DAO will need to be transacted in one method, and sync JMS call happens in the other, then DAO part is transacted, however JMS part is not.

    But what really needed is to transact a method (submitApplication) that calls DAO and send/receives a JMS message.

    According to Sun's documentation and sources "J2EETransactionManagerImpl" supports suspend and resume.

    CONFIGURATION:
    ----------------

    Hibernate Session Factory:

    Code:
        <!-- Hibernate SessionFactory -->
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
         
            <property name="mappingLocations">
                <value>classpath*:conf/*.hbm.xml</value>
            </property>
    
            <property name="jtaTransactionManager">
                <bean factory-bean="transactionManager" factory-method="getTransactionManager"/>
            </property>
    
            <property name="hibernateProperties">
                <props>
    
                    <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
                    <prop key="hibernate.use_sql_comments">true</prop> 
    
                    <prop key="hibernate.connection.datasource">${dataSources.dataSource.jndiName}</prop>
    
                    <prop key="hibernate.connection.release_mode">auto</prop>
                    <prop key="hibernate.current_session_context_class">jta</prop>
                    <prop key="hibernate.transaction.flush_before_completion">true</prop>
                    <prop key="hibernate.transaction.auto_close_session">true</prop>
    
    <!--
                    <prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.SunONETransactionManagerLookup</prop>
                    <prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>
    -->
                </props>
            </property>
        </bean>
    JTA Transaction Manager:

    Code:
        <jee:jndi-lookup id="platformTransactionManager" jndi-name="java:appserver/TransactionManager" resource-ref="false" expected-type="javax.transaction.TransactionManager"/>
    
        <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    
            <constructor-arg ref="platformTransactionManager"/>
    
            <property name="defaultTimeout" value="60"/>
    
        </bean>
    AOP TX Configuration:

    Code:
        <!-- Transact "submitApplication" service method -->
        <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
            <tx:attributes>
    
                <tx:method name="submit*" propagation="REQUIRED"/>
    
            </tx:attributes>
        </tx:advice>
    
        <!-- Outbound Connector (JMS) - sending part should not participate in the "main" transaction -->
        <tx:advice id="outboundConnectorAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="send" propagation="NOT_SUPPORTED"/>
            </tx:attributes>
        </tx:advice>
    
        <aop:config>
    
            <aop:pointcut id="servicePointcut" expression="execution(* org.us.service.OurSvc.*(..))" />
            <aop:pointcut id="outboundConnectorPointcut" expression="execution(* org.us.integration.connector.OutboundConnector.*(..))"/>
    
            <aop:advisor advice-ref="transactionAdvice" pointcut-ref="servicePointcut"/>
            <aop:advisor advice-ref="outboundConnectorAdvice" pointcut-ref="outboundConnectorPointcut" />
    
        </aop:config>
    Would appreciate your fresh ideas,

    -- litius

  • #2
    Problem solved - will post later with solution,

    -- litius

    Comment


    • #3
      Can you post your solution to tell how did you resolve the problem?

      Comment


      • #4
        a bit overdue with the solution, but still want to have it here, in case anybody else struggles. straight from my notes:

        Spring AOP/JEE/TX header:

        Code:
        <?xml version="1.0" encoding="UTF-8"?>
        
        <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:p="http://www.springframework.org/schema/p"
            xmlns:aop="http://www.springframework.org/schema/aop"
            xmlns:tx="http://www.springframework.org/schema/tx" 
            xmlns:jee="http://www.springframework.org/schema/jee"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
                    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
        JTA Transaction Manager Configuraion:

        Code:
            <jee:jndi-lookup id="platformTransactionManager" jndi-name="java:appserver/TransactionManager" resource-ref="false" expected-type="javax.transaction.TransactionManager"/>
        
            <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        
                <constructor-arg ref="platformTransactionManager"/>
        
            </bean>
        AOP Proxies ( Advices & Pointcuts ):

        Code:
            <tx:advice id="serviceTransactionAdvice" transaction-manager="transactionManager">
                <tx:attributes>
                    <tx:method name="*" propagation="REQUIRES_NEW"/>
                </tx:attributes>
            </tx:advice>
        
            <tx:advice id="outboundQueueConnectorAdvice" transaction-manager="transactionManager">
                <tx:attributes>
                    <tx:method name="send" propagation="REQUIRES_NEW"/> 
                </tx:attributes>
            </tx:advice>
        
            <aop:config>
        
                <aop:pointcut id="xxxYyyServicePointcut" expression="execution(* org.some.package.service.xxxYyySvc.*(..))" />
                <aop:pointcut id="outboundQueueConnectorPointcut" expression="execution(* org.some.package.impl.QueueOutboundConnectorImpl.*(..))"/>
          
                <aop:advisor advice-ref="serviceTransactionAdvice" pointcut-ref="xxxYyyServicePointcut"/> 
                <!-- <aop:advisor advice-ref="outboundQueueConnectorAdvice" pointcut-ref="outboundQueueConnectorPointcut" /> -->
        
            </aop:config>
        Hibernate Spring Configuration:

        Code:
        <beans>
        
            <!-- Hibernate SessionFactory -->
            <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        
                <property name="mappingLocations">
                    <value>classpath*:conf/*.hbm.xml</value>
                </property>
        
                <property name="dataSource" ref="dataSource" />
        
                <property name="jtaTransactionManager">
                    <bean factory-bean="transactionManager" factory-method="getTransactionManager"/>
                </property>
        
                <property name="hibernateProperties">
                    <props>
        
                        <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
                        <prop key="hibernate.use_sql_comments">true</prop>
        
                        <prop key="hibernate.connection.release_mode">auto</prop>
                        <prop key="hibernate.current_session_context_class">jta</prop>
                        <prop key="hibernate.transaction.auto_close_session">true</prop>
        
                    </props>
                </property>
            </bean>
        
        </beans>
        JMS Configuration:

        Code:
            	<bean id="xyzJmsTemplate" parent="abstractxyzJmsTemplate">
                <property name="connectionFactory" ref="xyzMQConnectionFactory"/>
                <property name="destinationResolver" ref="xyzJmsDestinationResolver"/>
            </bean> 
        
            <bean id="xyzMQConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
                <property name="jndiTemplate" ref="xyzJndiTemplate"/>
                <property name="jndiName" value="${someConfig.xyz.QConnFactory.jndiName}"/>
            </bean>
            
            <!-- JNDI Environment Template -->
            <bean id="xyzJndiTemplate" class="org.springframework.jndi.JndiTemplate"/>    
        
            <!-- JMS Destination Resolver -->
            <bean id="xyzJmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
                <property name="jndiTemplate" ref="xyzJndiTemplate"/>
                <property name="cache" value="true"/>
            </bean>

        Comment

        Working...
        X