1 Reply Latest reply: Oct 3, 2012 6:06 PM by Ant Kutschera RSS

Need a XAConnectionFactory for sending messages into HornetQ remotely

Ant Kutschera Newbie

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
    Ant Kutschera Newbie

    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?!