Announcement Announcement Module
Collapse
No announcement yet.
EJB + Spring + Transactions Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • EJB + Spring + Transactions

    I am trying to get Transactions working in the following scenario:

    SSB (with CMT) --> POJO (Injected with JMSTtemplate) --> Sends JMS Msg

    I have looked up the XA connection factory from weblogic and injected the JMS template with it. I expect the JMS message to be put on the queue only when i commit in the SSB. When i setRollbackonly to true in the SSB, i expect the JMS message not to be put on the queue. However that doesnt seem to happen. The message is put on the queue even when i rollback in the SSB.

    How do i get Spring to participate in the Transaction from the SSB?

    Here is the configuration:

    Code:
    ejb-jar.xml
    
        <enterprise-beans>
            <session>
                <display-name>PMSimulator</display-name>
                <ejb-name>PMSimulator</ejb-name>
                <home>com.abc.xyz.pmsimulator.PMSimulatorHome</home>
                <remote>com.abc.xyz.pmsimulator.PMSimulatorRemote</remote>
                <ejb-class>com.abc.xyz.pmsimulator.PMSimulatorBean</ejb-class>
                <session-type>Stateless</session-type>
                <transaction-type>Container</transaction-type>
                <resource-ref>
                    <res-ref-name>jms/mqwmcappqm1xaqcf</res-ref-name>
                    <res-type>javax.jms.QueueConnectionFactory</res-type>
                    <res-auth>Container</res-auth>
                    <res-sharing-scope>Shareable</res-sharing-scope>
                </resource-ref>
                <resource-env-ref>
                    <resource-env-ref-name>
                        jms/pm.submission.to.tg</resource-env-ref-name>
                    <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
                </resource-env-ref>
            </session>
        </enterprise-beans>
    
        <assembly-descriptor>
            <container-transaction>
                <method>
                    <ejb-name>PMSimulator</ejb-name>
                   <method-name>*</method-name>
                </method>
                <trans-attribute>Required</trans-attribute>
            </container-transaction>
        </assembly-descriptor>
    
    
    Weblogic-ejb-jar.xml
    
        <weblogic-enterprise-bean>
            <ejb-name>PMSimulator</ejb-name>
            <transaction-descriptor>
                <trans-timeout-seconds>3600</trans-timeout-seconds>
            </transaction-descriptor>
            <reference-descriptor>
                <resource-description>
                    <res-ref-name>jms/mqwmcappqm1xaqcf</res-ref-name>
                    <jndi-name>mqwmcappqm1xaqcf</jndi-name>
                </resource-description>
                <resource-env-description>
                    <res-env-ref-name>
                        jms/pm.submission.to.tg</res-env-ref-name>
                    <jndi-name>pm.submission.to.tg</jndi-name>
                </resource-env-description>
            </reference-descriptor>
            <enable-call-by-reference>true</enable-call-by-reference>
            <jndi-name>PMSimulator</jndi-name>
        </weblogic-enterprise-bean>
    
    
    Spring Context
    
    
        <!-- Define XA Connection Factory -->
    
        <bean id="common.messaging.XAConnectionFactory"
            class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">
            <property name="jndiName" value="mqwmcappqm1xaqcf"/>
        </bean>
    
        <!-- Define Transaction Manager -->
        <bean id="transactionManager"
            class="org.springframework.transaction.jta.WebLogicJtaTransactionManager" lazy-init="true">
        </bean>
    
        <!-- Enlist Transactional Resources -->
        <bean id="TransactionProxy"
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true">
            <property name="transactionManager">
                <ref bean="transactionManager"/>
            </property>
            <property name="transactionAttributes">
                <props>
                    <prop key="*">PROPAGATION_REQUIRED</prop>
                </props>
            </property>
        </bean>

  • #2
    1) Your TransactionProxy is useless, is doesn't do anything.
    2) Make sure your service call is transactional, currently I see no transactional service.
    3) Make sure you use the transactional service and not the unproxied instance..

    Comment


    • #3
      Marten,

      Thanks for your response.

      Since i am pretty new to Spring (Transactions), and couldn't find many examples around this on the internet, i was pretty much suspecting my spring configuration.

      Questions on your response:

      1. Why do you think the ProxyBean is not required? Isnt the proxy bean supposed to be wiring together the TransactionManager, Target (POJO) & also define the Transaction Attributes?

      Code:
          <bean id="MessageSender"
      class="com.abc.xyz.client.MessageSender">
              <property name="jmsTemplate" ref="jmsTemplate"/>
          </bean>
      
          <bean id="TransactionProxy"     class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
              lazy-init="true">
              <property name="transactionManager">
                  <ref bean="transactionManager"/>
              </property>
              <property name="target">
                  <ref local="MessageSender"/>
              </property>
              <property name="transactionAttributes">
                  <props>
                      <prop key="commit*">PROPAGATION_MANDATORY</prop>
                  </props>
              </property>
          </bean>
      2. Could you please be a little more specific when you say service call should be transactional? Isnt the SSB operating within the scope of a transaction created by the container?

      It would really helpful, if there is an example that you could point me to.
      Last edited by silverdream; Jun 2nd, 2008, 05:57 PM.

      Comment


      • #4
        1. Why do you think the ProxyBean is not required? Isnt the proxy bean supposed to be wiring together the TransactionManager, Target (POJO) & also define the Transaction Attributes?
        The sample you first posted didn't contain a target, so was pretty useless. Next to that you need to USE the proxy instead of the unproxied bean. So instead of using the MessageSender you need to use the TransactionProxy. (Chapter of the reference guide 6 explains proxies and spring aop in detail!).

        Comment


        • #5
          Marten,

          I understood the part about using the ProxyBean instead of the Unproxied Bean. Thank you for helping out.

          That apart, doing some more reading, i figured out that inorder to use the transaction from weblogic, all i needed to do was to lookup the connectionfactory from JNDI and that was enough for Spring to use that transaction to send the message. I didnt have to define the TransactionManager & ProxyBean in spring to use the transaction.

          http://dev2dev.bea.com/blog/maximdim...ssaging_w.html

          I tested this out with JMSTemplate102 and MQXAQueueConnectionFactory and i am able to test a 2 phase commit successfully.

          However when i try to use the unified MQXAConnectionFactory, the rollback doesn't seem to work. The message is still put on the queue when i set the ctx.setRollbackOnly.

          If i go back to use MQXAQueueConnectionFactory, 2PC works again.

          This problem is driving me nuts. I think its more of a question in the Bea forums but just thought i will give it a shot here.

          BTW, i have the following question:

          If i dont need to use WeblogicJTATransactionManager and not define the ProxyBean in this scenario to support transaction, then which scenario do these get used?

          Comment


          • #6
            You need a JTA transactionmanager configured, else spring will not detect any transaction. However your configuration can be simplyfied. By using the tx and aop namespaces.

            Code:
            <tx:jta-transaction-manager/>
            
            <tx:advice id="txAdvice>
              <tx:attributes>
                <tx:method name="commit*" propagation="REQUIRED" />
              </tx:attributes>
            </tx:advice>
            
            <aop:config>
              <aop:pointcut id="serviceMethods" expression="execution(* com.mycompane.*Service.*(..))" />
              <aop:advice pointcut-ref="serviceMethods" advice-ref="txAdvice" />
            </aop:config>
            The above is way shorter and easier then define a TransactionalProxy for all your beans.

            Comment


            • #7
              For some reason, i didnt need to define a TransactionManager in Spring to participate in the Transaction from Weblogic. It works perfectly fine with a QueueConnectionFactory.

              When i switch to ConnectionFactory, it does not participate in the Transaction even if i define the Transaction Manager.

              Has anyone tried testing this configuration with Websphere MQ?

              Comment

              Working...
              X