1 Reply Latest reply on Oct 3, 2012 6:06 PM by maxant

    Need a XAConnectionFactory for sending messages into HornetQ remotely

    maxant

      If I use the following code, I get a org.hornetq.jms.client.HornetQJMSConnectionFactory which doesn't implement the XAConnectionFactory interface, even though it has methods like createXAConnection().

       

      val JNDI_FACTORY = "org.jboss.naming.remote.client.InitialContextFactory"

      val JMS_FACTORY = "jms/RemoteConnectionFactory"

      val QUEUE = "jms/queue/ticketValidation"

      val env = new Hashtable[String, String]()

      env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);

      env.put(Context.PROVIDER_URL, "remote://localhost:4447");

      env.put(Context.SECURITY_PRINCIPAL, "ticketValidation");

      env.put(Context.SECURITY_CREDENTIALS, "password");

      val ctx = new InitialContext(env)

      //val qcf = ctx.lookup(JMS_FACTORY).asInstanceOf[QueueConnectionFactory]

       

      (sorry its scala, but should be readalbe by java folk)

       

      Because that factory doesn't implement XAConnectionFactory, I can't enlist it into an XA transaction using Bitronix on the calling side (which is a server written with scala & Play!)

       

      Is it worth creating a bug for this, or is there a reason its not an instanceof XAConnectionFactory, even though it has methods like createXAConnection?

       

      Just to make it clear, I'm trying to write to a database and send a JMS message to JBoss within an XA transaction.  The message server is hosted inside JBoss.

       

      Alternatively, can I create the QueueConnectionFactory myself rather than looking it up in the remote JNDI (which is hosted in JBoss)?  If so, how do I tell it where the message server is (its URL)?

       

      Thanks,

      Ant

        • 1. Re: Need a XAConnectionFactory for sending messages into HornetQ remotely
          maxant

          I took a look at the source of the JNDI wrapper out of Bitronix and came up with the following XAConnectionFactory:

           

          package ch.maxant.scalabook.btm

           

           

          import java.util.Hashtable

          import javax.naming.InitialContext

          import javax.naming.Context

          import scala.reflect.BeanProperty

          import javax.jms.XAConnectionFactory

           

           

          class HornetQXAConnectionFactory extends XAConnectionFactory {

           

           

              lazy val qcf = {

                              val JNDI_FACTORY = "org.jboss.naming.remote.client.InitialContextFactory"

                              val env = new Hashtable[String, String]()

                              env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);

                              env.put(Context.PROVIDER_URL, providerUrl)

                              env.put(Context.SECURITY_PRINCIPAL, securityPrincipal)

                              env.put(Context.SECURITY_CREDENTIALS, securityCredentials)

                              val ctx = new InitialContext(env)

                              val qcf = ctx.lookup(name).asInstanceOf[org.hornetq.jms.client.HornetQJMSConnectionFactory]

                              qcf

              }

           

           

              @BeanProperty

              var name = ""

           

           

              @BeanProperty

                    var providerUrl = ""

           

           

              @BeanProperty

                    var securityPrincipal = ""

           

           

              @BeanProperty

                    var securityCredentials = ""

           

                    @BeanProperty

                    var forceSecurity = true

                 

              def createXAQueueConnection = {

                  if(forceSecurity){

                      qcf.createXAQueueConnection(securityPrincipal, securityCredentials)

                  }else{

                            qcf.createXAQueueConnection

                  }

              }

           

           

              def createXAQueueConnection(username:String, password:String) = {

                        qcf.createXAQueueConnection(securityPrincipal, securityCredentials)

              }

             

                    def createXAConnection = {

                  if(forceSecurity){

                            qcf.createXAConnection(securityPrincipal, securityCredentials)

                  }else{

                            qcf.createXAConnection

                  }

                    }

           

                    def createXAConnection(username:String, password:String) = {

                        qcf.createXAConnection(securityPrincipal, securityCredentials)

                    }

           

              def createQueueConnection = {

                  if(forceSecurity){

                            qcf.createQueueConnection(securityPrincipal, securityCredentials)

                  }else{

                            qcf.createQueueConnection

                  }

              }

           

           

              def createQueueConnection(username:String, password:String) = {

                              qcf.createQueueConnection(securityPrincipal, securityCredentials)

                    }

           

                    def createConnection = {

                        if(forceSecurity){

                                  qcf.createConnection(securityPrincipal, securityCredentials)

                        }else{

                                  qcf.createConnection

                        }

                    }

           

                    def createConnection(username:String, password:String) = {

                              qcf.createConnection(securityPrincipal, securityCredentials)

                    }

          }

           

           

          The bitronix JNDI resource config to go with it is:

           

           

          # bind configured resources to JNDI

          bitronix.tm.resource.bind=true

           

          ...

           

          resource.mq1.className=ch.maxant.scalabook.btm.HornetQXAConnectionFactory

          resource.mq1.uniqueName=jms/maxant/scalabook/ticketvalidations

          resource.mq1.minPoolSize=2

          resource.mq1.maxPoolSize=5

          resource.mq1.driverProperties.name=jms/RemoteConnectionFactory

          resource.mq1.driverProperties.providerUrl=remote://localhost:4447

          resource.mq1.driverProperties.securityPrincipal=ticketValidation

          resource.mq1.driverProperties.securityCredentials=password

          resource.mq1.driverProperties.forceSecurity=true

           

           

          It appears to work well, although I haven't tested all the failure test cases.

           

          I'm still interested in hearing how come the connection factory pulled out of the Context doesnt implement XAConnectionFactory, even though its got all the methods.  Surely that is a bug?!