2 Replies Latest reply on Sep 16, 2016 9:31 AM by jbertram

    JMS Bridge Between WildFly 10 Artemis and ActiveMQ 5.14 (ONCE_AND_ONLY_ONCE Quality of Service)

    gregf

      I'm trying to set up a JMS Bridge between Artemis (Running in WildFly 10) and ActiveMQ 5.14

       

      In general the process seems to work smoothly, but unfortunately I'm getting stuck on the XA configuration that is necessary to get ONCE_AND_ONLY_ONCE QoS to work.

       

      Although messages do arrive on the ActiveMQ side, I get the following error in the WildFly log:

       

      11:25:57,920 WARN  [org.apache.activemq.artemis.jms.bridge] (Thread-97) AMQ342009: JMS Bridge failed to send + acknowledge batch, closing JMS objects: javax.jms.IllegalStateException: Not a transacted session

        at org.apache.activemq.ActiveMQSession.commit(ActiveMQSession.java:577)

        at org.apache.activemq.ra.ManagedSessionProxy.commit(ManagedSessionProxy.java:108)

        at org.apache.activemq.artemis.jms.bridge.impl.JMSBridgeImpl.sendBatchNonTransacted(JMSBridgeImpl.java:1291)

        at org.apache.activemq.artemis.jms.bridge.impl.JMSBridgeImpl.sendBatch(JMSBridgeImpl.java:1251)

        at org.apache.activemq.artemis.jms.bridge.impl.JMSBridgeImpl.access$1500(JMSBridgeImpl.java:75)

        at org.apache.activemq.artemis.jms.bridge.impl.JMSBridgeImpl$BatchTimeChecker.run(JMSBridgeImpl.java:1794)

        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

        at java.lang.Thread.run(Thread.java:745)

       

       

      My problem is similar to this one (Wildfly 10 ONCE_AND_ONLY_ONCE JMS bridge ) but unfortunately the solution doesn't totally apply to my situation, because my target is ActiveMQ 5.14.

       

      From all the posts I've read it seems clear that I should ensure that the connection factories for both sides of the bridge should be configured for XA Support. On the Artemis side this seems simple enough: Simply add factory-type="XA_GENERIC" to the definition. However, I'm not able to figure out how to do this on the ActiveMQ side.

       

      Here's the snippet from my standalone-full.xml that specifies my messaging subsystem:

       

              <subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">

                  <server name="default">

                      <security-setting name="#">

                          <role name="guest" delete-non-durable-queue="true" create-non-durable-queue="true" consume="true" send="true"/>

                      </security-setting>

                      <address-setting name="#" message-counter-history-day-limit="10" page-size-bytes="2097152" max-size-bytes="10485760" expiry-address="jms.queue.ExpiryQueue" dead-letter-address="jms.queue.DLQ"/>

                      <http-connector name="http-connector" endpoint="http-acceptor" socket-binding="http"/>

                      <http-connector name="http-connector-throughput" endpoint="http-acceptor-throughput" socket-binding="http">

                          <param name="batch-delay" value="50"/>

                      </http-connector>

                      <in-vm-connector name="in-vm" server-id="0"/>

                      <http-acceptor name="http-acceptor" http-listener="default"/>

                      <http-acceptor name="http-acceptor-throughput" http-listener="default">

                          <param name="batch-delay" value="50"/>

                          <param name="direct-deliver" value="false"/>

                      </http-acceptor>

                      <in-vm-acceptor name="in-vm" server-id="0"/>

                      <jms-queue name="ExpiryQueue" entries="java:/jms/queue/ExpiryQueue"/>

                      <jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>

                      <jms-queue name="NonBridgedTestQueue" entries="java:jboss/exported/jms/queue/nonBridgedTestQueue"/>

                      <jms-queue name="BridgedTestQueue" entries="java:jboss/exported/jms/queue/bridgedTestQueue"/>

                      <connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/>

                      <connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="http-connector"/>

                      <connection-factory name="InVmXAConnectionFactory" factory-type="XA_GENERIC" entries="java:/XAConnectionFactory" connectors="in-vm"/>              

                      <pooled-connection-factory name="activemq-ra" transaction="xa" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm"/>

                  </server>

                  <jms-bridge name="simple-jms-bridge" add-messageID-in-header="true" max-batch-time="100" max-batch-size="10" max-retries="5" failure-retry-interval="10000" quality-of-service="ONCE_AND_ONLY_ONCE">

                      <source destination="jboss/exported/jms/queue/bridgedTestQueue" connection-factory="java:/XAConnectionFactory"/>

                      <target destination="jboss/activemq/queue/bridgedTestQueue" connection-factory="AMQConnectionFactory"/>

                  </jms-bridge>

              </subsystem>

       

      For the ActiveMQ definition I've used a Resource Adapter, defined as follows:

       

              <subsystem xmlns="urn:jboss:domain:resource-adapters:4.0">

                  <resource-adapters>

                      <resource-adapter id="activemq">

                          <archive>activemq-rar-5.14.0.rar</archive>

                          <transaction-support>XATransaction</transaction-support>

                          <config-property name="ServerUrl">tcp://localhost:61616?jms.rmIdFromConnectionId=true</config-property>

                          <config-property name="UserName">admin</config-property>

                          <config-property name="UseInboundSession">false</config-property>

                          <config-property name="Password">admin</config-property>

                          <connection-definitions>

                              <connection-definition class-name="org.apache.activemq.ra.ActiveMQManagedConnectionFactory" jndi-name="java:/AMQConnectionFactory" enabled="true" pool-name="AMQConnectionFactory">

                                  <xa-pool>

                                      <min-pool-size>1</min-pool-size>

                                      <max-pool-size>20</max-pool-size>

                                      <prefill>false</prefill>

                                      <is-same-rm-override>false</is-same-rm-override>

                                  </xa-pool>

                              </connection-definition>

                          </connection-definitions>

                          <admin-objects>

                              <admin-object class-name="org.apache.activemq.command.ActiveMQTopic" jndi-name="java:jboss/activemq/topic/TestTopic" use-java-context="true" pool-name="TestTopic">

                                  <config-property name="PhysicalName">

                                      activemq/topic/TestTopic

                                  </config-property>

                              </admin-object>

                              <admin-object class-name="org.apache.activemq.command.ActiveMQQueue" jndi-name="java:jboss/activemq/queue/TestQueue" use-java-context="true" pool-name="TestQueue">

                                  <config-property name="PhysicalName">

                                      activemq/queue/TestQueue

                                  </config-property>

                              </admin-object>

                              <admin-object class-name="org.apache.activemq.command.ActiveMQQueue" jndi-name="java:jboss/activemq/queue/bridgedTestQueue" use-java-context="true" pool-name="BridgedTestQueue">

                                  <config-property name="PhysicalName">

                                      activemq/queue/bridgedTestQueue

                                  </config-property>

                              </admin-object>

                          </admin-objects>

                      </resource-adapter>

                  </resource-adapters>

              </subsystem>

       

      Some pointers in the right direction will be appreciated

       

      Greg

        • 1. Re: JMS Bridge Between WildFly 10 Artemis and ActiveMQ 5.14 (ONCE_AND_ONLY_ONCE Quality of Service)
          gregf

          After posting this question I tried something that seems to have worked. Would still be interested to hear if this is the correct approach though.

           

          When looking at the ra.xml file in the resource adapter I noticed that it offers an additional connection factory as an admin object. So I added the following to the Resource Adapter definition in standalone-full.xml:

           

                                  <admin-object class-name="org.apache.activemq.ActiveMQXAConnectionFactory" jndi-name="java:jboss/activemq/activeMQXAConnectionFactory" use-java-context="true">

                                      <config-property name="brokerURL">

                                          tcp://localhost:61616?jms.rmIdFromConnectionId=true

                                      </config-property>

                                  </admin-object>

           

          Using this Connection Factory I then updated the JMS Bridge as follows:

           

                      <jms-bridge name="simple-jms-bridge" add-messageID-in-header="true" max-batch-time="100" max-batch-size="10" max-retries="5" failure-retry-interval="10000" quality-of-service="ONCE_AND_ONLY_ONCE">

                          <source destination="jboss/exported/jms/queue/bridgedTestQueue" connection-factory="java:/XAConnectionFactory"/>

                          <target destination="jboss/activemq/queue/bridgedTestQueue" connection-factory="java:jboss/activemq/activeMQXAConnectionFactory"/>

                      </jms-bridge>

           

          Now all seems to work well. Messages arrive on the ActiveMQ side and I'm not getting any issues in the WildFly log. Whoopwhoop

          • 2. Re: JMS Bridge Between WildFly 10 Artemis and ActiveMQ 5.14 (ONCE_AND_ONLY_ONCE Quality of Service)
            jbertram

            There's absolutely no need to use the ActiveMQ JCA RA with the JMS bridge, and I would argue doing so creates extra work and unnecessary complexity. 

             

            Think of the JMS bridge just like any remote JMS client.  All it needs to connect to any remote JMS provide is the right client libraries and JNDI look-up information (i.e. initial context properties, JNDI look-up names for connection factory and destination).  There is a perfect example of this in the Wildfly documentation.  Just create a module with the ActiveMQ JMS client libraries and then configure the bridge with the appropriate initial context properties and JNDI names for connection factory and destination.  It should be really straight-forward.

             

            You can read more at WildFly HornetQ jms bridge to ActiveMQ.