2 Replies Latest reply on Jan 8, 2010 10:03 AM by Bernd Eckenfels

    JmsXA and remote queues

    Robert Lamie Newbie

      Env : JBoss 4.2.3, JbossMQ shipped with Jboss 4.2.3

      Hi all,
      I have a pretty simple question, but dont manage to find the solution through google/forum searchs.

      Inside an MDB, I need to enlist the sending of JMS messages in a JTA transaction. The queue is a remote queue located on another JBossMQ server.
      The need to enlist in a JTA transaction with multiples resources decided me to turn to JmsXA pool.

      Here is the code :

       activationConfig = {...}...
      @PoolClass (value=org.jboss.ejb3.StrictMaxPool.class, maxSize=1, timeout=30000)
      public class Test1MDB implements MessageListener {
       public void onMessage(Message msg) {
       ... do operations on database (XADataSource)
       Context jndi = new InitialContext();
       QueueConnection connection = (QueueConnectionFactory) jndi.lookup("java:JmsXA");
       QueueSession = connection.createQueueSession(true, QueueSession.AUTO_ACKNOWLEDGE);
       Queue queue = (Queue) jndi.lookup("jnp://");
       QueueSender sender = session.createSender(queue);
       ObjectMessage msg = MessageHelper.create(session, messageDTO);

      The result is that code works well if I target a local queue, but fails when I target a remote queue (like in my example). I add that the queues targeted are test queues (created temporarly by the MDB)

      The following logs appear at the end of the onMessage method (commit time) :
      16:53:40,413 WARN [loggerI18N] [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed] [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed] XAResourceRecord.prepare - prepare failed with exception XAException.XAER_RMFAIL
      16:53:40,416 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_50] - Prepare phase of action 7f000101:81ea:4adf0cd5:1255 received heuristic decision: TwoPhaseOutcome.HEURISTIC_HAZARD
      16:53:40,416 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_36] - BasicAction.End() - prepare phase of action-id 7f000101:81ea:4adf0cd5:1255 failed.
      16:53:40,416 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_37] - Received heuristic: TwoPhaseOutcome.HEURISTIC_HAZARD .
      16:53:40,416 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_38] - Action Aborting

      And it chains to replay the same input message, until the following exception occurs :
      16:53:40,449 ERROR [JmsServerSession] org.jboss.resource.adapter.jms.inflow.JmsServerSession@1c7811a failed to commit/rollback
       at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1397)
       at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:135)
       at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)
       at org.jboss.resource.adapter.jms.inflow.JmsServerSession$XATransactionDemarcationStrategy.end(JmsServerSession.java:494)
       at org.jboss.resource.adapter.jms.inflow.JmsServerSession.run(JmsServerSession.java:248)
       at org.jboss.resource.work.WorkWrapper.execute(WorkWrapper.java:204)
       at org.jboss.util.threadpool.BasicTaskWrapper.run(BasicTaskWrapper.java:275)
       at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:756)
       at java.lang.Thread.run(Thread.java:595)

      Strangely, that occurs only for remote queues.
      Any pointers?
      Thank you for your help.

        • 1. Re: JmsXA and remote queues
          Marcelo Leite Newbie

          Hi Robert, how are you?


          A have an issue like yours. My intention is to try to help you in your debug and ask for some help too.


          In my case, i have a simple cenario where i need to enlist a JMS message creation in a JTA transaction. I mean, i have a business process that starts in a MDB that listens a specific queue, this MDB calls a Session Bean that execute some business rules, save data in a database and finally generate another JMS message in a different queue. This last queue is secured, that is, only a special role has privilegies to read/write in this queue. The necessary credencials were provided through ConnectionFactory.createConnection method.


          For that, i have used the java:/JmsXA injected in my Session Bean. Many research sources point to this solution, but in this special case the transaction never commits and an error like yours is always thrown.


          According to the JavaDoc, the XAException is thrown by the Resource Manager (RM) to inform the Transaction Manager of an error encountered by the involved transaction. XAException.XAER_RMFAIL means that the resource manager is unavailable.


          So, after some time double checking my config, i decided to turn on my logging to MQ and JMS (to do that uncomment the specific category block) and discovered the real issue. The user trying to commit the transaction did not have enough privileges to do that.

          This user could be JBossTS? I am not sure.


          To temporaly solve this issue i have removed my queue securing, but it is not what i want in production environment.


          So i ask you. What is the best approach in this case? Is JBossTS the user? If yes, is there any way to authenticate the JBossTS?


          Best Regards, ML

          • 2. Re: JmsXA and remote queues
            Bernd Eckenfels Novice

            If you do not specify an explecite user and credentials on the mcf (which you should not) the user from the current EJB session is used. This could be a "run-as" declarative user on the session bean, or it can be the jaas login user from a client, or in your case it is the default user of the MDB subscription. I think the later is configured somewhere as a JbnossMQ guest on the container configuration.


            BTW: original code looks a bit strange, should be:


            QueueConnectionFactory qcf = (QueueConnectionFactory) ic.lookup("java:comp/env/QueueConnectionFactory");
            QueueConnection connection = qcf.createQueueConnection();


            QueueConnection connection = qcf.createQueueConnection(username, credential);