activemq-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jeroend <jer...@dijkmeijer.com>
Subject ActiveMQ on Websphere REQUIRES_NEW transactions.
Date Thu, 18 Mar 2010 09:37:22 GMT

Environment: 
Win32 
Environment
Websphere 6.1.0.13 

ActiveMQ 5.3.0 [Win32, same machine as WAS] 
ActiveMQ configured with accompanying Resource Adapter on Websphere. 

Spring 2.5.6. 
Hibernate 3.3.2 

LS, 

In preparation for our Websphere - Websphere MQ connection and absense of
the latter on our dev boxes we decided to set up a test environment locally
using Active MQ.

It has served us well in a better understanding of jms/mq and messaging and
configuring Spring to read out queues and setting up transactions.
After the low hanging fruit, a bit more sophisticated use case  came up: 
On the failure of parsing and storing a message, a new entry should be made
in a a notification table, apart of course from dequeueing the message. The
addNotification method in our NotificationService is wired with a
REQUIRES_NEW transaction in an aop configuration, but the addNotification
method fails with following exception:

[18-3-10 9:35:38:230 CET] 00000022 XATransaction E   J2CA0027E: An exception
occurred while invoking end on an XA Resource Adapter from dataSource
jms/gridMQFactory, within transaction ID {XidImpl: formatId(57415344),
gtrid_length(36), bqual_length(54),
data(000001277069dc4700000003000000b13663870e08a69927dc8e87578289a39c2b540745000001277069dc4700000003000000b13663870e08a69927dc8e87578289a39c2b540745000000010000000000000000000000000001)}:
javax.transaction.xa.XAException 	at
org.apache.activemq.ra.LocalAndXATransaction.end(LocalAndXATransaction.java:95) 
at com.ibm.ejs.j2c.XATransactionWrapper.end(XATransactionWrapper.java:574) 
at com.ibm.ws.Transaction.JTA.JTAResourceBase.end(JTAResourceBase.java:237) 
at
com.ibm.ws.Transaction.JTA.RegisteredResources.sendEnd(RegisteredResources.java:1341) 
at
com.ibm.ws.Transaction.JTA.RegisteredResources.distributeEnd(RegisteredResources.java:1315)

at
com.ibm.ws.Transaction.JTA.TransactionImpl.distributeEnd(TransactionImpl.java:2432) 
at
com.ibm.ws.Transaction.JTA.TransactionImpl.prepareResources(TransactionImpl.java:2058) 
at
com.ibm.ws.Transaction.JTA.TransactionImpl.stage1CommitProcessing(TransactionImpl.java:1646)

at
com.ibm.ws.Transaction.JTA.TransactionImpl.processCommit(TransactionImpl.java:1602) 
at
com.ibm.ws.Transaction.JTA.TransactionImpl.commit(TransactionImpl.java:1537) 
at
com.ibm.ws.Transaction.JTA.TranManagerImpl.commit(TranManagerImpl.java:239) 
at com.ibm.ws.Transaction.JTA.TranManagerSet.commit(TranManagerSet.java:163) 
at com.ibm.ws.uow.UOWManagerImpl.uowCommit(UOWManagerImpl.java:1055) 	at
com.ibm.ws.uow.UOWManagerImpl.uowEnd(UOWManagerImpl.java:1025) 	at
com.ibm.ws.uow.UOWManagerImpl.runUnderNewUOW(UOWManagerImpl.java:975) 	at
com.ibm.ws.uow.UOWManagerImpl.runUnderUOW(UOWManagerImpl.java:509) 	at
org.springframework.transaction.jta.WebSphereUowTransactionManager.execute(WebSphereUowTransactionManager.java:252)

at
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:123)

at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)

at
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)

at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)

at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 
at $Proxy1.addNotification(Unknown Source)  
<zip>
Caused by: javax.jms.JMSException: The resource is allready being used in
transaction context. 	at
org.apache.activemq.ra.ManagedTransactionContext.setUseSharedTxContext(ManagedTransactionContext.java:47)

at
org.apache.activemq.ra.ManagedSessionProxy.setUseSharedTxContext(ManagedSessionProxy.java:67)

at
org.apache.activemq.ra.ManagedConnectionProxy.setUseSharedTxContext(ManagedConnectionProxy.java:138)

at
org.apache.activemq.ra.ActiveMQManagedConnection$1.setInManagedTx(ActiveMQManagedConnection.java:83)

at
org.apache.activemq.ra.LocalAndXATransaction.end(LocalAndXATransaction.java:93) 
... 60 more 

We are suspecting  the resource adapter for this as the exception occurs in
"org.apache.activemq.ra.ManagedTransactionContext" and it works as expected
on Websphere MQ.

Below the layout of our spring jms configuration complete with relevant java
code. If needed we can supply a minimal testcase to demonstrate the above
documented behaviour.

    <bean id="gridMessageListener"
class="nl.our.company.jms.GridMessageListener"> 
        <property name="gridDAO" ref="gridDAO"/> 
        <property name="processTypeDAO" ref="processTypeDAO"/> 
        <property name="officeDAO" ref="officeDAO"/> 
        <property name="notificationService" ref="notificationService"/> 
    </bean> 
    <jms:listener-container transaction-manager="txManager"
task-executor="jmsTaskExecutor" 
                            connection-factory="trissJMSConnectionFactory"
destination-resolver="destinationResolver"> 
        <jms:listener destination="jms/gridQueue" ref="gridMessageListener"
method="receive"/> 
    </jms:listener-container> 
   
    <bean id="destinationResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver"> 
        <property name="fallbackToDynamicDestination" value="true"/> 
        <property name="resourceRef" value="true"/> 
    </bean> 


The grid MessageListener's code: 
        public void onMessage(Message msg) { 
                String msgText = null; 
                try { 
                        logger.trace("MSG IS " + msg + " messagetype
is " 
                                + msg.getJMSType()); 
                        boolean success = false; 
                        if (msg instanceof TextMessage) { 
                                StreamSource source = new StreamSource(new
ByteArrayInputStream( 
                                        ((TextMessage)
msg).getText().getBytes())); 
                                success = process(source); 
                                if (!success) { 
                                        msgText = ((TextMessage)
msg).getText(); 
                                } 
                        } else if (msg instanceof BytesMessage) { 
                                success = ... 
                        } else { 
                                logger.info("message is not recognized");

                        } 
                } catch (JMSException e1) { 
                        logger.error("error occured: ", e1); 
                } finally { 
                        if (msgText != null) { 
                                try { 
                                        ProcessInfor pio
= new
ProcessInfo(..); 
                                       
notificationService.addNotification(NotificationTypeDAO.NOTIFICATION_TYPE_GRID_DELIVERY_FAILED

                                               
, "GRID MQ Delivery Failed",
msgText, pio, NotificationDAO.NOTIFICATION_SEVERITY_ERROR);

                                } catch (Exception e) { 
                                        logger.error("error
", e); 
                                } 
                        } 
                } 
        } 

The magic is happening in the process(source), which parses and stores the
message. Unfortunately the parsing fails with a oracle "not null" exception.

java.sql.BatchUpdateException: ORA-01400: <zip> 

        at
oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343) 
[11-3-10 11:57:51:170 CET] 0000007f SystemOut     O ERROR 11-03-10
11:57:51,092 nager : 10 nl.our.company.businesslayer.jms.GridMessageListener
- error occured

org.springframework.dao.DataIntegrityViolationException: Could not execute
JDBC batch update; nested exception is
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC
batch update

        at
org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:636)

Which we can and should solve on our side but, still we should be prepared
for errors like this. The process method catches this exception, and returns
false.

Default our dao's and services are aop:advice'd with propagation:required,
however the notificationService has a propegation:requires_new (we need the
notificationService more than once outside current transactions)

        <tx:advice id="jmsAdvice" transaction-manager="txManager"> 
          <tx:attributes> 
                <!-- fix me change requires_new to required with xaexception
--> 
                <tx:method name="*" /> 
          </tx:attributes> 
        </tx:advice> 
      <aop:pointcut id="jmsOperation" 
                                expression="execution(*
nl.our.company.businesslayer.jms.GridMessageListener.onMessage(..))"/>

        <tx:advice id="newTxAdvice" transaction-manager="txManager"> 
           <tx:attributes> 
                    <tx:method name="get*" propagation="REQUIRES_NEW"
read-only="true"/> 
                        <tx:method name="*" propagation="REQUIRES_NEW"/>

           </tx:attributes> 
        </tx:advice> 

        <aop:advisor pointcut-ref="jmsOperation" advice-ref="jmsAdvice"/> 

        <aop:pointcut id="newServiceOperation" 
                    expression="execution(*
nl.ing.cmrm.aiss.businesslayer.services.ExportHistoryService.*(..)) 
                                               
or execution(*
nl.ing.cmrm.aiss.businesslayer.services.NotificationService.*(..))

                                               
or execution(*
nl.ing.cmrm.aiss.businesslayer.services.ProcessInfoService.*(..))

                                               
or execution(*
nl.ing.cmrm.aiss.businesslayer.services.ImporterService.importDelivery(..))

                                               
or execution(*
nl.ing.cmrm.aiss.businesslayer.services.ExporterService.insertExportHistory(..))"/>

      <aop:advisor pointcut-ref="newServiceOperation"
advice-ref="newTxAdvice"/> 

-- 
View this message in context: http://old.nabble.com/ActiveMQ-on-Websphere-REQUIRES_NEW-transactions.-tp27943359p27943359.html
Sent from the ActiveMQ - User mailing list archive at Nabble.com.


Mime
View raw message