11 Replies Latest reply on Jun 21, 2007 7:06 AM by mskonda

    Lookup for JmsXA returning null

    mskonda Apprentice

      Probably a silly question, but couldn't figure out why - I've configured JmsXA to be enlisted in Global Name Space and deployed (see below)

      20070621 09:00:32.333 INFO [main] ConnectionFactoryBindingService.Bound ConnectionManager 'jboss.jca:service=ConnectionFactoryBinding,name=JmsXA' to JNDI name 'JmsXA'(): Bound ConnectionManager 'jboss.jca:service=ConnectionFactoryBinding,name=JmsXA' to JNDI name 'JmsXA'


      However, when I do the lookup for publishing a message, I get the CF as null.

       public void publish3() throws Exception
       {
       Connection conn = null;
       try
       {
       ConnectionFactory fac = (ConnectionFactory) initialContext.lookup("JmsXA");
       logger.info("-->got xa conn fact" + fac);
       conn = fac.createConnection();
       logger.info("-->created conns");
       Session xaSession = conn.createSession(false,
       Session.AUTO_ACKNOWLEDGE);
       logger.info("-->created sessions");
       MessageProducer publisher = xaSession.createProducer(XATEST_QUEUE_1_DEST);
       logger.info("-->created pubishers");
       TextMessage message = xaSession.createTextMessage("Hello!");
       logger.info("-->created txtmsgs");
       publisher.send(message);
       }
       catch (Exception e)
       {
       logger.info("Exception in onMessage() " + e.getMessage());
       }
       finally
       {
       closeConnection(conn);
       }
       }
      


      I can see the JmsXA bound happily in JNDI View, but can't access though. I'm not sure how and why this happens? Any help appreciated!

      /Madhu

        • 1. Re: Lookup for JmsXA returning null
          mskonda Apprentice

          And this is my tx-connection-factory definition:

          <!-- JMS XA Resource adapter, use this to get transacted JMS in beans -->
           <tx-connection-factory>
           <jndi-name>JmsXA</jndi-name>
           <use-java-context>false</use-java-context>
           <xa-transaction/>
           <rar-name>jms-ra.rar</rar-name>
           <connection-definition>org.jboss.resource.adapter.jms.JmsConnectionFactory</connection-definition>
           <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property>
           <config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/DefaultJMSProvider</config-property>
           <max-pool-size>20</max-pool-size>
           <security-domain-and-application>JmsXARealm</security-domain-and-application>
           <depends>jboss.messaging:service=ServerPeer</depends>
           </tx-connection-factory>
          


          • 2. Re: Lookup for JmsXA returning null
            mskonda Apprentice

            BTW, I am accessing the CF from a Stanalone client (and hence JmsXA bound to Global NS)

            • 3. Re: Lookup for JmsXA returning null
              Tim Fox Master

              You can't use the JMS RA outside the VM.

              • 4. Re: Lookup for JmsXA returning null
                Tim Fox Master

                I'm sure there are wiki pages about this somewhere.

                • 5. Re: Lookup for JmsXA returning null
                  mskonda Apprentice

                  Does't say anything here thuogh: http://wiki.jboss.org/wiki/Wiki.jsp?page=ConfigConnectionFactory

                  What I'm trying to achieve is like this:

                  In a standalone client, I need to use UserTransaction to scope JMS and DB work. That is, I need to send a message and update the DB, all in one transaction.

                  If I can't use JmsXA, what is the other way I can enlist these two resoruces in a UserTransaction, Tim?

                  Thanks
                  Madhu

                  • 6. Re: Lookup for JmsXA returning null
                    Tim Fox Master

                    UserTransaction is only available in the java: namespace too (see J2EE spec)

                    In order to run recoverable transactions with different resources (DB and JMS) in a global tx *outside* the application server, you would need to:

                    a) Have a transaction manager
                    b) Have a recovery manager

                    running at the client.
                    The transaction manager would also need to have a trusted, reliable file system where it can log at the client side.

                    So, in other words you would have to recreate half the app sever at the client side to do this - this is almost certainly not something you would want to do.

                    If you want to enlist more than one resource in a global tx - do it on the app server (write an MBean or EJB or Servlet) where the infrastructure already exists to support this.

                    • 7. Re: Lookup for JmsXA returning null
                      Tim Fox Master

                      See the FAQ http://wiki.jboss.org/wiki/Wiki.jsp?page=HowCanIAccessADataSourceFromAClient

                      Note it seems you can access the datasource remotely, but (in bold type) this is not recommended.

                      For one thing, I don't see how transaction enlistment would work, since you'll have no transaction manager on the client side.

                      Anyway, you should ask this on the JCA forum, since this is nothing to do with JBM.

                      • 8. Re: Lookup for JmsXA returning null
                        mskonda Apprentice

                        Hello Tim, this is what I did and it works!!

                        /**
                         * Method that receives the messages on the specific destination and persist
                         * them into a database table all in one transaction.
                         *
                         * If the transction is committed, the message is consumed from the
                         * destination and acknowledged and a row appears in the database.
                         *
                         * If the transaciton is rolled back, the message still apears on the
                         * destination and the row does not get persisted in the database
                         *
                         * @param destination
                         * @param isDurable
                         * @throws Exception
                         */
                         public void receiveAndPersistCommit() throws Exception
                         {
                        
                         /*
                         * Create XAConnection and XASession objects
                         */
                         XAConnection c = jbcf.createXAConnection();
                         XASession xaSession = c.createXASession();
                        
                         /*
                         * Obtain a Messaging (JMS) XA Resource
                         */
                         MessagingXAResource msgRes =
                         (MessagingXAResource) xaSession.getXAResource();
                        
                         /*
                         * Create a sybase resource
                         */
                         SybaseXAResource sybaseRes = new SybaseXAResource();
                         javax.sql.XAConnection sybaseXaConn = sybaseRes.getXAConnection();
                        
                         /*
                         * Obtain a sybase XA Resource
                         */
                         XAResource sybaseXaResource = sybaseXaConn.getXAResource();
                        
                         /*
                         * Strat the transaction manager
                         */
                         tm.begin();
                        
                         /*
                         * Obtain a reference to the transaction object
                         */
                         Transaction tx = tm.getTransaction();
                        
                         logger.info("Enlisting resources");
                        
                         /*
                         * Enlist the resources
                         */
                         tx.enlistResource(msgRes);
                         tx.enlistResource(sybaseXaResource);
                        
                         /*
                         * Start the connection. Unless you start, you won't see messages
                         * being consumedd (usual culprit)
                         */
                         c.start();
                        
                         logger.info("Connection started");
                        
                         /*
                         * Create a message consumer
                         */
                         MessageConsumer mc = xaSession.createConsumer(XATEST_QUEUE_1_DEST);
                        
                         logger.info("Consumer started ");
                        
                         Message msg = mc.receiveNoWait();
                        
                         if (msg != null)
                         {
                         logger.info("Message received: " + ((TextMessage) msg).getText());
                         }
                         else
                         {
                         logger.info("No message");
                         }
                        
                         java.sql.Connection sybaseConn = sybaseXaConn.getConnection();
                         java.sql.Statement stmt = sybaseConn.createStatement();
                        
                         logger.info("Inserting values into table");
                         /*
                         * Execute the insert statement
                         */
                         int i = stmt.executeUpdate("INSERT INTO XATEST VALUES('test-"
                         + System.currentTimeMillis() / 1000 + "')");
                         logger.info("Rows affected: " + i);
                        
                         /*
                         * Unless you commit, the changes are not going to be affected
                         */
                         tx.commit();
                         logger.info("Transaction committed");
                        
                         logger.info("Closing connections");
                         /*
                         * Close all connections
                         */
                         closeConnection(c);
                         sybaseConn.close();
                         }
                        


                        Important to note is - I'm looking a ConnectionFactory but casting it to JBossConnectionFactory to obtain a XAConnection/XASession and hence MessagingResource. Also, I'm using a static method to create a transaction manager as shown below in setUp method:
                        public void setUp()
                         {
                         try
                         {
                         initialContext = new InitialContext();
                         /*
                         * Lookup for ConnectionFactory
                         */
                         jbcf = (JBossConnectionFactory) initialContext
                         .lookup("ConnectionFactory");
                         logger.info("found JBconnection factory: " + jbcf);
                        
                         /*
                         * Create a Transaction Manager
                         */
                        
                         tm = com.arjuna.ats.jta.TransactionManager.transactionManager();
                        
                         /*
                         * Deploy required destinations for this test
                         */
                        
                         deployDestination(XATEST_QUEUE_1);
                        
                         logger.info("Deployed " + XATEST_QUEUE_1);
                        
                         XATEST_QUEUE_1_DEST =
                         (Destination) initialContext.lookup(XATEST_QUEUE_1);
                         deployDestination(XATEST_TOPIC_1);
                        
                         logger.info("Deployed " + XATEST_TOPIC_1);
                         XATEST_TOPIC_1_DEST =
                         (Destination) initialContext.lookup(XATEST_TOPIC_1);
                         }
                         catch (NamingException e)
                         {
                         logger.error("NamingException while looking up cf/tm: "
                         + e.getMessage());
                         }
                         catch (Exception e)
                         {
                         logger.error("Exception in setup: " + e.getMessage());
                         }
                         }
                        


                        The sendAndPerssitCommit works too.

                        Thanks for all your input Tim. Let me know if there's any obvious pitfalls.

                        Thanks
                        Madhu

                        • 9. Re: Lookup for JmsXA returning null
                          Tim Fox Master

                          Well, it appears to work, but be very careful!

                          "mskonda" wrote:
                          Let me know if there's any obvious pitfalls.



                          This is what I said about you could have a transaction manager on the client side, which is what you have done.

                          This is probably a very dodgy thing to do, since you are unlikely to have a trusted or reliable file system on which the transaction is reliably logged.

                          So if the disk fails, or the user deletes the local objectstore after your tx has failed, you are hosed.

                          Also you have no recovery manager, so if the transaction fails mid way through it won't get recovered.

                          So, my advice is not to do this!

                          • 10. Re: Lookup for JmsXA returning null
                            Tim Fox Master

                             

                            "mskonda" wrote:


                            Important to note is - I'm looking a ConnectionFactory but casting it to JBossConnectionFactory to obtain a XAConnection/XASession and hence MessagingResource.


                            Why are you doing that?

                            Why not just lookup the XAConnection factory (at /XAConnectionFactory)?

                            • 11. Re: Lookup for JmsXA returning null
                              mskonda Apprentice

                              Tim, I've changed this to XAConnectionFactory (somewhere I read that XAConnectionFactory is used internal:( - wrong iterpretation, I guess).

                              I do understand the concerns raised, I'm putting forward them.

                              Thanks
                              Madhu